gnome-session r4731 - in branches/dbus_based: . gnome-session



Author: mccann
Date: Thu Jun 12 21:23:31 2008
New Revision: 4731
URL: http://svn.gnome.org/viewvc/gnome-session?rev=4731&view=rev

Log:
2008-06-12  William Jon McCann  <jmccann redhat com>

	* gnome-session/gsm-client-store.c (gsm_client_store_size),
	(gsm_client_store_lookup), (_has_client_id),
	(gsm_client_store_add), (gsm_client_store_set_locked),
	(gsm_client_store_set_property), (gsm_client_store_get_property),
	(gsm_client_store_class_init):
	* gnome-session/gsm-client-store.h:
	* gnome-session/gsm-client.c (gsm_client_set_status),
	(gsm_client_set_client_id), (gsm_client_set_property),
	(gsm_client_get_property), (_boolean_handled_accumulator),
	(gsm_client_class_init), (gsm_client_get_client_id),
	(gsm_client_stop), (gsm_client_manage_request),
	(gsm_client_logout_request):
	* gnome-session/gsm-client.h:
	* gnome-session/gsm-manager.c (_find_by_client_id),
	(app_condition_changed), (on_store_client_added),
	(gsm_manager_set_client_store), (_stop_client), (manager_shutdown),
	(_shutdown_client), (initiate_shutdown):
	* gnome-session/gsm-marshal.list:
	* gnome-session/gsm-xsmp-client.c (client_iochannel_watch),
	(client_protocol_timeout), (find_property), (set_description),
	(setup_connection), (gsm_xsmp_client_constructor),
	(gsm_xsmp_client_init), (delete_property), (debug_print_property),
	(set_properties_callback), (delete_properties_callback),
	(get_properties_callback), (prop_to_command),
	(xsmp_get_restart_command), (xsmp_get_discard_command),
	(xsmp_get_autorestart), (xsmp_restart), (do_save_yourself),
	(xsmp_save_yourself), (xsmp_save_yourself_phase2), (xsmp_interact),
	(xsmp_shutdown_cancelled), (xsmp_stop),
	(gsm_client_set_ice_connection), (gsm_xsmp_client_set_property),
	(gsm_xsmp_client_get_property), (gsm_xsmp_client_finalize),
	(gsm_xsmp_client_class_init), (gsm_xsmp_client_new),
	(register_client_callback), (save_yourself_request_callback),
	(save_yourself_phase2_request_callback),
	(interact_request_callback), (interact_done_callback),
	(save_yourself_done_callback), (close_connection_callback),
	(gsm_xsmp_client_connect):
	* gnome-session/gsm-xsmp-client.h:
	* gnome-session/gsm-xsmp-server.c (accept_ice_connection):
	Give the code another whacking.



Modified:
   branches/dbus_based/ChangeLog
   branches/dbus_based/gnome-session/gsm-client-store.c
   branches/dbus_based/gnome-session/gsm-client-store.h
   branches/dbus_based/gnome-session/gsm-client.c
   branches/dbus_based/gnome-session/gsm-client.h
   branches/dbus_based/gnome-session/gsm-manager.c
   branches/dbus_based/gnome-session/gsm-marshal.list
   branches/dbus_based/gnome-session/gsm-xsmp-client.c
   branches/dbus_based/gnome-session/gsm-xsmp-client.h
   branches/dbus_based/gnome-session/gsm-xsmp-server.c

Modified: branches/dbus_based/gnome-session/gsm-client-store.c
==============================================================================
--- branches/dbus_based/gnome-session/gsm-client-store.c	(original)
+++ branches/dbus_based/gnome-session/gsm-client-store.c	Thu Jun 12 21:23:31 2008
@@ -38,6 +38,7 @@
 struct GsmClientStorePrivate
 {
         GHashTable *clients;
+        gboolean    locked;
 };
 
 enum {
@@ -46,11 +47,16 @@
         LAST_SIGNAL
 };
 
+enum {
+        PROP_0,
+        PROP_LOCKED,
+};
+
 static guint signals [LAST_SIGNAL] = { 0, };
 
 static void     gsm_client_store_class_init    (GsmClientStoreClass *klass);
 static void     gsm_client_store_init          (GsmClientStore      *client_store);
-static void     gsm_client_store_finalize      (GObject              *object);
+static void     gsm_client_store_finalize      (GObject             *object);
 
 G_DEFINE_TYPE (GsmClientStore, gsm_client_store, G_TYPE_OBJECT)
 
@@ -65,6 +71,12 @@
         return ret;
 }
 
+guint
+gsm_client_store_size (GsmClientStore    *store)
+{
+        return g_hash_table_size (store->priv->clients);
+}
+
 void
 gsm_client_store_clear (GsmClientStore    *store)
 {
@@ -125,6 +137,21 @@
         return client;
 }
 
+GsmClient *
+gsm_client_store_lookup (GsmClientStore    *store,
+                         const char        *id)
+{
+        GsmClient *client;
+
+        g_return_val_if_fail (store != NULL, NULL);
+        g_return_val_if_fail (id != NULL, NULL);
+
+        client = g_hash_table_lookup (store->priv->clients,
+                                      id);
+
+        return client;
+}
+
 guint
 gsm_client_store_foreach_remove (GsmClientStore    *store,
                                  GsmClientStoreFunc func,
@@ -142,22 +169,95 @@
         return ret;
 }
 
-void
+static gboolean
+_has_client_id (const char *id,
+                GsmClient  *client,
+                gpointer    user_data)
+{
+        const char *sm_id_a;
+        const char *sm_id_b;
+
+        sm_id_a = user_data;
+        sm_id_b = gsm_client_get_client_id (client);
+        if (sm_id_b == NULL) {
+                return FALSE;
+        }
+        return (strcmp (sm_id_a, sm_id_b) == 0);
+}
+
+gboolean
 gsm_client_store_add (GsmClientStore *store,
                       GsmClient      *client)
 {
-        char *id;
+        const char *id;
 
-        g_return_if_fail (store != NULL);
-        g_return_if_fail (client != NULL);
+        g_return_val_if_fail (store != NULL, FALSE);
+        g_return_val_if_fail (client != NULL, FALSE);
 
         id = gsm_client_get_id (client);
 
+        /* If we're shutting down, we don't accept any new session
+           clients. */
+        if (store->priv->locked) {
+                return FALSE;
+        }
+
         g_debug ("GsmClientStore: Adding client %s to store", id);
 
         g_hash_table_insert (store->priv->clients,
-                             id,
+                             g_strdup (id),
                              g_object_ref (client));
+
+        return TRUE;
+}
+
+static void
+gsm_client_store_set_locked (GsmClientStore *store,
+                             gboolean        locked)
+{
+        g_return_if_fail (GSM_IS_CLIENT_STORE (store));
+
+        store->priv->locked = locked;
+}
+
+static void
+gsm_client_store_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+        GsmClientStore *self;
+
+        self = GSM_CLIENT_STORE (object);
+
+        switch (prop_id) {
+        case PROP_LOCKED:
+                gsm_client_store_set_locked (self, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gsm_client_store_get_property (GObject    *object,
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+        GsmClientStore *self;
+
+        self = GSM_CLIENT_STORE (object);
+
+        switch (prop_id) {
+        case PROP_LOCKED:
+                g_value_set_boolean (value, self->priv->locked);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
 }
 
 static void
@@ -165,6 +265,8 @@
 {
         GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
+        object_class->get_property = gsm_client_store_get_property;
+        object_class->set_property = gsm_client_store_set_property;
         object_class->finalize = gsm_client_store_finalize;
 
         signals [CLIENT_ADDED] =
@@ -187,6 +289,13 @@
                               g_cclosure_marshal_VOID__STRING,
                               G_TYPE_NONE,
                               1, G_TYPE_STRING);
+        g_object_class_install_property (object_class,
+                                         PROP_LOCKED,
+                                         g_param_spec_boolean ("locked",
+                                                               NULL,
+                                                               NULL,
+                                                               FALSE,
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
         g_type_class_add_private (klass, sizeof (GsmClientStorePrivate));
 }

Modified: branches/dbus_based/gnome-session/gsm-client-store.h
==============================================================================
--- branches/dbus_based/gnome-session/gsm-client-store.h	(original)
+++ branches/dbus_based/gnome-session/gsm-client-store.h	Thu Jun 12 21:23:31 2008
@@ -49,7 +49,7 @@
         void          (* client_added)    (GsmClientStore *client_store,
                                            const char      *id);
         void          (* client_removed)  (GsmClientStore *client_store,
-                                            const char      *id);
+                                           const char      *id);
 } GsmClientStoreClass;
 
 typedef enum
@@ -68,7 +68,8 @@
 
 GsmClientStore *    gsm_client_store_new                      (void);
 
-void                gsm_client_store_add                      (GsmClientStore    *store,
+guint               gsm_client_store_size                     (GsmClientStore    *store);
+gboolean            gsm_client_store_add                      (GsmClientStore    *store,
                                                                GsmClient         *client);
 void                gsm_client_store_clear                    (GsmClientStore    *store);
 gboolean            gsm_client_store_remove                   (GsmClientStore    *store,
@@ -82,6 +83,8 @@
 GsmClient *         gsm_client_store_find                     (GsmClientStore    *store,
                                                                GsmClientStoreFunc predicate,
                                                                gpointer           user_data);
+GsmClient *         gsm_client_store_lookup                   (GsmClientStore    *store,
+                                                               const char        *id);
 
 
 G_END_DECLS

Modified: branches/dbus_based/gnome-session/gsm-client.c
==============================================================================
--- branches/dbus_based/gnome-session/gsm-client.c	(original)
+++ branches/dbus_based/gnome-session/gsm-client.c	Thu Jun 12 21:23:31 2008
@@ -32,17 +32,27 @@
 struct GsmClientPrivate
 {
         char *id;
+        char *client_id;
+        int   status;
 };
 
 enum {
+        PROP_0,
+        PROP_ID,
+        PROP_CLIENT_ID,
+        PROP_STATUS,
+};
+
+enum {
+        MANAGE_REQUEST,
+        LOGOUT_REQUEST,
+
         SAVED_STATE,
         REQUEST_PHASE2,
         REQUEST_INTERACTION,
         INTERACTION_DONE,
         SAVE_YOURSELF_DONE,
         DISCONNECTED,
-        REGISTER_CLIENT,
-        REQUEST_LOGOUT,
         LAST_SIGNAL
 };
 
@@ -108,14 +118,122 @@
         g_free (client->priv->id);
 }
 
+void
+gsm_client_set_status (GsmClient *client,
+                       int        status)
+{
+        g_return_if_fail (GSM_IS_CLIENT (client));
+        if (client->priv->status != status) {
+                client->priv->status = status;
+                g_object_notify (G_OBJECT (client), "status");
+        }
+}
+
+static void
+gsm_client_set_client_id (GsmClient  *client,
+                          const char *client_id)
+{
+        g_return_if_fail (GSM_IS_CLIENT (client));
+
+        g_free (client->priv->client_id);
+
+        client->priv->client_id = g_strdup (client_id);
+        g_object_notify (G_OBJECT (client), "client-id");
+}
+
+static void
+gsm_client_set_property (GObject       *object,
+                         guint          prop_id,
+                         const GValue  *value,
+                         GParamSpec    *pspec)
+{
+        GsmClient *self;
+
+        self = GSM_CLIENT (object);
+
+        switch (prop_id) {
+        case PROP_CLIENT_ID:
+                gsm_client_set_client_id (self, g_value_get_string (value));
+                break;
+        case PROP_STATUS:
+                gsm_client_set_status (self, g_value_get_int (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gsm_client_get_property (GObject    *object,
+                         guint       prop_id,
+                         GValue     *value,
+                         GParamSpec *pspec)
+{
+        GsmClient *self;
+
+        self = GSM_CLIENT (object);
+
+        switch (prop_id) {
+        case PROP_CLIENT_ID:
+                g_value_set_string (value, self->priv->client_id);
+                break;
+        case PROP_STATUS:
+                g_value_set_int (value, self->priv->status);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static gboolean
+_boolean_handled_accumulator (GSignalInvocationHint *ihint,
+                              GValue                *return_accu,
+                              const GValue          *handler_return,
+                              gpointer               dummy)
+{
+        gboolean    continue_emission;
+        gboolean    signal_handled;
+
+        signal_handled = g_value_get_boolean (handler_return);
+        g_value_set_boolean (return_accu, signal_handled);
+        continue_emission = !signal_handled;
+
+        return continue_emission;
+}
+
 static void
 gsm_client_class_init (GsmClientClass *klass)
 {
         GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+        object_class->get_property = gsm_client_get_property;
+        object_class->set_property = gsm_client_set_property;
         object_class->constructor = gsm_client_constructor;
         object_class->finalize = gsm_client_finalize;
 
+        signals[MANAGE_REQUEST] =
+                g_signal_new ("manage-request",
+                              G_OBJECT_CLASS_TYPE (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GsmClientClass, manage_request),
+                              _boolean_handled_accumulator,
+                              NULL,
+                              gsm_marshal_BOOLEAN__POINTER,
+                              G_TYPE_BOOLEAN,
+                              1, G_TYPE_POINTER);
+        signals[LOGOUT_REQUEST] =
+                g_signal_new ("logout-request",
+                              G_OBJECT_CLASS_TYPE (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GsmClientClass, logout_request),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__BOOLEAN,
+                              G_TYPE_NONE,
+                              1, G_TYPE_BOOLEAN);
+
         signals[SAVED_STATE] =
                 g_signal_new ("saved_state",
                               G_OBJECT_CLASS_TYPE (object_class),
@@ -175,24 +293,23 @@
                               g_cclosure_marshal_VOID__VOID,
                               G_TYPE_NONE,
                               0);
-        signals[REGISTER_CLIENT] =
-                g_signal_new ("register-client",
-                              G_OBJECT_CLASS_TYPE (object_class),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GsmClientClass, register_client),
-                              NULL, NULL,
-                              gsm_marshal_STRING__STRING,
-                              G_TYPE_STRING,
-                              1, G_TYPE_STRING);
-        signals[REQUEST_LOGOUT] =
-                g_signal_new ("request-logout",
-                              G_OBJECT_CLASS_TYPE (object_class),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GsmClientClass, request_logout),
-                              NULL, NULL,
-                              g_cclosure_marshal_VOID__BOOLEAN,
-                              G_TYPE_NONE,
-                              0);
+
+        g_object_class_install_property (object_class,
+                                         PROP_CLIENT_ID,
+                                         g_param_spec_string ("client-id",
+                                                              "client-id",
+                                                              "client-id",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+        g_object_class_install_property (object_class,
+                                         PROP_STATUS,
+                                         g_param_spec_uint ("status",
+                                                            "status",
+                                                            "status",
+                                                            0,
+                                                            G_MAXINT,
+                                                            0,
+                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
         g_type_class_add_private (klass, sizeof (GsmClientPrivate));
 }
@@ -211,23 +328,7 @@
 {
         g_return_val_if_fail (GSM_IS_CLIENT (client), NULL);
 
-        return GSM_CLIENT_GET_CLASS (client)->get_client_id (client);
-}
-
-pid_t
-gsm_client_get_pid (GsmClient *client)
-{
-        g_return_val_if_fail (GSM_IS_CLIENT (client), -1);
-
-        return GSM_CLIENT_GET_CLASS (client)->get_pid (client);
-}
-
-char *
-gsm_client_get_desktop_file (GsmClient *client)
-{
-        g_return_val_if_fail (GSM_IS_CLIENT (client), NULL);
-
-        return GSM_CLIENT_GET_CLASS (client)->get_desktop_file (client);
+        return client->priv->client_id;
 }
 
 char *
@@ -302,11 +403,11 @@
 }
 
 void
-gsm_client_die (GsmClient *client)
+gsm_client_stop (GsmClient *client)
 {
         g_return_if_fail (GSM_IS_CLIENT (client));
 
-        GSM_CLIENT_GET_CLASS (client)->die (client);
+        GSM_CLIENT_GET_CLASS (client)->stop (client);
 }
 
 void
@@ -345,17 +446,22 @@
         g_signal_emit (client, signals[DISCONNECTED], 0);
 }
 
-void
-gsm_client_register_client (GsmClient  *client,
-                            const char *previous_id,
-                            char      **id)
+
+gboolean
+gsm_client_manage_request (GsmClient *client,
+                           char     **client_idp)
 {
-        g_signal_emit (client, signals[REGISTER_CLIENT], 0, previous_id, id);
+        gboolean res;
+
+        res = FALSE;
+        g_signal_emit (client, signals[MANAGE_REQUEST], 0, client_idp, &res);
+
+        return res;
 }
 
 void
-gsm_client_request_logout (GsmClient  *client,
-                           gboolean    prompt)
+gsm_client_logout_request (GsmClient *client,
+                           gboolean   prompt)
 {
-        g_signal_emit (client, signals[REQUEST_LOGOUT], 0, prompt);
+        g_signal_emit (client, signals[LOGOUT_REQUEST], 0, prompt);
 }

Modified: branches/dbus_based/gnome-session/gsm-client.h
==============================================================================
--- branches/dbus_based/gnome-session/gsm-client.h	(original)
+++ branches/dbus_based/gnome-session/gsm-client.h	Thu Jun 12 21:23:31 2008
@@ -38,6 +38,13 @@
 
 typedef struct GsmClientPrivate GsmClientPrivate;
 
+typedef enum {
+        GSM_CLIENT_UNMANAGED = 0,
+        GSM_CLIENT_MANAGED,
+        GSM_CLIENT_FINISHED,
+        GSM_CLIENT_FAILED,
+} GsmClientStatus;
+
 struct _GsmClient
 {
         GObject           parent;
@@ -49,11 +56,11 @@
         GObjectClass parent_class;
 
         /* signals */
-        void (*register_client)      (GsmClient  *client,
-                                      const char *previous_id,
-                                      char      **id);
-        void (*request_logout)       (GsmClient  *client,
-                                      gboolean    prompt);
+        gboolean (*manage_request)   (GsmClient *client,
+                                      char     **client_id);
+        gboolean (*logout_request)   (GsmClient *client,
+                                      gboolean   prompt);
+
 
         void (*saved_state)          (GsmClient *client);
 
@@ -68,9 +75,9 @@
         void (*disconnected)         (GsmClient *client);
 
         /* virtual methods */
-        const char * (*get_client_id)       (GsmClient *client);
-        pid_t        (*get_pid)             (GsmClient *client);
-        char       * (*get_desktop_file)    (GsmClient *client);
+        void (*stop)                 (GsmClient *client);
+
+
         char       * (*get_restart_command) (GsmClient *client);
         char       * (*get_discard_command) (GsmClient *client);
         gboolean     (*get_autorestart)     (GsmClient *client);
@@ -82,46 +89,52 @@
         void (*save_yourself_phase2) (GsmClient *client);
         void (*interact)             (GsmClient *client);
         void (*shutdown_cancelled)   (GsmClient *client);
-        void (*die)                  (GsmClient *client);
 };
 
 GType       gsm_client_get_type             (void) G_GNUC_CONST;
 
-const char *gsm_client_get_id               (GsmClient *client);
-const char *gsm_client_get_client_id        (GsmClient *client);
+const char *gsm_client_get_id               (GsmClient  *client);
+const char *gsm_client_get_client_id        (GsmClient  *client);
+int         gsm_client_get_status           (GsmClient  *client);
+void        gsm_client_set_status           (GsmClient  *client,
+                                             int         status);
+
+gboolean    gsm_client_manage               (GsmClient  *client,
+                                             const char *client_id);
+void        gsm_client_stop                 (GsmClient  *client);
 
-pid_t       gsm_client_get_pid              (GsmClient *client);
-char       *gsm_client_get_desktop_file     (GsmClient *client);
-char       *gsm_client_get_restart_command  (GsmClient *client);
-char       *gsm_client_get_discard_command  (GsmClient *client);
-gboolean    gsm_client_get_autorestart      (GsmClient *client);
-
-void        gsm_client_save_state           (GsmClient *client);
-
-void        gsm_client_restart              (GsmClient *client,
-                                             GError   **error);
-void        gsm_client_save_yourself        (GsmClient *client,
-                                             gboolean   save_state);
-void        gsm_client_save_yourself_phase2 (GsmClient *client);
-void        gsm_client_interact             (GsmClient *client);
-void        gsm_client_shutdown_cancelled   (GsmClient *client);
-void        gsm_client_die                  (GsmClient *client);
 
-/* protected */
-void        gsm_client_saved_state          (GsmClient *client);
-void        gsm_client_request_phase2       (GsmClient *client);
-void        gsm_client_request_interaction  (GsmClient *client);
-void        gsm_client_interaction_done     (GsmClient *client,
-                                             gboolean   cancel_shutdown);
-void        gsm_client_save_yourself_done   (GsmClient *client);
-void        gsm_client_disconnected         (GsmClient *client);
 
-void        gsm_client_register_client      (GsmClient  *client,
-                                             const char *previous_id,
+char       *gsm_client_get_restart_command  (GsmClient  *client);
+char       *gsm_client_get_discard_command  (GsmClient  *client);
+gboolean    gsm_client_get_autorestart      (GsmClient  *client);
+
+void        gsm_client_save_state           (GsmClient  *client);
+
+void        gsm_client_restart              (GsmClient  *client,
+                                             GError    **error);
+void        gsm_client_save_yourself        (GsmClient  *client,
+                                             gboolean    save_state);
+void        gsm_client_save_yourself_phase2 (GsmClient  *client);
+void        gsm_client_interact             (GsmClient  *client);
+void        gsm_client_shutdown_cancelled   (GsmClient  *client);
+
+/* protected */
+gboolean    gsm_client_manage_request       (GsmClient  *client,
                                              char      **id);
-void        gsm_client_request_logout       (GsmClient  *client,
+void        gsm_client_logout_request       (GsmClient  *client,
                                              gboolean    prompt);
 
+
+void        gsm_client_saved_state          (GsmClient  *client);
+void        gsm_client_request_phase2       (GsmClient  *client);
+void        gsm_client_request_interaction  (GsmClient  *client);
+void        gsm_client_interaction_done     (GsmClient  *client,
+                                             gboolean    cancel_shutdown);
+void        gsm_client_save_yourself_done   (GsmClient  *client);
+void        gsm_client_disconnected         (GsmClient  *client);
+
+
 G_END_DECLS
 
 #endif /* __GSM_CLIENT_H__ */

Modified: branches/dbus_based/gnome-session/gsm-manager.c
==============================================================================
--- branches/dbus_based/gnome-session/gsm-manager.c	(original)
+++ branches/dbus_based/gnome-session/gsm-manager.c	Thu Jun 12 21:23:31 2008
@@ -78,8 +78,6 @@
         guint                   timeout_id;
         GSList                 *pending_apps;
 
-        /* SM clients */
-        GSList                 *clients;
 
         /* When shutdown starts, all clients are put into shutdown_clients.
          * If they request phase2, they are moved from shutdown_clients to
@@ -141,24 +139,31 @@
         return ret;
 }
 
+static gboolean
+_find_by_client_id (const char *id,
+                    GsmClient  *client,
+                    const char *client_id_a)
+{
+        const char *client_id_b;
+
+        client_id_b = gsm_client_get_client_id (client);
+        if (client_id_b == NULL) {
+                return FALSE;
+        }
+
+        return (strcmp (client_id_a, client_id_b) == 0);
+}
+
 static void
 app_condition_changed (GsmApp     *app,
                        gboolean    condition,
                        GsmManager *manager)
 {
-        GsmClient  *client;
-        GSList     *cl;
-
-        client = NULL;
+        GsmClient *client;
 
-        /* Check for an existing session client for this app */
-        for (cl = manager->priv->clients; cl; cl = cl->next) {
-                GsmClient *c = GSM_CLIENT (cl->data);
-
-                if (!strcmp (app->client_id, gsm_client_get_id (c))) {
-                        client = c;
-                }
-        }
+        client = gsm_client_store_find (manager->priv->store,
+                                        (GsmClientStoreFunc)_find_by_client_id,
+                                        app->client_id);
 
         if (condition) {
                 GError *error = NULL;
@@ -178,7 +183,11 @@
                  * be automatically restarted by adding the client to
                  * condition_clients */
                 manager->priv->condition_clients = g_slist_prepend (manager->priv->condition_clients, client);
-                gsm_client_die (client);
+
+                /* FIXME: this should probably do gsm_app_stop
+                 */
+
+                gsm_client_stop (client);
                 app->pid = -1;
         }
 }
@@ -412,6 +421,14 @@
 }
 
 static void
+on_store_client_added (GsmClientStore *store,
+                       const char     *id,
+                       GsmManager     *manager)
+{
+        g_debug ("GsmManager: Client added: %s", id);
+}
+
+static void
 gsm_manager_set_client_store (GsmManager     *manager,
                               GsmClientStore *store)
 {
@@ -422,10 +439,21 @@
         }
 
         if (manager->priv->store != NULL) {
+                g_signal_handlers_disconnect_by_func (manager->priv->store,
+                                                      on_store_client_added,
+                                                      manager);
+
                 g_object_unref (manager->priv->store);
         }
 
         manager->priv->store = store;
+
+        if (manager->priv->store != NULL) {
+                g_signal_connect (manager->priv->store,
+                                  "client-added",
+                                  G_CALLBACK (on_store_client_added),
+                                  manager);
+        }
 }
 
 static void
@@ -945,18 +973,26 @@
         return TRUE;
 }
 
+static gboolean
+_stop_client (const char *id,
+              GsmClient  *client,
+              gpointer    data)
+{
+        gsm_client_stop (client);
+
+        return FALSE;
+}
+
 static void
 manager_shutdown (GsmManager *manager)
 {
-        GSList *cl;
-
         /* Emit session over signal */
         g_signal_emit (manager, signals[SESSION_OVER], 0);
 
         /* FIXME: do this in reverse phase order */
-        for (cl = manager->priv->clients; cl; cl = cl->next) {
-                gsm_client_die (cl->data);
-        }
+        gsm_client_store_foreach (manager->priv->store,
+                                  (GsmClientStoreFunc)_stop_client,
+                                  NULL);
 
         switch (manager->priv->logout_response_id) {
         case GSM_LOGOUT_RESPONSE_SHUTDOWN:
@@ -971,24 +1007,30 @@
         }
 }
 
+static gboolean
+_shutdown_client (const char *id,
+                  GsmClient  *client,
+                  GsmManager *manager)
+{
+        manager->priv->shutdown_clients = g_slist_prepend (manager->priv->shutdown_clients, client);
+
+        gsm_client_save_yourself (client, FALSE);
+
+        return FALSE;
+}
+
 static void
 initiate_shutdown (GsmManager *manager)
 {
-        GSList *cl;
-
         manager->priv->phase = GSM_MANAGER_PHASE_SHUTDOWN;
 
-        if (manager->priv->clients == NULL) {
+        if (gsm_client_store_size (manager->priv->store) == 0) {
                 manager_shutdown (manager);
         }
 
-        for (cl = manager->priv->clients; cl; cl = cl->next) {
-                GsmClient *client = GSM_CLIENT (cl->data);
-
-                manager->priv->shutdown_clients = g_slist_prepend (manager->priv->shutdown_clients, client);
-
-                gsm_client_save_yourself (client, FALSE);
-        }
+        gsm_client_store_foreach (manager->priv->store,
+                                  (GsmClientStoreFunc)_shutdown_client,
+                                  NULL);
 }
 
 static void

Modified: branches/dbus_based/gnome-session/gsm-marshal.list
==============================================================================
--- branches/dbus_based/gnome-session/gsm-marshal.list	(original)
+++ branches/dbus_based/gnome-session/gsm-marshal.list	Thu Jun 12 21:23:31 2008
@@ -1 +1 @@
-STRING:STRING
+BOOLEAN:POINTER

Modified: branches/dbus_based/gnome-session/gsm-xsmp-client.c
==============================================================================
--- branches/dbus_based/gnome-session/gsm-xsmp-client.c	(original)
+++ branches/dbus_based/gnome-session/gsm-xsmp-client.c	Thu Jun 12 21:23:31 2008
@@ -35,134 +35,49 @@
 /* FIXME */
 #define GsmDesktopFile "_Gsm_DesktopFile"
 
-static gboolean client_iochannel_watch  (GIOChannel   *channel,
-                                         GIOCondition  condition,
-                                         gpointer      data);
-static gboolean client_protocol_timeout (gpointer      data);
-
-static void set_description (GsmXSMPClient *xsmp);
-
-static const char *xsmp_get_client_id       (GsmClient *client);
-static pid_t       xsmp_get_pid             (GsmClient *client);
-static char       *xsmp_get_desktop_file    (GsmClient *client);
-static char       *xsmp_get_restart_command (GsmClient *client);
-static char       *xsmp_get_discard_command (GsmClient *client);
-static gboolean    xsmp_get_autorestart     (GsmClient *client);
-
-static void xsmp_finalize             (GObject   *object);
-static void xsmp_restart              (GsmClient *client,
-                                       GError   **error);
-static void xsmp_save_yourself        (GsmClient *client,
-                                       gboolean   save_state);
-static void xsmp_save_yourself_phase2 (GsmClient *client);
-static void xsmp_interact             (GsmClient *client);
-static void xsmp_shutdown_cancelled   (GsmClient *client);
-static void xsmp_die                  (GsmClient *client);
+#define GSM_XSMP_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientPrivate))
 
-G_DEFINE_TYPE (GsmXSMPClient, gsm_xsmp_client, GSM_TYPE_CLIENT)
-
-static void
-gsm_xsmp_client_init (GsmXSMPClient *xsmp)
-{
-        ;
-}
-
-static void
-gsm_xsmp_client_class_init (GsmXSMPClientClass *klass)
-{
-        GObjectClass *object_class = G_OBJECT_CLASS (klass);
-        GsmClientClass *client_class = GSM_CLIENT_CLASS (klass);
-
-        object_class->finalize             = xsmp_finalize;
-
-        client_class->get_client_id        = xsmp_get_client_id;
-        client_class->get_pid              = xsmp_get_pid;
-        client_class->get_desktop_file     = xsmp_get_desktop_file;
-        client_class->get_restart_command  = xsmp_get_restart_command;
-        client_class->get_discard_command  = xsmp_get_discard_command;
-        client_class->get_autorestart      = xsmp_get_autorestart;
-
-        client_class->restart              = xsmp_restart;
-        client_class->save_yourself        = xsmp_save_yourself;
-        client_class->save_yourself_phase2 = xsmp_save_yourself_phase2;
-        client_class->interact             = xsmp_interact;
-        client_class->shutdown_cancelled   = xsmp_shutdown_cancelled;
-        client_class->die                  = xsmp_die;
-}
-
-GsmXSMPClient *
-gsm_xsmp_client_new (IceConn ice_conn)
-{
-        GsmXSMPClient *xsmp;
-        GIOChannel *channel;
-        int fd;
-
-        xsmp = g_object_new (GSM_TYPE_XSMP_CLIENT, NULL);
-        xsmp->props = g_ptr_array_new ();
-
-        xsmp->ice_conn = ice_conn;
-        xsmp->current_save_yourself = -1;
-        xsmp->next_save_yourself = -1;
-
-        fd = IceConnectionNumber (ice_conn);
-        fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC);
-
-        channel = g_io_channel_unix_new (fd);
-        xsmp->watch_id = g_io_add_watch (channel, G_IO_IN | G_IO_ERR,
-                                         client_iochannel_watch, xsmp);
-        g_io_channel_unref (channel);
-
-        xsmp->protocol_timeout = g_timeout_add (5000, client_protocol_timeout, xsmp);
-
-        set_description (xsmp);
-        g_debug ("New client '%s'", xsmp->description);
-
-        return xsmp;
-}
-
-static void
-xsmp_finalize (GObject *object)
+struct GsmXSMPClientPrivate
 {
-        GsmXSMPClient *xsmp = (GsmXSMPClient *) object;
 
-        g_debug ("xsmp_finalize (%s)", xsmp->description);
+        SmsConn    conn;
+        IceConn    ice_connection;
 
-        if (xsmp->watch_id) {
-                g_source_remove (xsmp->watch_id);
-        }
+        guint      watch_id;
+        guint      protocol_timeout;
 
-        if (xsmp->conn) {
-                SmsCleanUp (xsmp->conn);
-        } else {
-                IceCloseConnection (xsmp->ice_conn);
-        }
+        int        current_save_yourself;
+        int        next_save_yourself;
+        char      *id;
+        char      *description;
+        GPtrArray *props;
+};
 
-        if (xsmp->protocol_timeout)
-                g_source_remove (xsmp->protocol_timeout);
+enum {
+        PROP_0,
+        PROP_ICE_CONNECTION,
+};
 
-        G_OBJECT_CLASS (gsm_xsmp_client_parent_class)->finalize (object);
-}
+G_DEFINE_TYPE (GsmXSMPClient, gsm_xsmp_client, GSM_TYPE_CLIENT)
 
 static gboolean
-client_iochannel_watch (GIOChannel   *channel,
-                        GIOCondition  condition,
-                        gpointer      data)
+client_iochannel_watch (GIOChannel    *channel,
+                        GIOCondition   condition,
+                        GsmXSMPClient *client)
 {
-        GsmClient *client = data;
-        GsmXSMPClient *xsmp = data;
 
-        switch (IceProcessMessages (xsmp->ice_conn, NULL, NULL)) {
+        switch (IceProcessMessages (client->priv->ice_connection, NULL, NULL)) {
         case IceProcessMessagesSuccess:
                 return TRUE;
 
         case IceProcessMessagesIOError:
-                g_debug ("IceProcessMessagesIOError on '%s'", xsmp->description);
-                gsm_client_disconnected (client);
+                g_debug ("IceProcessMessagesIOError on '%s'", client->priv->description);
+                gsm_client_disconnected (GSM_CLIENT (client));
                 return FALSE;
 
         case IceProcessMessagesConnectionClosed:
                 g_debug ("IceProcessMessagesConnectionClosed on '%s'",
-                         xsmp->description);
+                         client->priv->description);
                 return FALSE;
 
         default:
@@ -174,319 +89,146 @@
  * the XSMP protocol setup.
  */
 static gboolean
-client_protocol_timeout (gpointer data)
+client_protocol_timeout (GsmXSMPClient *client)
 {
-        GsmClient *client = data;
-        GsmXSMPClient *xsmp = data;
-
         g_debug ("client_protocol_timeout for client '%s' in ICE status %d",
-                 xsmp->description, IceConnectionStatus (xsmp->ice_conn));
-        gsm_client_disconnected (client);
-
-        return FALSE;
-}
-
-static Status
-register_client_callback (SmsConn    conn,
-                          SmPointer  manager_data,
-                          char      *previous_id)
-{
-        GsmClient *client = manager_data;
-        GsmXSMPClient *xsmp = manager_data;
-        char *id;
-
-        g_debug ("Client '%s' received RegisterClient(%s)",
-                 xsmp->description,
-                 previous_id ? previous_id : "NULL");
-
-        id = NULL;
-        gsm_client_register_client (client, previous_id, &id);
-
-        if (id == NULL) {
-                g_debug ("  rejected: invalid previous_id");
-                free (previous_id);
-                return FALSE;
-        }
-
-        xsmp->id = id;
-
-        set_description (xsmp);
-
-        g_debug ("Sending RegisterClientReply to '%s'", xsmp->description);
-
-        SmsRegisterClientReply (conn, xsmp->id);
-
-        if (!previous_id) {
-                /* Send the initial SaveYourself. */
-                g_debug ("Sending initial SaveYourself");
-                SmsSaveYourself (conn, SmSaveLocal, False, SmInteractStyleNone, False);
-                xsmp->current_save_yourself = SmSaveLocal;
+                 client->priv->description,
+                 IceConnectionStatus (client->priv->ice_connection));
 
-                free (previous_id);
-        }
+        gsm_client_disconnected (GSM_CLIENT (client));
 
-        return TRUE;
+        return FALSE;
 }
 
-static void
-do_save_yourself (GsmXSMPClient *xsmp, int save_type)
+static SmProp *
+find_property (GsmXSMPClient *client,
+               const char    *name,
+               int           *index)
 {
-        if (xsmp->next_save_yourself != -1) {
-                /* Either we're currently doing a shutdown and there's a checkpoint
-                 * queued after it, or vice versa. Either way, the new SaveYourself
-                 * is redundant.
-                 */
-                g_debug ("  skipping redundant SaveYourself for '%s'",
-                         xsmp->description);
-        }
-        else if (xsmp->current_save_yourself != -1) {
-                g_debug ("  queuing new SaveYourself for '%s'",
-                         xsmp->description);
-                xsmp->next_save_yourself = save_type;
-        } else {
-                xsmp->current_save_yourself = save_type;
+        SmProp *prop;
+        int i;
 
-                switch (save_type) {
-                case SmSaveLocal:
-                        /* Save state */
-                        SmsSaveYourself (xsmp->conn, SmSaveLocal, FALSE,
-                                         SmInteractStyleNone, FALSE);
-                        break;
+        for (i = 0; i < client->priv->props->len; i++) {
+                prop = client->priv->props->pdata[i];
 
-                default:
-                        /* Logout */
-                        SmsSaveYourself (xsmp->conn, save_type, TRUE,
-                                         SmInteractStyleAny, FALSE);
-                        break;
+                if (!strcmp (prop->name, name)) {
+                        if (index) {
+                                *index = i;
+                        }
+                        return prop;
                 }
         }
+
+        return NULL;
 }
 
 static void
-save_yourself_request_callback (SmsConn   conn,
-                                SmPointer manager_data,
-                                int       save_type,
-                                Bool      shutdown,
-                                int       interact_style,
-                                Bool      fast,
-                                Bool      global)
+set_description (GsmXSMPClient *client)
 {
-        GsmXSMPClient *xsmp = manager_data;
-
-        g_debug ("Client '%s' received SaveYourselfRequest(%s, %s, %s, %s, %s)",
-                 xsmp->description,
-                 save_type == SmSaveLocal ? "SmSaveLocal" :
-                 save_type == SmSaveGlobal ? "SmSaveGlobal" : "SmSaveBoth",
-                 shutdown ? "Shutdown" : "!Shutdown",
-                 interact_style == SmInteractStyleAny ? "SmInteractStyleAny" :
-                 interact_style == SmInteractStyleErrors ? "SmInteractStyleErrors" :
-                 "SmInteractStyleNone", fast ? "Fast" : "!Fast",
-                 global ? "Global" : "!Global");
+        SmProp     *prop;
+        const char *id;
 
-        /* Examining the g_debug above, you can see that there are a total
-         * of 72 different combinations of options that this could have been
-         * called with. However, most of them are stupid.
-         *
-         * If @shutdown and @global are both TRUE, that means the caller is
-         * requesting that a logout message be sent to all clients, so we do
-         * that. We use @fast to decide whether or not to show a
-         * confirmation dialog. (This isn't really what @fast is for, but
-         * the old gnome-session and ksmserver both interpret it that way,
-         * so we do too.) We ignore @save_type because we pick the correct
-         * save_type ourselves later based on user prefs, dialog choices,
-         * etc, and we ignore @interact_style, because clients have not used
-         * it correctly consistently enough to make it worth honoring.
-         *
-         * If @shutdown is TRUE and @global is FALSE, the caller is
-         * confused, so we ignore the request.
-         *
-         * If @shutdown is FALSE and @save_type is SmSaveGlobal or
-         * SmSaveBoth, then the client wants us to ask some or all open
-         * applications to save open files to disk, but NOT quit. This is
-         * silly and so we ignore the request.
-         *
-         * If @shutdown is FALSE and @save_type is SmSaveLocal, then the
-         * client wants us to ask some or all open applications to update
-         * their current saved state, but not log out. At the moment, the
-         * code only supports this for the !global case (ie, a client
-         * requesting that it be allowed to update *its own* saved state,
-         * but not having everyone else update their saved state).
-         */
+        prop = find_property (client, SmProgram, NULL);
+        id = gsm_client_get_client_id (GSM_CLIENT (client));
 
-        if (shutdown && global) {
-                g_debug ("  initiating shutdown");
-                gsm_client_request_logout (GSM_CLIENT (xsmp),
-                                           !fast);
-        } else if (!shutdown && !global) {
-                g_debug ("  initiating checkpoint");
-                do_save_yourself (xsmp, SmSaveLocal);
+        g_free (client->priv->description);
+        if (prop) {
+                client->priv->description = g_strdup_printf ("%p [%.*s %s]",
+                                                             client,
+                                                             prop->vals[0].length,
+                                                             (char *)prop->vals[0].value,
+                                                             id);
+        } else if (id != NULL) {
+                client->priv->description = g_strdup_printf ("%p [%s]", client, id);
         } else {
-                g_debug ("  ignoring");
+                client->priv->description = g_strdup_printf ("%p", client);
         }
 }
 
 static void
-xsmp_restart (GsmClient *client, GError **error)
-{
-        char *restart_cmd = gsm_client_get_restart_command (client);
-
-        g_spawn_command_line_async (restart_cmd, error);
-
-        g_free (restart_cmd);
-}
-
-static void
-xsmp_save_yourself (GsmClient *client, gboolean save_state)
-{
-        GsmXSMPClient *xsmp = (GsmXSMPClient *)client;
-
-        g_debug ("xsmp_save_yourself ('%s', %s)", xsmp->description,
-                 save_state ? "True" : "False");
-
-        do_save_yourself (xsmp, save_state ? SmSaveBoth : SmSaveGlobal);
-}
-
-static void
-save_yourself_phase2_request_callback (SmsConn   conn,
-                                       SmPointer manager_data)
-{
-        GsmClient *client = manager_data;
-        GsmXSMPClient *xsmp = manager_data;
-
-        g_debug ("Client '%s' received SaveYourselfPhase2Request",
-                 xsmp->description);
-
-        if (xsmp->current_save_yourself == SmSaveLocal)
-                {
-                        /* WTF? Anyway, if it's checkpointing, it doesn't have to wait
-                         * for anyone else.
-                         */
-                        SmsSaveYourselfPhase2 (xsmp->conn);
-                }
-        else
-                gsm_client_request_phase2 (client);
-}
-
-static void
-xsmp_save_yourself_phase2 (GsmClient *client)
-{
-        GsmXSMPClient *xsmp = (GsmXSMPClient *)client;
-
-        g_debug ("xsmp_save_yourself_phase2 ('%s')", xsmp->description);
-
-        SmsSaveYourselfPhase2 (xsmp->conn);
-}
-
-static void
-interact_request_callback (SmsConn   conn,
-                           SmPointer manager_data,
-                           int       dialog_type)
+setup_connection (GsmXSMPClient *client)
 {
-        GsmClient *client = manager_data;
-        GsmXSMPClient *xsmp = manager_data;
+        GIOChannel    *channel;
+        int            fd;
 
-        g_debug ("Client '%s' received InteractRequest(%s)", xsmp->description,
-                 dialog_type == SmInteractStyleAny ? "Any" : "Errors");
-
-        gsm_client_request_interaction (client);
-}
-
-static void
-xsmp_interact (GsmClient *client)
-{
-        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
+        fd = IceConnectionNumber (client->priv->ice_connection);
+        fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC);
+        channel = g_io_channel_unix_new (fd);
+        client->priv->watch_id = g_io_add_watch (channel,
+                                                 G_IO_IN | G_IO_ERR,
+                                                 (GIOFunc)client_iochannel_watch,
+                                                 client);
+        g_io_channel_unref (channel);
 
-        g_debug ("xsmp_interact ('%s')", xsmp->description);
+        client->priv->protocol_timeout = g_timeout_add (5000,
+                                                        (GSourceFunc)client_protocol_timeout,
+                                                        client);
 
-        SmsInteract (xsmp->conn);
+        set_description (client);
+        g_debug ("New client '%s'", client->priv->description);
 }
 
-static void
-interact_done_callback (SmsConn   conn,
-                        SmPointer manager_data,
-                        Bool      cancel_shutdown)
+static GObject *
+gsm_xsmp_client_constructor (GType                  type,
+                             guint                  n_construct_properties,
+                             GObjectConstructParam *construct_properties)
 {
-        GsmClient *client = manager_data;
-        GsmXSMPClient *xsmp = manager_data;
+        GsmXSMPClient *client;
 
-        g_debug ("Client '%s' received InteractDone(cancel_shutdown = %s)",
-                 xsmp->description, cancel_shutdown ? "True" : "False");
+        client = GSM_XSMP_CLIENT (G_OBJECT_CLASS (gsm_xsmp_client_parent_class)->constructor (type,
+                                                                                              n_construct_properties,
+                                                                                              construct_properties));
+        setup_connection (client);
 
-        gsm_client_interaction_done (client, cancel_shutdown);
+        return G_OBJECT (client);
 }
 
 static void
-xsmp_shutdown_cancelled (GsmClient *client)
+gsm_xsmp_client_init (GsmXSMPClient *client)
 {
-        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
+        client->priv = GSM_XSMP_CLIENT_GET_PRIVATE (client);
 
-        g_debug ("xsmp_shutdown_cancelled ('%s')", xsmp->description);
-
-        SmsShutdownCancelled (xsmp->conn);
+        client->priv->props = g_ptr_array_new ();
+        client->priv->current_save_yourself = -1;
+        client->priv->next_save_yourself = -1;
 }
 
-static void
-xsmp_die (GsmClient *client)
-{
-        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
-
-        g_debug ("xsmp_die ('%s')", xsmp->description);
-
-        SmsDie (xsmp->conn);
-}
 
 static void
-save_yourself_done_callback (SmsConn   conn,
-                             SmPointer manager_data,
-                             Bool      success)
+delete_property (GsmXSMPClient *client,
+                 const char    *name)
 {
-        GsmClient *client = manager_data;
-        GsmXSMPClient *xsmp = manager_data;
-
-        g_debug ("Client '%s' received SaveYourselfDone(success = %s)",
-                 xsmp->description, success ? "True" : "False");
-
-        if (xsmp->current_save_yourself == SmSaveLocal) {
-                xsmp->current_save_yourself = -1;
-                SmsSaveComplete (xsmp->conn);
-                gsm_client_saved_state (client);
-        } else {
-                xsmp->current_save_yourself = -1;
-                gsm_client_save_yourself_done (client);
-        }
-
-        if (xsmp->next_save_yourself) {
-                int save_type = xsmp->next_save_yourself;
+        int     index;
+        SmProp *prop;
 
-                xsmp->next_save_yourself = -1;
-                do_save_yourself (xsmp, save_type);
+        prop = find_property (client, name, &index);
+        if (!prop) {
+                return;
         }
-}
-
-static void
-close_connection_callback (SmsConn     conn,
-                           SmPointer   manager_data,
-                           int         count,
-                           char      **reason_msgs)
-{
-        GsmClient *client = manager_data;
-        GsmXSMPClient *xsmp = manager_data;
-        int i;
 
-        g_debug ("Client '%s' received CloseConnection", xsmp->description);
-        for (i = 0; i < count; i++) {
-                g_debug (" close reason: '%s'", reason_msgs[i]);
+#if 0
+        /* This is wrong anyway; we can't unconditionally run the current
+         * discard command; if this client corresponds to a GsmAppResumed,
+         * and the current discard command is identical to the app's
+         * discard_command, then we don't run the discard command now,
+         * because that would delete a saved state we may want to resume
+         * again later.
+         */
+        if (!strcmp (name, SmDiscardCommand)) {
+                gsm_client_run_discard (GSM_CLIENT (client));
         }
-        SmFreeReasons (count, reason_msgs);
+#endif
 
-        gsm_client_disconnected (client);
+        g_ptr_array_remove_index_fast (client->priv->props, index);
+        SmFreeProperty (prop);
 }
 
+
 static void
 debug_print_property (SmProp *prop)
 {
         GString *tmp;
-        int i;
+        int      i;
 
         switch (prop->type[0]) {
         case 'C': /* CARD8 */
@@ -513,53 +255,6 @@
         }
 }
 
-static SmProp *
-find_property (GsmXSMPClient *client, const char *name, int *index)
-{
-        SmProp *prop;
-        int i;
-
-        for (i = 0; i < client->props->len; i++) {
-                prop = client->props->pdata[i];
-
-                if (!strcmp (prop->name, name)) {
-                        if (index) {
-                                *index = i;
-                        }
-                        return prop;
-                }
-        }
-
-        return NULL;
-}
-
-static void
-delete_property (GsmXSMPClient *client, const char *name)
-{
-        int index;
-        SmProp *prop;
-
-        prop = find_property (client, name, &index);
-        if (!prop) {
-                return;
-        }
-
-#if 0
-        /* This is wrong anyway; we can't unconditionally run the current
-         * discard command; if this client corresponds to a GsmAppResumed,
-         * and the current discard command is identical to the app's
-         * discard_command, then we don't run the discard command now,
-         * because that would delete a saved state we may want to resume
-         * again later.
-         */
-        if (!strcmp (name, SmDiscardCommand)) {
-                gsm_client_run_discard (client);
-        }
-#endif
-
-        g_ptr_array_remove_index_fast (client->props, index);
-        SmFreeProperty (prop);
-}
 
 static void
 set_properties_callback (SmsConn     conn,
@@ -568,13 +263,13 @@
                          SmProp    **props)
 {
         GsmXSMPClient *client = manager_data;
-        int i;
+        int            i;
 
-        g_debug ("Set properties from client '%s'", client->description);
+        g_debug ("Set properties from client '%s'", client->priv->description);
 
         for (i = 0; i < num_props; i++) {
                 delete_property (client, props[i]->name);
-                g_ptr_array_add (client->props, props[i]);
+                g_ptr_array_add (client->priv->props, props[i]);
 
                 debug_print_property (props[i]);
 
@@ -595,7 +290,7 @@
         GsmXSMPClient *client = manager_data;
         int i;
 
-        g_debug ("Delete properties from '%s'", client->description);
+        g_debug ("Delete properties from '%s'", client->priv->description);
 
         for (i = 0; i < num_props; i++) {
                 delete_property (client, prop_names[i]);
@@ -612,47 +307,11 @@
 {
         GsmXSMPClient *client = manager_data;
 
-        g_debug ("Get properties request from '%s'", client->description);
-
-        SmsReturnProperties (conn, client->props->len,
-                             (SmProp **)client->props->pdata);
-}
-
-static const char *
-xsmp_get_client_id (GsmClient *client)
-{
-        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
-
-        return xsmp->id;
-}
-
-static pid_t
-xsmp_get_pid (GsmClient *client)
-{
-        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
-        SmProp *prop = find_property (xsmp, SmProcessID, NULL);
-        char buf[32];
-
-        if (!prop || strcmp (prop->type, SmARRAY8) != 0) {
-                return (pid_t)-1;
-        }
+        g_debug ("Get properties request from '%s'", client->priv->description);
 
-        /* prop->vals[0].value might not be '\0'-terminated... */
-        g_strlcpy (buf, prop->vals[0].value, MIN (prop->vals[0].length, sizeof (buf)));
-        return (pid_t)strtoul (buf, NULL, 10);
-}
-
-static char *
-xsmp_get_desktop_file (GsmClient *client)
-{
-        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
-        SmProp *prop = find_property (xsmp, GsmDesktopFile, NULL);
-
-        if (!prop || strcmp (prop->type, SmARRAY8) != 0) {
-                return NULL;
-        }
-
-        return g_strndup (prop->vals[0].value, prop->vals[0].length);
+        SmsReturnProperties (conn,
+                             client->priv->props->len,
+                             (SmProp **)client->priv->props->pdata);
 }
 
 static char *
@@ -679,7 +338,9 @@
                 }
 
                 if (!need_quotes) {
-                        g_string_append_printf (str, "%.*s", prop->vals[i].length,
+                        g_string_append_printf (str,
+                                                "%.*s",
+                                                prop->vals[i].length,
                                                 (char *)prop->vals[i].value);
                 } else {
                         g_string_append_c (str, '\'');
@@ -701,8 +362,9 @@
 static char *
 xsmp_get_restart_command (GsmClient *client)
 {
-        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
-        SmProp *prop = find_property (xsmp, SmRestartCommand, NULL);
+        SmProp *prop;
+
+        prop = find_property (GSM_XSMP_CLIENT (client), SmRestartCommand, NULL);
 
         if (!prop || strcmp (prop->type, SmLISTofARRAY8) != 0) {
                 return NULL;
@@ -714,8 +376,9 @@
 static char *
 xsmp_get_discard_command (GsmClient *client)
 {
-        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
-        SmProp *prop = find_property (xsmp, SmDiscardCommand, NULL);
+        SmProp *prop;
+
+        prop = find_property (GSM_XSMP_CLIENT (client), SmDiscardCommand, NULL);
 
         if (!prop || strcmp (prop->type, SmLISTofARRAY8) != 0) {
                 return NULL;
@@ -727,8 +390,9 @@
 static gboolean
 xsmp_get_autorestart (GsmClient *client)
 {
-        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
-        SmProp *prop = find_property (xsmp, SmRestartStyleHint, NULL);
+        SmProp *prop;
+
+        prop = find_property (GSM_XSMP_CLIENT (client), SmRestartStyleHint, NULL);
 
         if (!prop || strcmp (prop->type, SmCARD8) != 0) {
                 return FALSE;
@@ -738,21 +402,436 @@
 }
 
 static void
-set_description (GsmXSMPClient *client)
+xsmp_restart (GsmClient *client,
+              GError   **error)
 {
-        SmProp *prop = find_property (client, SmProgram, NULL);
+        char *restart_cmd;
 
-        g_free (client->description);
-        if (prop) {
-                client->description = g_strdup_printf ("%p [%.*s %s]", client,
-                                                       prop->vals[0].length,
-                                                       (char *)prop->vals[0].value,
-                                                       client->id);
-        } else if (client->id) {
-                client->description = g_strdup_printf ("%p [%s]", client, client->id);
+        restart_cmd = gsm_client_get_restart_command (client);
+
+        g_spawn_command_line_async (restart_cmd, error);
+
+        g_free (restart_cmd);
+}
+
+static void
+do_save_yourself (GsmXSMPClient *client,
+                  int            save_type)
+{
+        if (client->priv->next_save_yourself != -1) {
+                /* Either we're currently doing a shutdown and there's a checkpoint
+                 * queued after it, or vice versa. Either way, the new SaveYourself
+                 * is redundant.
+                 */
+                g_debug ("  skipping redundant SaveYourself for '%s'",
+                         client->priv->description);
+        } else if (client->priv->current_save_yourself != -1) {
+                g_debug ("  queuing new SaveYourself for '%s'",
+                         client->priv->description);
+                client->priv->next_save_yourself = save_type;
+        } else {
+                client->priv->current_save_yourself = save_type;
+
+                switch (save_type) {
+                case SmSaveLocal:
+                        /* Save state */
+                        SmsSaveYourself (client->priv->conn,
+                                         SmSaveLocal,
+                                         FALSE,
+                                         SmInteractStyleNone,
+                                         FALSE);
+                        break;
+
+                default:
+                        /* Logout */
+                        SmsSaveYourself (client->priv->conn,
+                                         save_type,
+                                         TRUE,
+                                         SmInteractStyleAny,
+                                         FALSE);
+                        break;
+                }
+        }
+}
+
+static void
+xsmp_save_yourself (GsmClient *client,
+                    gboolean   save_state)
+{
+        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
+
+        g_debug ("xsmp_save_yourself ('%s', %s)",
+                 xsmp->priv->description,
+                 save_state ? "True" : "False");
+
+        do_save_yourself (xsmp, save_state ? SmSaveBoth : SmSaveGlobal);
+}
+
+static void
+xsmp_save_yourself_phase2 (GsmClient *client)
+{
+        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
+
+        g_debug ("xsmp_save_yourself_phase2 ('%s')", xsmp->priv->description);
+
+        SmsSaveYourselfPhase2 (xsmp->priv->conn);
+}
+
+static void
+xsmp_interact (GsmClient *client)
+{
+        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
+
+        g_debug ("xsmp_interact ('%s')", xsmp->priv->description);
+
+        SmsInteract (xsmp->priv->conn);
+}
+
+
+static void
+xsmp_shutdown_cancelled (GsmClient *client)
+{
+        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
+
+        g_debug ("xsmp_shutdown_cancelled ('%s')", xsmp->priv->description);
+
+        SmsShutdownCancelled (xsmp->priv->conn);
+}
+
+static void
+xsmp_stop (GsmClient *client)
+{
+        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
+
+        g_debug ("xsmp_die ('%s')", xsmp->priv->description);
+
+        SmsDie (xsmp->priv->conn);
+}
+
+static void
+gsm_client_set_ice_connection (GsmXSMPClient *client,
+                               gpointer       conn)
+{
+        client->priv->ice_connection = conn;
+}
+
+static void
+gsm_xsmp_client_set_property (GObject       *object,
+                              guint          prop_id,
+                              const GValue  *value,
+                              GParamSpec    *pspec)
+{
+        GsmXSMPClient *self;
+
+        self = GSM_XSMP_CLIENT (object);
+
+        switch (prop_id) {
+        case PROP_ICE_CONNECTION:
+                gsm_client_set_ice_connection (self, g_value_get_pointer (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gsm_xsmp_client_get_property (GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+        GsmXSMPClient *self;
+
+        self = GSM_XSMP_CLIENT (object);
+
+        switch (prop_id) {
+        case PROP_ICE_CONNECTION:
+                g_value_set_pointer (value, self->priv->ice_connection);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gsm_xsmp_client_finalize (GObject *object)
+{
+        GsmXSMPClient *client = (GsmXSMPClient *) object;
+
+        g_debug ("xsmp_finalize (%s)", client->priv->description);
+
+        if (client->priv->watch_id) {
+                g_source_remove (client->priv->watch_id);
+        }
+
+        if (client->priv->conn) {
+                SmsCleanUp (client->priv->conn);
+        } else {
+                IceCloseConnection (client->priv->ice_connection);
+        }
+
+        if (client->priv->protocol_timeout) {
+                g_source_remove (client->priv->protocol_timeout);
+        }
+
+        G_OBJECT_CLASS (gsm_xsmp_client_parent_class)->finalize (object);
+}
+
+static void
+gsm_xsmp_client_class_init (GsmXSMPClientClass *klass)
+{
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+        GsmClientClass *client_class = GSM_CLIENT_CLASS (klass);
+
+        object_class->finalize             = gsm_xsmp_client_finalize;
+        object_class->constructor          = gsm_xsmp_client_constructor;
+        object_class->get_property         = gsm_xsmp_client_get_property;
+        object_class->set_property         = gsm_xsmp_client_set_property;
+
+        g_object_class_install_property (object_class,
+                                         PROP_ICE_CONNECTION,
+                                         g_param_spec_pointer ("ice-connection",
+                                                               "ice-connection",
+                                                               "ice-connection",
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+        client_class->get_restart_command  = xsmp_get_restart_command;
+        client_class->get_discard_command  = xsmp_get_discard_command;
+        client_class->get_autorestart      = xsmp_get_autorestart;
+
+        client_class->stop                 = xsmp_stop;
+        client_class->restart              = xsmp_restart;
+        client_class->save_yourself        = xsmp_save_yourself;
+        client_class->save_yourself_phase2 = xsmp_save_yourself_phase2;
+        client_class->interact             = xsmp_interact;
+        client_class->shutdown_cancelled   = xsmp_shutdown_cancelled;
+}
+
+GsmClient *
+gsm_xsmp_client_new (IceConn ice_conn)
+{
+        GsmXSMPClient *xsmp;
+
+        xsmp = g_object_new (GSM_TYPE_XSMP_CLIENT,
+                             "ice-connection", ice_conn,
+                             NULL);
+
+        return GSM_CLIENT (xsmp);
+}
+
+static Status
+register_client_callback (SmsConn    conn,
+                          SmPointer  manager_data,
+                          char      *previous_id)
+{
+        GsmXSMPClient *client = manager_data;
+        gboolean       handled;
+        char          *id;
+
+        g_debug ("Client '%s' received RegisterClient(%s)",
+                 client->priv->description,
+                 previous_id ? previous_id : "NULL");
+
+
+        /* There are three cases:
+         * 1. id is NULL - we'll use a new one
+         * 2. id is known - we'll use known one
+         * 3. id is unknown - this is an error
+         */
+        id = g_strdup (previous_id);
+        handled = gsm_client_manage_request (GSM_CLIENT (client), &id);
+        if (! handled) {
+                g_debug (" RegisterClient not handled!");
+                g_free (id);
+                free (previous_id);
+                return FALSE;
+        }
+
+        if (id == NULL) {
+                g_debug ("  rejected: invalid previous_id");
+                free (previous_id);
+                return FALSE;
+        }
+
+        g_object_set (client, "client-id", id, NULL);
+
+        set_description (client);
+
+        g_debug ("Sending RegisterClientReply to '%s'", client->priv->description);
+
+        SmsRegisterClientReply (conn, id);
+
+        if (previous_id == NULL) {
+                /* Send the initial SaveYourself. */
+                g_debug ("Sending initial SaveYourself");
+                SmsSaveYourself (conn, SmSaveLocal, False, SmInteractStyleNone, False);
+                client->priv->current_save_yourself = SmSaveLocal;
+
+                free (previous_id);
+        }
+
+        gsm_client_set_status (GSM_CLIENT (client), GSM_CLIENT_MANAGED);
+
+        return TRUE;
+}
+
+
+static void
+save_yourself_request_callback (SmsConn   conn,
+                                SmPointer manager_data,
+                                int       save_type,
+                                Bool      shutdown,
+                                int       interact_style,
+                                Bool      fast,
+                                Bool      global)
+{
+        GsmXSMPClient *client = manager_data;
+
+        g_debug ("Client '%s' received SaveYourselfRequest(%s, %s, %s, %s, %s)",
+                 client->priv->description,
+                 save_type == SmSaveLocal ? "SmSaveLocal" :
+                 save_type == SmSaveGlobal ? "SmSaveGlobal" : "SmSaveBoth",
+                 shutdown ? "Shutdown" : "!Shutdown",
+                 interact_style == SmInteractStyleAny ? "SmInteractStyleAny" :
+                 interact_style == SmInteractStyleErrors ? "SmInteractStyleErrors" :
+                 "SmInteractStyleNone", fast ? "Fast" : "!Fast",
+                 global ? "Global" : "!Global");
+
+        /* Examining the g_debug above, you can see that there are a total
+         * of 72 different combinations of options that this could have been
+         * called with. However, most of them are stupid.
+         *
+         * If @shutdown and @global are both TRUE, that means the caller is
+         * requesting that a logout message be sent to all clients, so we do
+         * that. We use @fast to decide whether or not to show a
+         * confirmation dialog. (This isn't really what @fast is for, but
+         * the old gnome-session and ksmserver both interpret it that way,
+         * so we do too.) We ignore @save_type because we pick the correct
+         * save_type ourselves later based on user prefs, dialog choices,
+         * etc, and we ignore @interact_style, because clients have not used
+         * it correctly consistently enough to make it worth honoring.
+         *
+         * If @shutdown is TRUE and @global is FALSE, the caller is
+         * confused, so we ignore the request.
+         *
+         * If @shutdown is FALSE and @save_type is SmSaveGlobal or
+         * SmSaveBoth, then the client wants us to ask some or all open
+         * applications to save open files to disk, but NOT quit. This is
+         * silly and so we ignore the request.
+         *
+         * If @shutdown is FALSE and @save_type is SmSaveLocal, then the
+         * client wants us to ask some or all open applications to update
+         * their current saved state, but not log out. At the moment, the
+         * code only supports this for the !global case (ie, a client
+         * requesting that it be allowed to update *its own* saved state,
+         * but not having everyone else update their saved state).
+         */
+
+        if (shutdown && global) {
+                g_debug ("  initiating shutdown");
+                gsm_client_logout_request (GSM_CLIENT (client),
+                                           !fast);
+        } else if (!shutdown && !global) {
+                g_debug ("  initiating checkpoint");
+                do_save_yourself (client, SmSaveLocal);
+        } else {
+                g_debug ("  ignoring");
+        }
+}
+
+static void
+save_yourself_phase2_request_callback (SmsConn   conn,
+                                       SmPointer manager_data)
+{
+        GsmXSMPClient *client = manager_data;
+
+        g_debug ("Client '%s' received SaveYourselfPhase2Request",
+                 client->priv->description);
+
+        if (client->priv->current_save_yourself == SmSaveLocal) {
+                /* WTF? Anyway, if it's checkpointing, it doesn't have to wait
+                 * for anyone else.
+                 */
+                SmsSaveYourselfPhase2 (client->priv->conn);
+        } else {
+                gsm_client_request_phase2 (GSM_CLIENT (client));
+        }
+}
+
+static void
+interact_request_callback (SmsConn   conn,
+                           SmPointer manager_data,
+                           int       dialog_type)
+{
+        GsmXSMPClient *client = manager_data;
+
+        g_debug ("Client '%s' received InteractRequest(%s)",
+                 client->priv->description,
+                 dialog_type == SmInteractStyleAny ? "Any" : "Errors");
+
+        gsm_client_request_interaction (GSM_CLIENT (client));
+}
+
+static void
+interact_done_callback (SmsConn   conn,
+                        SmPointer manager_data,
+                        Bool      cancel_shutdown)
+{
+        GsmXSMPClient *client = manager_data;
+
+        g_debug ("Client '%s' received InteractDone(cancel_shutdown = %s)",
+                 client->priv->description,
+                 cancel_shutdown ? "True" : "False");
+
+        gsm_client_interaction_done (GSM_CLIENT (client), cancel_shutdown);
+}
+
+static void
+save_yourself_done_callback (SmsConn   conn,
+                             SmPointer manager_data,
+                             Bool      success)
+{
+        GsmXSMPClient *client = manager_data;
+
+        g_debug ("Client '%s' received SaveYourselfDone(success = %s)",
+                 client->priv->description,
+                 success ? "True" : "False");
+
+        if (client->priv->current_save_yourself == SmSaveLocal) {
+                client->priv->current_save_yourself = -1;
+                SmsSaveComplete (client->priv->conn);
+                gsm_client_saved_state (GSM_CLIENT (client));
         } else {
-                client->description = g_strdup_printf ("%p", client);
+                client->priv->current_save_yourself = -1;
+                gsm_client_save_yourself_done (GSM_CLIENT (client));
+        }
+
+        if (client->priv->next_save_yourself) {
+                int save_type = client->priv->next_save_yourself;
+
+                client->priv->next_save_yourself = -1;
+                do_save_yourself (client, save_type);
+        }
+}
+
+static void
+close_connection_callback (SmsConn     conn,
+                           SmPointer   manager_data,
+                           int         count,
+                           char      **reason_msgs)
+{
+        GsmXSMPClient *client = manager_data;
+        int            i;
+
+        g_debug ("Client '%s' received CloseConnection", client->priv->description);
+        for (i = 0; i < count; i++) {
+                g_debug (" close reason: '%s'", reason_msgs[i]);
         }
+        SmFreeReasons (count, reason_msgs);
+
+        gsm_client_disconnected (GSM_CLIENT (client));
 }
 
 void
@@ -761,14 +840,14 @@
                          unsigned long *mask_ret,
                          SmsCallbacks  *callbacks_ret)
 {
-        client->conn = conn;
+        client->priv->conn = conn;
 
-        if (client->protocol_timeout) {
-                g_source_remove (client->protocol_timeout);
-                client->protocol_timeout = 0;
+        if (client->priv->protocol_timeout) {
+                g_source_remove (client->priv->protocol_timeout);
+                client->priv->protocol_timeout = 0;
         }
 
-        g_debug ("Initializing client %s", client->description);
+        g_debug ("Initializing client %s", client->priv->description);
 
         *mask_ret = 0;
 

Modified: branches/dbus_based/gnome-session/gsm-xsmp-client.h
==============================================================================
--- branches/dbus_based/gnome-session/gsm-xsmp-client.h	(original)
+++ branches/dbus_based/gnome-session/gsm-xsmp-client.h	Thu Jun 12 21:23:31 2008
@@ -37,32 +37,22 @@
 typedef struct _GsmXSMPClient        GsmXSMPClient;
 typedef struct _GsmXSMPClientClass   GsmXSMPClientClass;
 
+typedef struct GsmXSMPClientPrivate  GsmXSMPClientPrivate;
+
 struct _GsmXSMPClient
 {
-        GsmClient  parent;
-
-        SmsConn    conn;
-        IceConn    ice_conn;
-
-        guint      watch_id;
-        guint      protocol_timeout;
-
-        int        current_save_yourself;
-        int        next_save_yourself;
-        char      *id;
-        char      *description;
-        GPtrArray *props;
+        GsmClient             parent;
+        GsmXSMPClientPrivate *priv;
 };
 
 struct _GsmXSMPClientClass
 {
         GsmClientClass parent_class;
-
 };
 
 GType          gsm_xsmp_client_get_type           (void) G_GNUC_CONST;
 
-GsmXSMPClient *gsm_xsmp_client_new                (IceConn ice_conn);
+GsmClient     *gsm_xsmp_client_new                (IceConn ice_conn);
 
 void           gsm_xsmp_client_connect            (GsmXSMPClient *client,
                                                    SmsConn        conn,

Modified: branches/dbus_based/gnome-session/gsm-xsmp-server.c
==============================================================================
--- branches/dbus_based/gnome-session/gsm-xsmp-server.c	(original)
+++ branches/dbus_based/gnome-session/gsm-xsmp-server.c	Thu Jun 12 21:23:31 2008
@@ -105,7 +105,7 @@
         IceListenObj    listener;
         IceConn         ice_conn;
         IceAcceptStatus status;
-        GsmXSMPClient  *client;
+        GsmClient      *client;
         GsmXsmpServer  *server;
 
         listener = data->listener;
@@ -122,6 +122,8 @@
         client = gsm_xsmp_client_new (ice_conn);
         ice_conn->context = client;
 
+        gsm_client_store_add (server->priv->client_store, client);
+
         return TRUE;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]