summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian J. Tarricone <brian@tarricone.org>2009-09-18 01:45:29 -0700
committerBrian J. Tarricone <brian@tarricone.org>2009-09-18 01:45:29 -0700
commite3c7a7736c50dc989297c5b25f5bc7378ee8f465 (patch)
tree03c1a3f9a25419ff741a28ea75295bf7eb821ab8
parentf6bffc104bf11fdfa8e91e09daa565f19ff09cb3 (diff)
downloadxfce4-session-e3c7a7736c50dc989297c5b25f5bc7378ee8f465.tar.gz
huge refactoring of how SM properties are handled
the motivation here was to follow the XSMP spec more closely and allow application's to set custom properties. the trigger for this was GNOME's new-ish _GSM_DesktopFile property, which let's an app associate a .desktop file with itself, so the SM (or other apps) can show a localized app name, icon, etc. instead of keeping track of each of the "official" SM properties, we just have a GTree of everything the client has set. this makes a lot of code more generic, and also now makes it easier to make XfsmProperties look more like a semi-opaque object. it also removes a lot of annoying conversion code from XfsmClient, since XfsmProperties uses GValues internally now. along with the _GSM_DesktopFile support, xfce4-session now first tries to use the app's localized name in the splash screen before falling back to a guess based on SmProgram.
-rw-r--r--xfce4-session/sm-layer.c8
-rw-r--r--xfce4-session/xfsm-client.c555
-rw-r--r--xfce4-session/xfsm-manager.c52
-rw-r--r--xfce4-session/xfsm-properties.c664
-rw-r--r--xfce4-session/xfsm-properties.h59
-rw-r--r--xfce4-session/xfsm-startup.c51
6 files changed, 622 insertions, 767 deletions
diff --git a/xfce4-session/sm-layer.c b/xfce4-session/sm-layer.c
index e7c53766..4476875c 100644
--- a/xfce4-session/sm-layer.c
+++ b/xfce4-session/sm-layer.c
@@ -346,7 +346,8 @@ sm_set_properties (SmsConn sms_conn,
xfsm_client_get_id (client), num_props);
for (n = 0; n < num_props; ++n)
{
- xfsm_verbose (" Name: %s\n Type: %s\n", props[n]->name, props[n]->type);
+ xfsm_verbose (" Name: %s\n", props[n]->name);
+ xfsm_verbose (" Type: %s\n", props[n]->type);
if (strcmp (props[n]->type, "ARRAY8") == 0)
{
xfsm_verbose (" Value: %s\n", (const gchar *) props[n]->vals->value);
@@ -358,13 +359,14 @@ sm_set_properties (SmsConn sms_conn,
}
else if (strcmp (props[n]->type, "LISTofARRAY8") == 0)
{
- xfsm_verbose (" Value: ");
+ xfsm_verbose (" Value:\n");
for (i = 0; i < props[n]->num_vals; ++i)
{
- xfsm_verbose ("%s%s", (const gchar *) props[n]->vals[i].value,
+ xfsm_verbose (" %s%s\n", (const gchar *) props[n]->vals[i].value,
(i == props[n]->num_vals - 1) ? "" : ",");
}
}
+ xfsm_verbose ("\n");
}
xfsm_verbose ("\n");
}
diff --git a/xfce4-session/xfsm-client.c b/xfce4-session/xfsm-client.c
index ca400d52..19aac188 100644
--- a/xfce4-session/xfsm-client.c
+++ b/xfce4-session/xfsm-client.c
@@ -90,8 +90,8 @@ enum
static void xfsm_client_finalize (GObject *obj);
-static void xfsm_properties_replace_discard_command (XfsmProperties *properties,
- gchar **new_discard);
+static void xfsm_properties_discard_command_changed (XfsmProperties *properties,
+ gchar **old_discard);
static void xfsm_client_dbus_class_init (XfsmClientClass *klass);
static void xfsm_client_dbus_init (XfsmClient *client);
static void xfsm_client_dbus_cleanup (XfsmClient *client);
@@ -169,33 +169,30 @@ xfsm_client_finalize (GObject *obj)
-
static void
-xfsm_properties_replace_discard_command (XfsmProperties *properties,
- gchar **new_discard)
+xfsm_properties_discard_command_changed (XfsmProperties *properties,
+ gchar **old_discard)
{
- gchar **old_discard = properties->discard_command;
+ gchar **new_discard;
- if (old_discard != NULL)
- {
- if (!xfsm_strv_equal (old_discard, new_discard))
- {
- xfsm_verbose ("Client Id = %s, running old discard command.\n\n",
- properties->client_id);
-
- g_spawn_sync (properties->current_directory,
- old_discard,
- properties->environment,
- G_SPAWN_SEARCH_PATH,
- NULL, NULL,
- NULL, NULL,
- NULL, NULL);
- }
+ g_return_if_fail (properties != NULL);
+ g_return_if_fail (old_discard != NULL);
- g_strfreev (old_discard);
- }
+ new_discard = xfsm_properties_get_strv (properties, SmDiscardCommand);
- properties->discard_command = new_discard;
+ if (!xfsm_strv_equal (old_discard, new_discard))
+ {
+ xfsm_verbose ("Client Id = %s, running old discard command.\n\n",
+ properties->client_id);
+
+ g_spawn_sync (xfsm_properties_get_string(properties, SmCurrentDirectory),
+ old_discard,
+ xfsm_properties_get_strv(properties, SmEnvironment),
+ G_SPAWN_SEARCH_PATH,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL);
+ }
}
@@ -203,78 +200,15 @@ static void
xfsm_client_signal_prop_change (XfsmClient *client,
const gchar *name)
{
- GValue val = { 0, };
+ const GValue *value;
XfsmProperties *properties = client->properties;
- if (strcmp (name, SmCloneCommand) == 0)
- {
- g_value_init (&val, G_TYPE_STRV);
- g_value_set_boxed (&val, properties->clone_command);
- }
- else if (strcmp (name, SmCurrentDirectory) == 0)
- {
- g_value_init (&val, G_TYPE_STRING);
- g_value_set_string (&val, properties->current_directory);
- }
- else if (strcmp (name, SmDiscardCommand) == 0)
- {
- g_value_init (&val, G_TYPE_STRV);
- g_value_set_boxed (&val, properties->discard_command);
- }
- else if (strcmp (name, SmEnvironment) == 0)
- {
- g_value_init (&val, G_TYPE_STRV);
- g_value_set_boxed (&val, properties->environment);
- }
- else if (strcmp (name, SmProcessID) == 0)
- {
- g_value_init (&val, G_TYPE_STRING);
- g_value_set_string (&val, properties->process_id);
- }
- else if (strcmp (name, SmProgram) == 0)
- {
- g_value_init (&val, G_TYPE_STRING);
- g_value_set_string (&val, properties->program);
- }
- else if (strcmp (name, SmRestartCommand) == 0)
- {
- g_value_init (&val, G_TYPE_STRV);
- g_value_set_boxed (&val, properties->restart_command);
- }
- else if (strcmp (name, SmResignCommand) == 0)
- {
- g_value_init (&val, G_TYPE_STRV);
- g_value_set_boxed (&val, properties->resign_command);
- }
- else if (strcmp (name, SmRestartStyleHint) == 0)
- {
- g_value_init (&val, G_TYPE_UCHAR);
- g_value_set_uchar (&val, properties->restart_style_hint);
- }
- else if (strcmp (name, SmShutdownCommand) == 0)
- {
- g_value_init (&val, G_TYPE_STRV);
- g_value_set_boxed (&val, properties->shutdown_command);
- }
- else if (strcmp (name, SmUserID) == 0)
- {
- g_value_init (&val, G_TYPE_STRING);
- g_value_set_string (&val, properties->user_id);
- }
- else if (strcmp (name, GsmPriority) == 0)
+ value = xfsm_properties_get (properties, name);
+ if (value)
{
- g_value_init (&val, G_TYPE_UCHAR);
- g_value_set_uchar (&val, properties->priority);
+ g_signal_emit (client, signals[SIG_SM_PROPERTY_CHANGED], 0,
+ name, value);
}
- else
- {
- xfsm_verbose ("Client Id = %s, unhandled property change %s\n",
- client->id, name);
- return;
- }
-
- g_signal_emit (client, signals[SIG_SM_PROPERTY_CHANGED], 0, name, &val);
- g_value_unset (&val);
}
@@ -388,7 +322,6 @@ xfsm_client_merge_properties (XfsmClient *client,
gint num_props)
{
XfsmProperties *properties;
- gchar **strv;
SmProp *prop;
gint n;
@@ -399,199 +332,28 @@ xfsm_client_merge_properties (XfsmClient *client,
for (n = 0; n < num_props; ++n)
{
+ gchar **old_discard = NULL;
+
prop = props[n];
- if (strcmp (prop->name, SmCloneCommand) == 0)
- {
- strv = xfsm_strv_from_smprop (prop);
-
- if (strv != NULL)
- {
- if (properties->clone_command != NULL)
- g_strfreev (properties->clone_command);
- properties->clone_command = strv;
- xfsm_client_signal_prop_change (client, SmCloneCommand);
- }
- else
- {
- g_warning ("Client %s specified property %s of invalid "
- "type %s, ignoring.",
- properties->client_id,
- prop->name,
- prop->type);
- }
- }
- else if (strcmp (prop->name, SmCurrentDirectory) == 0)
- {
- if (properties->current_directory != NULL)
- g_free (properties->current_directory);
- properties->current_directory = g_strdup ((const gchar *) prop->vals->value);
- xfsm_client_signal_prop_change (client, SmCurrentDirectory);
- }
- else if (strcmp (prop->name, SmDiscardCommand) == 0)
- {
- strv = xfsm_strv_from_smprop (prop);
-
- if (strv != NULL)
- {
- xfsm_properties_replace_discard_command (properties, strv);
- xfsm_client_signal_prop_change (client, SmDiscardCommand);
- }
- else
- {
- g_warning ("Client %s specified property %s of invalid "
- "type %s, ignoring.",
- properties->client_id,
- prop->name,
- prop->type);
- }
- }
- else if (strcmp (prop->name, SmEnvironment) == 0)
+ if (!strcmp (props[n]->name, SmDiscardCommand))
{
- strv = xfsm_strv_from_smprop (prop);
-
- if (strv != NULL)
- {
- if (properties->environment != NULL)
- g_strfreev (properties->environment);
- properties->environment = strv;
- xfsm_client_signal_prop_change (client, SmEnvironment);
- }
- else
- {
- g_warning ("Client %s specified property %s of invalid "
- "type %s, ignoring.",
- properties->client_id,
- prop->name,
- prop->type);
- }
+ old_discard = xfsm_properties_get_strv (properties, SmDiscardCommand);
+ if (old_discard)
+ old_discard = g_strdupv (old_discard);
}
- else if (strcmp (prop->name, GsmPriority) == 0)
- {
- if (strcmp (prop->type, SmCARD8) == 0)
- {
- properties->priority = *((gint8 *) prop->vals->value);
- xfsm_client_signal_prop_change (client, GsmPriority);
- }
- else
- {
- g_warning ("Client %s specified property %s of invalid "
- "type %s, ignoring.",
- properties->client_id,
- prop->name,
- prop->type);
- }
- }
- else if (strcmp (prop->name, SmProcessID) == 0)
- {
- if (strcmp (prop->type, SmARRAY8) == 0)
- {
- if (properties->process_id != NULL)
- g_free (properties->process_id);
- properties->process_id = g_strdup ((const gchar *) prop->vals->value);
- xfsm_client_signal_prop_change (client, SmProcessID);
- }
- else
- {
- g_warning ("Client %s specified property %s of invalid "
- "type %s, ignoring.",
- properties->client_id,
- prop->name,
- prop->type);
- }
- }
- else if (strcmp (prop->name, SmProgram) == 0)
- {
- if (strcmp (prop->type, SmARRAY8) == 0)
- {
- if (properties->program != NULL)
- g_free (properties->program);
-
- /* work-around damn f*cking xmms */
- if (properties->restart_command != NULL
- && g_str_has_suffix (properties->restart_command[0], "xmms"))
- {
- properties->program = g_strdup ("xmms");
- }
- else
- {
- properties->program = g_strdup ((const gchar *) prop->vals->value);
- }
-
- xfsm_client_signal_prop_change (client, SmProgram);
- }
- else
- {
- g_warning ("Client %s specified property %s of invalid "
- "type %s, ignoring.",
- properties->client_id,
- prop->name,
- prop->type);
- }
- }
- else if (strcmp (prop->name, SmRestartCommand) == 0)
- {
- strv = xfsm_strv_from_smprop (prop);
-
- if (strv != NULL)
- {
- if (properties->restart_command != NULL)
- g_strfreev (properties->restart_command);
- properties->restart_command = strv;
- xfsm_client_signal_prop_change (client, SmRestartCommand);
-
- /* work-around damn f*cking xmms */
- if (g_str_has_suffix (strv[0], "xmms"))
- {
- if (properties->program != NULL)
- g_free (properties->program);
- properties->program = g_strdup ("xmms");
- xfsm_client_signal_prop_change (client, SmProgram);
- }
- }
- else
- {
- g_warning ("Client %s specified property %s of invalid "
- "type %s, ignoring.",
- properties->client_id,
- prop->name,
- prop->type);
- }
- }
- else if (strcmp (prop->name, SmRestartStyleHint) == 0)
- {
- if (strcmp (prop->type, SmCARD8) == 0)
- {
- properties->restart_style_hint = *((gint8 *) prop->vals->value);
- xfsm_client_signal_prop_change (client, SmRestartStyleHint);
- }
- else
- {
- g_warning ("Client %s specified property %s of invalid "
- "type %s, ignoring.",
- properties->client_id,
- prop->name,
- prop->type);
- }
- }
- else if (strcmp (prop->name, SmUserID) == 0)
+
+ xfsm_verbose ("Attempting to set prop (%s)\n", props[n]->name);
+
+ if (xfsm_properties_set_from_smprop (properties, props[n]))
{
- if (strcmp (prop->type, SmARRAY8) == 0)
- {
- if (properties->user_id != NULL)
- g_free (properties->user_id);
- properties->user_id = g_strdup ((const gchar *) prop->vals->value);
- xfsm_client_signal_prop_change (client, SmUserID);
- }
- else
- {
- g_warning ("Client %s specified property %s of invalid "
- "type %s, ignoring.",
- properties->client_id,
- prop->name,
- prop->type);
- }
+ if (old_discard)
+ xfsm_properties_discard_command_changed (properties, old_discard);
+
+ xfsm_client_signal_prop_change (client, props[n]->name);
}
+
+ g_strfreev (old_discard);
}
}
@@ -603,80 +365,20 @@ xfsm_client_delete_properties (XfsmClient *client,
{
XfsmProperties *properties;
gint n;
- const gchar *name_signal = NULL;
g_return_if_fail (XFSM_IS_CLIENT (client));
g_return_if_fail (client->properties != NULL);
properties = client->properties;
-
+
for (n = 0; n < num_props; ++n)
{
- if (strcmp (prop_names[n], SmCloneCommand) == 0)
- {
- if (properties->clone_command != NULL)
- {
- g_strfreev (properties->clone_command);
- properties->clone_command = NULL;
- name_signal = prop_names[n];
- }
- }
- else if (strcmp (prop_names[n], SmCurrentDirectory) == 0)
- {
- if (properties->current_directory != NULL)
- {
- g_free (properties->current_directory);
- properties->current_directory = NULL;
- name_signal = prop_names[n];
- }
- }
- else if (strcmp (prop_names[n], SmDiscardCommand) == 0)
- {
- if (properties->discard_command != NULL)
- {
- g_strfreev (properties->discard_command);
- properties->discard_command = NULL;
- name_signal = prop_names[n];
- }
- }
- else if (strcmp (prop_names[n], SmEnvironment) == 0)
- {
- if (properties->environment != NULL)
- {
- g_strfreev (properties->environment);
- properties->environment = NULL;
- name_signal = prop_names[n];
- }
- }
- else if (strcmp (prop_names[n], GsmPriority) == 0)
- {
- if (properties->priority != 50)
- {
- properties->priority = 50;
- xfsm_client_signal_prop_change (client, GsmPriority);
- }
- }
- else if (strcmp (prop_names[n], SmRestartStyleHint) == 0)
- {
- if (properties->restart_style_hint != SmRestartIfRunning)
- {
- properties->restart_style_hint = SmRestartIfRunning;
- xfsm_client_signal_prop_change (client, SmRestartStyleHint);
- }
- }
- else if (strcmp (prop_names[n], SmUserID) == 0)
+ if (xfsm_properties_remove (properties, prop_names[n]))
{
- if (properties->user_id != NULL)
- {
- g_free (properties->user_id);
- properties->user_id = NULL;
- name_signal = prop_names[n];
- }
+ g_signal_emit (client, signals[SIG_SM_PROPERTY_DELETED], 0,
+ prop_names[n]);
}
}
-
- if (name_signal != NULL)
- g_signal_emit (client, signals[SIG_SM_PROPERTY_DELETED], 0, name_signal);
}
@@ -780,6 +482,22 @@ xfsm_client_dbus_get_state (XfsmClient *client,
static gboolean
+xfsm_client_properties_tree_foreach (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ gchar *prop_name = key;
+ GValue *prop_value = value;
+ GHashTable *hash_table = data;
+
+ xfsm_verbose (" -> (%s)\n", prop_name);
+
+ g_hash_table_insert (hash_table, prop_name, prop_value);
+
+ return FALSE;
+}
+
+static gboolean
xfsm_client_dbus_get_all_sm_properties (XfsmClient *client,
GHashTable **OUT_properties,
GError **error)
@@ -793,45 +511,15 @@ xfsm_client_dbus_get_all_sm_properties (XfsmClient *client,
return FALSE;
}
- *OUT_properties = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL,
- (GDestroyNotify) xfsm_g_value_free);
-
- g_hash_table_insert (*OUT_properties, SmCloneCommand,
- xfsm_g_value_from_property (properties, SmCloneCommand));
-
- g_hash_table_insert (*OUT_properties, SmCurrentDirectory,
- xfsm_g_value_from_property (properties, SmCurrentDirectory));
-
- g_hash_table_insert (*OUT_properties, SmDiscardCommand,
- xfsm_g_value_from_property (properties, SmDiscardCommand));
-
- g_hash_table_insert (*OUT_properties, SmEnvironment,
- xfsm_g_value_from_property (properties, SmEnvironment));
+ xfsm_verbose ("DBus: getting all properties\n");
- g_hash_table_insert (*OUT_properties, SmProcessID,
- xfsm_g_value_from_property (properties, SmProcessID));
-
- g_hash_table_insert (*OUT_properties, SmProgram,
- xfsm_g_value_from_property (properties, SmProgram));
-
- g_hash_table_insert (*OUT_properties, SmRestartCommand,
- xfsm_g_value_from_property (properties, SmRestartCommand));
-
- g_hash_table_insert (*OUT_properties, SmResignCommand,
- xfsm_g_value_from_property (properties, SmResignCommand));
-
- g_hash_table_insert (*OUT_properties, SmRestartStyleHint,
- xfsm_g_value_from_property (properties, SmRestartStyleHint));
-
- g_hash_table_insert (*OUT_properties, SmShutdownCommand,
- xfsm_g_value_from_property (properties, SmShutdownCommand));
-
- g_hash_table_insert (*OUT_properties, SmUserID,
- xfsm_g_value_from_property (properties, SmUserID));
+ *OUT_properties = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, NULL);
+ g_tree_foreach (properties->sm_properties,
+ xfsm_client_properties_tree_foreach,
+ *OUT_properties);
- g_hash_table_insert (*OUT_properties, GsmPriority,
- xfsm_g_value_from_property (properties, GsmPriority));
+ xfsm_verbose ("DBus: done\n");
return TRUE;
}
@@ -854,12 +542,11 @@ xfsm_client_dbus_get_sm_properties (XfsmClient *client,
}
*OUT_properties = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL,
- (GDestroyNotify) xfsm_g_value_free);
+ NULL, NULL);
for (i = 0; names[i]; ++i)
{
- GValue *value = xfsm_g_value_from_property (properties, names[i]);
+ GValue *value = g_tree_lookup (properties->sm_properties, names[i]);
if (G_LIKELY (value))
g_hash_table_insert (*OUT_properties, names[i], value);
}
@@ -868,81 +555,16 @@ xfsm_client_dbus_get_sm_properties (XfsmClient *client,
}
-/* this is a "lightweight" version of xfsm_properties_extract(). it
- * uses glib functions to allocate memory, and doesn't allocate where
- * it doesn't need to (it assumes all strings will last a while. for
- * these reasons, you can't use SmFreeProperty() on the results.
- */
static void
-xfsm_convert_sm_properties_ht (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- HtToPropsData *pdata = user_data;
- gchar *name = key;
- GValue *val = value;
- gint n = pdata->count;
-
- if (strcmp (name, SmCloneCommand) == 0
- || strcmp (name, SmDiscardCommand) == 0
- || strcmp (name, SmEnvironment) == 0
- || strcmp (name, SmRestartCommand) == 0
- || strcmp (name, SmResignCommand) == 0
- || strcmp (name, SmShutdownCommand) == 0)
- {
- gchar **val_strv = g_value_get_boxed (val);
- gint i;
-
- if (G_UNLIKELY (val_strv == NULL))
- return;
-
- pdata->props[n].name = name;
- pdata->props[n].type = SmLISTofARRAY8;
- pdata->props[n].num_vals = g_strv_length (val_strv);
- pdata->props[n].vals = g_new0 (SmPropValue, pdata->props[n].num_vals);
- for (i = 0; i < pdata->props[n].num_vals; ++i)
- {
- pdata->props[n].vals[i].length = strlen (val_strv[i]);
- pdata->props[n].vals[i].value = val_strv[i];
- }
- }
- else if (strcmp (name, SmCurrentDirectory) == 0
- || strcmp (name, SmProcessID) == 0
- || strcmp (name, SmProgram) == 0
- || strcmp (name, SmUserID) == 0)
- {
- gchar *val_str = (gchar *) g_value_get_string (val);
-
- if (G_UNLIKELY (val_str == NULL))
- return;
-
- pdata->props[n].name = name;
- pdata->props[n].type = SmARRAY8;
- pdata->props[n].num_vals = 1;
- pdata->props[n].vals = g_new0 (SmPropValue, 1);
- pdata->props[n].vals[0].length = strlen (val_str);
- pdata->props[n].vals[0].value = val_str;
- }
- else if (strcmp (name, SmRestartStyleHint) == 0
- || strcmp (name, GsmPriority) == 0)
- {
- guint val_uchar = g_value_get_uchar (val);
-
- pdata->props[n].name = name;
- pdata->props[n].type = SmCARD8;
- pdata->props[n].num_vals = 1;
- pdata->props[n].vals = g_new0 (SmPropValue, 1);
- pdata->props[n].vals[0].length = 1;
- pdata->props[n].vals[0].value = g_new0 (guchar, 1);
- *(guchar *)(pdata->props[n].vals[0].value) = val_uchar;
- }
- else
- {
- g_warning ("Unhandled property \"%s\"", name);
- return;
- }
+xfsm_client_dbus_merge_properties_ht (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ gchar *prop_name = key;
+ GValue *prop_value = value;
+ XfsmProperties *properties = user_data;
- ++pdata->count;
+ xfsm_properties_set (properties, prop_name, prop_value);
}
@@ -951,9 +573,6 @@ xfsm_client_dbus_set_sm_properties (XfsmClient *client,
GHashTable *properties,
GError **error)
{
- HtToPropsData pdata;
- gint n_props, i;
-
if (G_UNLIKELY (client->properties == NULL))
{
g_set_error (error, XFSM_ERROR, XFSM_ERROR_BAD_VALUE,
@@ -961,20 +580,12 @@ xfsm_client_dbus_set_sm_properties (XfsmClient *client,
return FALSE;
}
- n_props = g_hash_table_size (properties);
- pdata.props = g_new0 (SmProp, n_props);
- pdata.count = 0;
+ xfsm_verbose ("DBus: setting properties\n");
- g_hash_table_foreach (properties, xfsm_convert_sm_properties_ht, &pdata);
- xfsm_client_merge_properties (client, &pdata.props, pdata.count);
+ g_hash_table_foreach (properties, xfsm_client_dbus_merge_properties_ht,
+ client->properties);
- for (i = 0; i < pdata.count; ++i)
- {
- if (strcmp (pdata.props[i].type, SmCARD8) == 0)
- g_free (pdata.props[i].vals[0].value);
- g_free (pdata.props[i].vals);
- }
- g_free (pdata.props);
+ xfsm_verbose ("DBus: done\n");
return TRUE;
}
diff --git a/xfce4-session/xfsm-manager.c b/xfce4-session/xfsm-manager.c
index 49f6cd20..4f9e60ed 100644
--- a/xfce4-session/xfsm-manager.c
+++ b/xfce4-session/xfsm-manager.c
@@ -347,6 +347,8 @@ gboolean
xfsm_manager_handle_failed_properties (XfsmManager *manager,
XfsmProperties *properties)
{
+ gint restart_style_hint;
+
/* Handle apps that failed to start, or died randomly, here */
xfsm_properties_set_default_child_watch (properties);
@@ -357,11 +359,15 @@ xfsm_manager_handle_failed_properties (XfsmManager *manager,
properties->restart_attempts_reset_id = 0;
}
- if (properties->restart_style_hint == SmRestartAnyway)
+ restart_style_hint = xfsm_properties_get_uchar (properties,
+ SmRestartStyleHint,
+ SmRestartIfRunning);
+
+ if (restart_style_hint == SmRestartAnyway)
{
g_queue_push_tail (manager->restart_properties, properties);
}
- else if (properties->restart_style_hint == SmRestartImmediately)
+ else if (restart_style_hint == SmRestartImmediately)
{
if (++properties->restart_attempts > MAX_RESTART_ATTEMPTS)
{
@@ -391,6 +397,8 @@ xfsm_manager_handle_failed_properties (XfsmManager *manager,
}
else
{
+ gchar **discard_command;
+
/* We get here if a SmRestartNever or SmRestartIfRunning client
* has exited. SmRestartNever clients shouldn't have discard
* commands, but it can't hurt to run it if it has one for some
@@ -398,7 +406,8 @@ xfsm_manager_handle_failed_properties (XfsmManager *manager,
xfsm_verbose ("Client Id %s exited, removing from session.\n",
properties->client_id);
- if (properties->discard_command != NULL)
+ discard_command = xfsm_properties_get_strv (properties, SmDiscardCommand);
+ if (discard_command != NULL)
{
/* Run the SmDiscardCommand after the client exited in any state,
* but only if we don't expect the client to be restarted,
@@ -420,9 +429,9 @@ xfsm_manager_handle_failed_properties (XfsmManager *manager,
xfsm_verbose ("Client Id = %s: running discard command.\n\n",
properties->client_id);
- g_spawn_sync (properties->current_directory,
- properties->discard_command,
- properties->environment,
+ g_spawn_sync (xfsm_properties_get_string (properties, SmCurrentDirectory),
+ discard_command,
+ xfsm_properties_get_strv (properties, SmEnvironment),
G_SPAWN_SEARCH_PATH,
NULL, NULL,
NULL, NULL,
@@ -1162,14 +1171,13 @@ xfsm_manager_save_yourself_global (XfsmManager *manager,
{
XfsmClient *client = lp->data;
XfsmProperties *properties = xfsm_client_get_properties (client);
+ const gchar *program;
/* xterm's session management is broken, so we won't
* send a SAVE YOURSELF to xterms */
- if (properties->program != NULL
- && strcasecmp (properties->program, "xterm") == 0)
- {
- continue;
- }
+ program = xfsm_properties_get_string (properties, SmProgram);
+ if (program != NULL && strcasecmp (program, "xterm") == 0)
+ continue;
if (xfsm_client_get_state (client) != XFSM_CLIENT_SAVINGLOCAL)
{
@@ -1430,16 +1438,22 @@ xfsm_manager_perform_shutdown (XfsmManager *manager)
lp = lp->next)
{
XfsmProperties *properties = lp->data;
+ gint restart_style_hint;
+ gchar **shutdown_command;
+
+ restart_style_hint = xfsm_properties_get_uchar (properties,
+ SmRestartStyleHint,
+ SmRestartIfRunning);
+ shutdown_command = xfsm_properties_get_strv (properties, SmShutdownCommand);
- if (properties->restart_style_hint == SmRestartAnyway
- && properties->shutdown_command != NULL)
+ if (restart_style_hint == SmRestartAnyway && shutdown_command != NULL)
{
xfsm_verbose ("Client Id = %s, quit already, running shutdown command.\n\n",
properties->client_id);
- g_spawn_sync (properties->current_directory,
- properties->shutdown_command,
- properties->environment,
+ g_spawn_sync (xfsm_properties_get_string (properties, SmCurrentDirectory),
+ shutdown_command,
+ xfsm_properties_get_strv (properties, SmEnvironment),
G_SPAWN_SEARCH_PATH,
NULL, NULL,
NULL, NULL,
@@ -1652,10 +1666,14 @@ xfsm_manager_store_session (XfsmManager *manager)
{
XfsmClient *client = lp->data;
XfsmProperties *properties = xfsm_client_get_properties (client);
+ gint restart_style_hint;
if (properties == NULL || !xfsm_properties_check (xfsm_client_get_properties (client)))
continue;
- if (properties->restart_style_hint == SmRestartNever)
+ restart_style_hint = xfsm_properties_get_uchar (properties,
+ SmRestartStyleHint,
+ SmRestartIfRunning);
+ if (restart_style_hint == SmRestartNever)
continue;
g_snprintf (prefix, 64, "Client%d_", count);
diff --git a/xfce4-session/xfsm-properties.c b/xfce4-session/xfsm-properties.c
index a4341b1c..45243dd6 100644
--- a/xfce4-session/xfsm-properties.c
+++ b/xfce4-session/xfsm-properties.c
@@ -48,6 +48,45 @@ static SmProp* str_to_property (const gchar *name,
static SmProp* int_to_property (const gchar *name,
gint value) G_GNUC_PURE;
+/* these three structs hold lists of properties that we save in
+ * and load from the session file */
+static const struct
+{
+ const gchar *name;
+ const gchar *xsmp_name;
+} strv_properties[] = {
+ { "CloneCommand", SmCloneCommand },
+ { "DiscardCommand", SmDiscardCommand },
+ { "Environment", SmEnvironment },
+ { "ResignCommand", SmResignCommand },
+ { "RestartCommand", SmRestartCommand },
+ { "ShutdownCommand", SmShutdownCommand },
+ { NULL, NULL }
+};
+
+static const struct
+{
+ const gchar *name;
+ const gchar *xsmp_name;
+} str_properties[] = {
+ { "CurrentDirectory", SmCurrentDirectory },
+ { "DesktopFile", GsmDesktopFile },
+ { "Program", SmProgram },
+ { "UserId", SmUserID },
+ { NULL, NULL }
+};
+
+static const struct
+{
+ const gchar *name;
+ const gchar *xsmp_name;
+ const guchar default_value;
+} uchar_properties[] = {
+ { "Priority", GsmPriority, 50 },
+ { "RestartStyleHint", SmRestartStyleHint, SmRestartIfRunning },
+ { NULL, NULL, 0 }
+};
+
#ifndef HAVE_STRDUP
static char*
@@ -149,16 +188,43 @@ xfsm_properties_new (const gchar *client_id,
{
XfsmProperties *properties;
- properties = g_new0 (XfsmProperties, 1);
+ properties = g_slice_new0 (XfsmProperties);
properties->client_id = g_strdup (client_id);
properties->hostname = g_strdup (hostname);
- properties->priority = 50;
properties->pid = -1;
+
+ properties->sm_properties = g_tree_new_full ((GCompareDataFunc) strcmp,
+ NULL,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) xfsm_g_value_free);
return properties;
}
+static gboolean
+xfsm_properties_extract_foreach (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ const gchar *prop_name = key;
+ const GValue *prop_value = value;
+ SmProp ***pp = data;
+
+ if (G_VALUE_HOLDS (prop_value, G_TYPE_STRV))
+ **pp++ = strv_to_property (prop_name, g_value_get_boxed (prop_value));
+ else if (G_VALUE_HOLDS_STRING (prop_value))
+ **pp++ = str_to_property (prop_name, g_value_get_string (prop_value));
+ else if (G_VALUE_HOLDS_UCHAR (prop_value))
+ **pp++ = int_to_property (prop_name, g_value_get_uchar (prop_value));
+ else {
+ g_warning ("Unhandled property \"%s\" with type \"%s\"", prop_name,
+ g_type_name (G_VALUE_TYPE (prop_value)));
+ }
+
+ return FALSE;
+}
+
void
xfsm_properties_extract (XfsmProperties *properties,
gint *num_props,
@@ -169,47 +235,17 @@ xfsm_properties_extract (XfsmProperties *properties,
g_return_if_fail (num_props != NULL);
g_return_if_fail (props != NULL);
- *props = pp = (SmProp **) malloc (sizeof (SmProp *) * 20);
-
- if (properties->clone_command != NULL)
- *pp++ = strv_to_property (SmCloneCommand, properties->clone_command);
-
- if (properties->current_directory != NULL)
- *pp++ = str_to_property (SmCurrentDirectory, properties->current_directory);
-
- if (properties->discard_command != NULL)
- *pp++ = strv_to_property (SmDiscardCommand, properties->discard_command);
-
- if (properties->environment != NULL)
- *pp++ = strv_to_property (SmEnvironment, properties->environment);
-
- *pp++ = int_to_property (GsmPriority, properties->priority);
-
- if (properties->process_id != NULL)
- *pp++ = str_to_property (SmProcessID, properties->process_id);
-
- if (properties->program != NULL)
- *pp++ = str_to_property (SmProgram, properties->program);
-
- if (properties->resign_command != NULL)
- *pp++ = strv_to_property (SmResignCommand, properties->resign_command);
+ *props = pp = (SmProp **) malloc (sizeof (SmProp *) * g_tree_nnodes (properties->sm_properties));
- if (properties->restart_command != NULL)
- *pp++ = strv_to_property (SmRestartCommand, properties->restart_command);
-
- *pp++ = int_to_property (SmRestartStyleHint, properties->restart_style_hint);
-
- if (properties->shutdown_command != NULL)
- *pp++ = strv_to_property (SmShutdownCommand, properties->shutdown_command);
-
- if (properties->user_id != NULL)
- *pp++ = str_to_property (SmUserID, properties->user_id);
+ g_tree_foreach (properties->sm_properties,
+ xfsm_properties_extract_foreach,
+ &pp);
*num_props = pp - *props;
}
-XfsmProperties*
+XfsmProperties *
xfsm_properties_load (XfceRc *rc,
const gchar *prefix)
{
@@ -218,9 +254,13 @@ xfsm_properties_load (XfceRc *rc,
XfsmProperties *properties;
const gchar *client_id;
const gchar *hostname;
- const gchar *value;
+ GValue *value;
+ const gchar *value_str;
+ gchar **value_strv;
+ gint value_int;
gchar buffer[256];
-
+ gint i;
+
client_id = xfce_rc_read_entry (rc, ENTRY ("ClientId"), NULL);
if (client_id == NULL)
{
@@ -236,39 +276,40 @@ xfsm_properties_load (XfceRc *rc,
"Skipping client.");
return NULL;
}
+
+ xfsm_verbose ("Loading properties for client %s\n", client_id);
- properties = g_new0 (XfsmProperties, 1);
- properties->restart_attempts = 0;
- properties->client_id = g_strdup (client_id);
- properties->hostname = g_strdup (hostname);
- properties->clone_command = xfce_rc_read_list_entry (rc, ENTRY ("CloneCommand"),
- NULL);
- properties->discard_command = xfce_rc_read_list_entry (rc, ENTRY ("DiscardCommand"),
- NULL);
- properties->environment = xfce_rc_read_list_entry (rc, ENTRY ("Environment"),
- NULL);
- properties->resign_command = xfce_rc_read_list_entry (rc, ENTRY ("ResignCOmmand"),
- NULL);
- properties->restart_command = xfce_rc_read_list_entry (rc, ENTRY ("RestartCommand"),
- NULL);
- properties->shutdown_command = xfce_rc_read_list_entry (rc, ENTRY ("ShutdownCommand"),
- NULL);
- properties->priority = xfce_rc_read_int_entry (rc, ENTRY ("Priority"), 50);
- properties->restart_style_hint = xfce_rc_read_int_entry (rc, ENTRY ("RestartStyleHint"),
- SmRestartIfRunning);
-
- value = xfce_rc_read_entry (rc, ENTRY ("CurrentDirectory"), NULL);
- if (value != NULL)
- properties->current_directory = g_strdup (value);
-
- value = xfce_rc_read_entry (rc, ENTRY ("Program"), NULL);
- if (value != NULL)
- properties->program = g_strdup (value);
-
- value = xfce_rc_read_entry (rc, ENTRY ("UserId"), NULL);
- if (value != NULL)
- properties->user_id = g_strdup (value);
-
+ properties = xfsm_properties_new (client_id, hostname);
+
+ for (i = 0; strv_properties[i].name; ++i)
+ {
+ value_strv = xfce_rc_read_list_entry (rc, ENTRY (strv_properties[i].name), NULL);
+ if (value_strv)
+ {
+ xfsm_verbose ("-> Set strv (%s)\n", strv_properties[i].xsmp_name);
+ /* don't use _set_strv() to avoid a realloc of the whole strv */
+ value = xfsm_g_value_new (G_TYPE_STRV);
+ g_value_take_boxed (value, value_strv);
+ g_tree_replace (properties->sm_properties,
+ g_strdup (strv_properties[i].xsmp_name),
+ value);
+ }
+ }
+
+ for (i = 0; str_properties[i].name; ++i)
+ {
+ value_str = xfce_rc_read_entry (rc, ENTRY (str_properties[i].name), NULL);
+ if (value_str)
+ xfsm_properties_set_string (properties, str_properties[i].xsmp_name, value_str);
+ }
+
+ for (i = 0; uchar_properties[i].name; ++i)
+ {
+ value_int = xfce_rc_read_int_entry (rc, ENTRY (uchar_properties[i].name),
+ uchar_properties[i].default_value);
+ xfsm_properties_set_uchar (properties, uchar_properties[i].xsmp_name, value_int);
+ }
+
if (!xfsm_properties_check (properties))
{
xfsm_properties_free (properties);
@@ -288,77 +329,41 @@ xfsm_properties_store (XfsmProperties *properties,
{
#define ENTRY(name) (compose(buffer, 256, prefix, (name)))
- gchar buffer[256];
+ GValue *value;
+ gint i;
+ gchar buffer[256];
xfce_rc_write_entry (rc, ENTRY ("ClientId"), properties->client_id);
xfce_rc_write_entry (rc, ENTRY ("Hostname"), properties->hostname);
-
- if (properties->clone_command != NULL)
- {
- xfce_rc_write_list_entry (rc, ENTRY ("CloneCommand"),
- properties->clone_command, NULL);
- }
-
- if (properties->current_directory != NULL)
- {
- xfce_rc_write_entry (rc, ENTRY ("CurrentDirectory"),
- properties->current_directory);
- }
-
- if (properties->discard_command != NULL)
- {
- xfce_rc_write_list_entry (rc, ENTRY ("DiscardCommand"),
- properties->discard_command, NULL);
- }
- if (properties->environment != NULL)
+ for (i = 0; strv_properties[i].name; ++i)
{
- xfce_rc_write_list_entry (rc, ENTRY ("Environment"),
- properties->environment, NULL);
- }
-
- if (properties->priority != 50)
- {
- xfce_rc_write_int_entry (rc, ENTRY ("Priority"),
- properties->priority);
+ value = g_tree_lookup (properties->sm_properties, strv_properties[i].xsmp_name);
+ if (value)
+ {
+ xfce_rc_write_list_entry (rc, ENTRY (strv_properties[i].name),
+ g_value_get_boxed (value), NULL);
+ }
}
- /* ProcessID isn't something you'd generally want saved... */
-
- if (properties->program != NULL)
+ for (i = 0; str_properties[i].name; ++i)
{
- xfce_rc_write_entry (rc, ENTRY ("Program"),
- properties->program);
+ value = g_tree_lookup (properties->sm_properties, str_properties[i].xsmp_name);
+ if (value)
+ {
+ xfce_rc_write_entry (rc, ENTRY (str_properties[i].name),
+ g_value_get_string (value));
+ }
}
- if (properties->resign_command != NULL)
+ for (i = 0; uchar_properties[i].name; ++i)
{
- xfce_rc_write_list_entry (rc, ENTRY ("ResignCommand"),
- properties->resign_command, NULL);
- }
-
- if (properties->restart_command != NULL)
- {
- xfce_rc_write_list_entry (rc, ENTRY ("RestartCommand"),
- properties->restart_command, NULL);
- }
-
- if (properties->restart_style_hint != SmRestartIfRunning)
- {
- xfce_rc_write_int_entry (rc, ENTRY ("RestartStyleHint"),
- properties->restart_style_hint);
- }
-
- if (properties->shutdown_command != NULL)
- {
- xfce_rc_write_list_entry (rc, ENTRY ("ShutdownCommand"),
- properties->shutdown_command, NULL);
- }
-
- if (properties->user_id != NULL)
- {
- xfce_rc_write_entry (rc, ENTRY ("UserId"),
- properties->user_id);
+ value = g_tree_lookup (properties->sm_properties, uchar_properties[i].xsmp_name);
+ if (value)
+ {
+ xfce_rc_write_int_entry (rc, ENTRY (uchar_properties[i].name),
+ g_value_get_uchar (value));
+ }
}
#undef ENTRY
@@ -369,7 +374,18 @@ gint
xfsm_properties_compare (const XfsmProperties *a,
const XfsmProperties *b)
{
- return a->priority - b->priority;
+ GValue *va, *vb;
+ gint ia = 50, ib = 50;
+
+ va = g_tree_lookup (a->sm_properties, GsmPriority);
+ if (va)
+ ia = g_value_get_uchar (va);
+
+ vb = g_tree_lookup (b->sm_properties, GsmPriority);
+ if (vb)
+ ib = g_value_get_uchar (vb);
+
+ return ia - ib;
}
@@ -388,161 +404,323 @@ xfsm_properties_check (const XfsmProperties *properties)
return properties->client_id != NULL
&& properties->hostname != NULL
- && properties->program != NULL
- && properties->restart_command != NULL;
+ && g_tree_lookup (properties->sm_properties, SmProgram) != NULL
+ && g_tree_lookup (properties->sm_properties, SmRestartCommand) != NULL;
}
-void
-xfsm_properties_set_default_child_watch (XfsmProperties *properties)
+G_CONST_RETURN gchar *
+xfsm_properties_get_string (XfsmProperties *properties,
+ const gchar *property_name)
{
- if (properties->child_watch_id > 0)
- {
- g_source_remove (properties->child_watch_id);
- properties->child_watch_id = 0;
- }
+ GValue *value;
- if (properties->pid != -1)
- {
- /* if the PID is still open, we need to close it,
- * or it will become a zombie when it quits */
- g_child_watch_add (properties->pid,
- (GChildWatchFunc) g_spawn_close_pid,
- NULL);
- properties->pid = -1;
- }
+ g_return_val_if_fail (properties != NULL, NULL);
+ g_return_val_if_fail (property_name != NULL, NULL);
+
+ value = g_tree_lookup (properties->sm_properties, property_name);
+
+ if (G_LIKELY (value && G_VALUE_HOLDS_STRING (value)))
+ return g_value_get_string (value);
+
+ return NULL;
}
-void
-xfsm_properties_free (XfsmProperties *properties)
+
+gchar **
+xfsm_properties_get_strv (XfsmProperties *properties,
+ const gchar *property_name)
{
- g_return_if_fail (properties != NULL);
+ GValue *value;
- xfsm_properties_set_default_child_watch (properties);
+ g_return_val_if_fail (properties != NULL, NULL);
+ g_return_val_if_fail (property_name != NULL, NULL);
- if (properties->restart_attempts_reset_id > 0)
- g_source_remove (properties->restart_attempts_reset_id);
- 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)
- g_free (properties->hostname);
- if (properties->clone_command != NULL)
- g_strfreev (properties->clone_command);
- if (properties->current_directory != NULL)
- g_free (properties->current_directory);
- if (properties->process_id != NULL)
- g_free (properties->process_id);
- if (properties->program != NULL)
- g_free (properties->program);
- if (properties->discard_command != NULL)
- g_strfreev (properties->discard_command);
- if (properties->resign_command != NULL)
- g_strfreev (properties->resign_command);
- if (properties->restart_command != NULL)
- g_strfreev (properties->restart_command);
- if (properties->shutdown_command != NULL)
- g_strfreev (properties->shutdown_command);
- if (properties->environment != NULL)
- g_strfreev (properties->environment);
- if (properties->user_id)
- g_free (properties->user_id);
- g_free (properties);
+ value = g_tree_lookup (properties->sm_properties, property_name);
+
+ if (G_LIKELY (value && G_VALUE_HOLDS (value, G_TYPE_STRV)))
+ return g_value_get_boxed (value);
+
+ return NULL;
}
-gchar **
-xfsm_strv_from_smprop (const SmProp *prop)
+guchar
+xfsm_properties_get_uchar (XfsmProperties *properties,
+ const gchar *property_name,
+ guchar default_value)
{
- gchar **strv = NULL;
- gint strc;
- gint n;
-
- if (strcmp (prop->type, SmARRAY8) == 0)
+ GValue *value;
+
+ g_return_val_if_fail (properties != NULL, default_value);
+ g_return_val_if_fail (property_name != NULL, default_value);
+
+ value = g_tree_lookup (properties->sm_properties, property_name);
+
+ if (G_LIKELY (value && G_VALUE_HOLDS_UCHAR (value)))
+ return g_value_get_uchar (value);
+
+ return default_value;
+}
+
+
+const GValue *
+xfsm_properties_get (XfsmProperties *properties,
+ const gchar *property_name)
+{
+ g_return_val_if_fail (properties != NULL, NULL);
+ g_return_val_if_fail (property_name != NULL, NULL);
+
+ return g_tree_lookup (properties->sm_properties, property_name);
+}
+
+
+void
+xfsm_properties_set_string (XfsmProperties *properties,
+ const gchar *property_name,
+ const gchar *property_value)
+{
+ GValue *value;
+
+ g_return_if_fail (properties != NULL);
+ g_return_if_fail (property_name != NULL);
+ g_return_if_fail (property_value != NULL);
+
+ xfsm_verbose ("-> Set string (%s, %s)\n", property_name, property_value);
+
+ value = g_tree_lookup (properties->sm_properties, property_name);
+ if (value)
{
- if (!g_shell_parse_argv ((const gchar *) prop->vals->value,
- &strc, &strv, NULL))
- return NULL;
+ if (!G_VALUE_HOLDS_STRING (value))
+ {
+ g_value_unset (value);
+ g_value_init (value, G_TYPE_STRING);
+ }
+ g_value_set_string (value, property_value);
}
- else if (strcmp (prop->type, SmLISTofARRAY8) == 0)
+ else
{
- strv = g_new (gchar *, prop->num_vals + 1);
- for (n = 0; n < prop->num_vals; ++n)
- strv[n] = g_strdup ((const gchar *) prop->vals[n].value);
- strv[n] = NULL;
+ value = xfsm_g_value_new (G_TYPE_STRING);
+ g_value_set_string (value, property_value);
+ g_tree_replace (properties->sm_properties,
+ g_strdup (property_name),
+ value);
}
-
- return strv;
}
-GValue *
-xfsm_g_value_from_property (XfsmProperties *properties,
- const gchar *name)
+void
+xfsm_properties_set_strv (XfsmProperties *properties,
+ const gchar *property_name,
+ gchar **property_value)
{
- GValue *val = NULL;
+ GValue *value;
- if (strcmp (name, SmCloneCommand) == 0)
- {
- val = xfsm_g_value_new (G_TYPE_STRV);
- g_value_take_boxed (val, g_strdupv (properties->clone_command));
- }
- else if (strcmp (name, SmCurrentDirectory) == 0)
+ g_return_if_fail (properties != NULL);
+ g_return_if_fail (property_name != NULL);
+ g_return_if_fail (property_value != NULL);
+
+ xfsm_verbose ("-> Set strv (%s)\n", property_name);
+
+ value = g_tree_lookup (properties->sm_properties, property_name);
+ if (value)
{
- val = xfsm_g_value_new (G_TYPE_STRING);
- g_value_take_string (val, g_strdup (properties->current_directory));
+ if (!G_VALUE_HOLDS (value, G_TYPE_STRV))
+ {
+ g_value_unset (value);
+ g_value_init (value, G_TYPE_STRV);
+ }
+ g_value_set_boxed (value, property_value);
}
- else if (strcmp (name, SmDiscardCommand) == 0)
+ else
{
- val = xfsm_g_value_new (G_TYPE_STRV);
- g_value_take_boxed (val, g_strdupv (properties->discard_command));
+ value = xfsm_g_value_new (G_TYPE_STRV);
+ g_value_set_boxed (value, property_value);
+ g_tree_replace (properties->sm_properties,
+ g_strdup (property_name),
+ value);
}
- else if (strcmp (name, SmEnvironment) == 0)
+}
+
+void
+xfsm_properties_set_uchar (XfsmProperties *properties,
+ const gchar *property_name,
+ guchar property_value)
+{
+ GValue *value;
+
+ g_return_if_fail (properties != NULL);
+ g_return_if_fail (property_name != NULL);
+
+ xfsm_verbose ("-> Set uchar (%s, %d)\n", property_name, property_value);
+
+ value = g_tree_lookup (properties->sm_properties, property_name);
+ if (value)
{
- val = xfsm_g_value_new (G_TYPE_STRV);
- g_value_take_boxed (val, g_strdupv (properties->environment));
+ if (!G_VALUE_HOLDS_UCHAR (value))
+ {
+ g_value_unset (value);
+ g_value_init (value, G_TYPE_UCHAR);
+ }
+ g_value_set_uchar (value, property_value);
}
- else if (strcmp(name, SmProcessID) == 0)
+ else
{
- val = xfsm_g_value_new (G_TYPE_STRING);
- g_value_take_string (val, g_strdup (properties->process_id));
+ value = xfsm_g_value_new (G_TYPE_UCHAR);
+ g_value_set_uchar (value, property_value);
+ g_tree_replace (properties->sm_properties,
+ g_strdup (property_name),
+ value);
}
- else if (strcmp (name, SmProgram) == 0)
+}
+
+
+gboolean
+xfsm_properties_set (XfsmProperties *properties,
+ const gchar *property_name,
+ const GValue *property_value)
+{
+ GValue *new_value;
+
+ g_return_val_if_fail (properties != NULL, FALSE);
+ g_return_val_if_fail (property_name != NULL, FALSE);
+ g_return_val_if_fail (property_value != NULL, FALSE);
+
+ if (!G_VALUE_HOLDS (property_value, G_TYPE_STRV)
+ && !G_VALUE_HOLDS_STRING (property_value)
+ && !G_VALUE_HOLDS_UCHAR (property_value))
{
- val = xfsm_g_value_new (G_TYPE_STRING);
- g_value_take_string (val, g_strdup (properties->program));
+ g_warning ("Unhandled property \"%s\" of type \"%s\"", property_name,
+ g_type_name (G_VALUE_TYPE (property_value)));
+ return FALSE;
}
- else if (strcmp (name, SmRestartCommand) == 0)
+
+ xfsm_verbose ("-> Set (%s)\n", property_name);
+
+ new_value = xfsm_g_value_new (G_VALUE_TYPE (property_value));
+ g_value_copy (property_value, new_value);
+
+ g_tree_replace (properties->sm_properties, g_strdup (property_name), new_value);
+
+ return TRUE;
+}
+
+gboolean
+xfsm_properties_set_from_smprop (XfsmProperties *properties,
+ const SmProp *sm_prop)
+{
+ GValue *value;
+ gchar **value_strv;
+ guchar value_uchar;
+ gint n;
+
+ g_return_val_if_fail (properties != NULL, FALSE);
+ g_return_val_if_fail (sm_prop != NULL, FALSE);
+
+ if (!strcmp (sm_prop->type, SmLISTofARRAY8))
{
- val = xfsm_g_value_new (G_TYPE_STRV);
- g_value_take_boxed (val, g_strdupv (properties->restart_command));
+ if (G_UNLIKELY (!sm_prop->num_vals || !sm_prop->vals))
+ return FALSE;
+
+ value_strv = g_new0 (gchar *, sm_prop->num_vals + 1);
+ for (n = 0; n < sm_prop->num_vals; ++n)
+ value_strv[n] = g_strdup ((const gchar *) sm_prop->vals[n].value);
+
+ xfsm_verbose ("-> Set strv (%s)\n", sm_prop->name);
+
+ /* don't use _set_strv() to avoid a realloc of the whole strv */
+ value = g_tree_lookup (properties->sm_properties, sm_prop->name);
+ if (value)
+ {
+ if (!G_VALUE_HOLDS (value, G_TYPE_STRV))
+ {
+ g_value_unset (value);
+ g_value_init (value, G_TYPE_STRV);
+ }
+ g_value_take_boxed (value, value_strv);
+ }
+ else
+ {
+ value = xfsm_g_value_new (G_TYPE_STRV);
+ g_value_take_boxed (value, value_strv);
+ g_tree_replace (properties->sm_properties,
+ g_strdup (sm_prop->name),
+ value);
+ }
}
- else if (strcmp (name, SmResignCommand) == 0)
+ else if (!strcmp (sm_prop->type, SmARRAY8))
{
- val = xfsm_g_value_new (G_TYPE_STRV);
- g_value_take_boxed (val, g_strdupv (properties->resign_command));
+ if (G_UNLIKELY (!sm_prop->vals[0].value))
+ return FALSE;
+
+ xfsm_properties_set_string (properties, sm_prop->name, sm_prop->vals[0].value);
}
- else if (strcmp (name, SmRestartStyleHint) == 0)
+ else if (!strcmp (sm_prop->type, SmCARD8))
{
- val = xfsm_g_value_new (G_TYPE_UCHAR);
- g_value_set_uchar (val, properties->restart_style_hint);
+ value_uchar = *(guchar *)(sm_prop->vals[0].value);
+ xfsm_properties_set_uchar (properties, sm_prop->name, value_uchar);
}
- else if (strcmp (name, SmShutdownCommand) == 0)
+ else
{
- val = xfsm_g_value_new (G_TYPE_STRV);
- g_value_take_boxed (val, g_strdupv (properties->shutdown_command));
+ g_warning ("Unhandled SMProp type: \"%s\"", sm_prop->type);
+ return FALSE;
}
- else if (strcmp (name, SmUserID) == 0)
+
+ return TRUE;
+}
+
+
+gboolean
+xfsm_properties_remove (XfsmProperties *properties,
+ const gchar *property_name)
+{
+ g_return_val_if_fail (properties != NULL, FALSE);
+ g_return_val_if_fail (property_name != NULL, FALSE);
+
+ xfsm_verbose ("-> Removing (%s)\n", property_name);
+
+ return g_tree_remove (properties->sm_properties, property_name);
+}
+
+
+void
+xfsm_properties_set_default_child_watch (XfsmProperties *properties)
+{
+ if (properties->child_watch_id > 0)
{
- val = xfsm_g_value_new (G_TYPE_STRING);
- g_value_take_string (val, g_strdup (properties->user_id));
+ g_source_remove (properties->child_watch_id);
+ properties->child_watch_id = 0;
}
- else if (strcmp (name, GsmPriority) == 0)
+
+ if (properties->pid != -1)
{
- val = xfsm_g_value_new (G_TYPE_UCHAR);
- g_value_set_uchar (val, properties->priority);
+ /* if the PID is still open, we need to close it,
+ * or it will become a zombie when it quits */
+ g_child_watch_add (properties->pid,
+ (GChildWatchFunc) g_spawn_close_pid,
+ NULL);
+ properties->pid = -1;
}
+}
+
+void
+xfsm_properties_free (XfsmProperties *properties)
+{
+ g_return_if_fail (properties != NULL);
+
+ xfsm_properties_set_default_child_watch (properties);
+
+ if (properties->restart_attempts_reset_id > 0)
+ g_source_remove (properties->restart_attempts_reset_id);
+ 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)
+ g_free (properties->hostname);
+
+ g_tree_destroy (properties->sm_properties);
- return val;
+ g_slice_free (XfsmProperties, properties);
}
diff --git a/xfce4-session/xfsm-properties.h b/xfce4-session/xfsm-properties.h
index 3e66d3ac..f3fd8d3c 100644
--- a/xfce4-session/xfsm-properties.h
+++ b/xfce4-session/xfsm-properties.h
@@ -27,7 +27,8 @@
#include <libxfce4util/libxfce4util.h>
/* GNOME compatibility */
-#define GsmPriority "_GSM_Priority"
+#define GsmPriority "_GSM_Priority"
+#define GsmDesktopFile "_GSM_DesktopFile"
#define MAX_RESTART_ATTEMPTS 5
@@ -38,26 +39,15 @@ struct _XfsmProperties
guint restart_attempts;
guint restart_attempts_reset_id;
- gchar *client_id;
- gchar *hostname;
-
- gchar **clone_command;
- gchar *current_directory;
- gchar **discard_command;
- gchar **environment;
- gint priority;
- gchar *process_id;
- gchar *program;
- gchar **resign_command;
- gchar **restart_command;
- gint restart_style_hint;
- gchar **shutdown_command;
- gchar *user_id;
-
guint startup_timeout_id;
GPid pid;
guint child_watch_id;
+
+ gchar *client_id;
+ gchar *hostname;
+
+ GTree *sm_properties;
};
@@ -79,12 +69,37 @@ XfsmProperties* xfsm_properties_load (XfceRc *rc, const gchar *prefix);
gboolean xfsm_properties_check (const XfsmProperties *properties) G_GNUC_CONST;
-void xfsm_properties_set_default_child_watch (XfsmProperties *properties);
+G_CONST_RETURN gchar *xfsm_properties_get_string (XfsmProperties *properties,
+ const gchar *property_name);
+gchar **xfsm_properties_get_strv (XfsmProperties *properties,
+ const gchar *property_name);
+guchar xfsm_properties_get_uchar (XfsmProperties *properties,
+ const gchar *property_name,
+ guchar default_value);
+
+const GValue *xfsm_properties_get (XfsmProperties *properties,
+ const gchar *property_name);
+
+void xfsm_properties_set_string (XfsmProperties *properties,
+ const gchar *property_name,
+ const gchar *property_value);
+void xfsm_properties_set_strv (XfsmProperties *properties,
+ const gchar *property_name,
+ gchar **property_value);
+void xfsm_properties_set_uchar (XfsmProperties *properties,
+ const gchar *property_name,
+ guchar property_value);
+
+gboolean xfsm_properties_set (XfsmProperties *properties,
+ const gchar *property_name,
+ const GValue *property_value);
+gboolean xfsm_properties_set_from_smprop (XfsmProperties *properties,
+ const SmProp *sm_prop);
+
+gboolean xfsm_properties_remove (XfsmProperties *properties,
+ const gchar *property_name);
-gchar **xfsm_strv_from_smprop (const SmProp *prop);
-
-GValue *xfsm_g_value_from_property (XfsmProperties *properties,
- const gchar *name);
+void xfsm_properties_set_default_child_watch (XfsmProperties *properties);
gint xfsm_properties_compare (const XfsmProperties *a,
const XfsmProperties *b) G_GNUC_CONST;
diff --git a/xfce4-session/xfsm-startup.c b/xfce4-session/xfsm-startup.c
index 23dfec17..caa34f22 100644
--- a/xfce4-session/xfsm-startup.c
+++ b/xfce4-session/xfsm-startup.c
@@ -490,26 +490,31 @@ xfsm_startup_start_properties (XfsmProperties *properties,
{
XfsmStartupData *child_watch_data;
XfsmStartupData *startup_timeout_data;
+ gchar **restart_command;
gchar **argv;
gint argc;
gint n;
+ const gchar *current_directory;
GPid pid;
/* release any possible old resources related to a previous startup */
xfsm_properties_set_default_child_watch (properties);
/* generate the argument vector for the application (expanding variables) */
- argc = g_strv_length (properties->restart_command);
+ restart_command = xfsm_properties_get_strv (properties, SmRestartCommand);
+ argc = g_strv_length (restart_command);
argv = g_new (gchar *, argc + 1);
for (n = 0; n < argc; ++n)
- argv[n] = xfce_expand_variables (properties->restart_command[n], NULL);
+ argv[n] = xfce_expand_variables (restart_command[n], NULL);
argv[n] = NULL;
+ current_directory = xfsm_properties_get_string (properties, SmCurrentDirectory);
+
/* fork a new process for the application */
#ifdef HAVE_VFORK
/* vfork() doesn't allow you to do anything but call exec*() or _exit(),
* so if we need to set the working directory, we can't use vfork() */
- if (properties->current_directory == NULL)
+ if (current_directory == NULL)
pid = vfork ();
else
#endif
@@ -519,10 +524,10 @@ xfsm_startup_start_properties (XfsmProperties *properties,
if (pid == 0)
{
/* execute the application here */
- if (properties->current_directory)
+ if (current_directory)
{
- if (chdir (properties->current_directory))
- g_warning ("Unable to chdir to \"%s\": %s", properties->current_directory, strerror (errno));
+ if (chdir (current_directory))
+ g_warning ("Unable to chdir to \"%s\": %s", current_directory, strerror (errno));
}
execvp (argv[0], argv);
_exit (127);
@@ -602,14 +607,14 @@ xfsm_startup_session_next_prio_group (XfsmManager *manager)
if (properties == NULL)
return FALSE;
- cur_prio_group = properties->priority;
+ cur_prio_group = xfsm_properties_get_uchar (properties, GsmPriority, 50);
xfsm_verbose ("Starting apps in prio group %d\n", cur_prio_group);
while ((properties = g_queue_pop_head (pending_properties)))
{
/* quit if we've hit all the clients in the current prio group */
- if (properties->priority != cur_prio_group)
+ if (xfsm_properties_get_uchar (properties, GsmPriority, 50) != cur_prio_group)
{
/* we're not starting this one yet; put it back */
g_queue_push_head (pending_properties, properties);
@@ -619,8 +624,34 @@ xfsm_startup_session_next_prio_group (XfsmManager *manager)
/* FIXME: splash */
if (G_LIKELY (splash_screen != NULL))
{
- xfsm_splash_screen_next (splash_screen,
- figure_app_name (properties->program));
+ const gchar *app_name = NULL;
+ const gchar *desktop_file;
+ XfceRc *rcfile = NULL;
+
+ desktop_file = xfsm_properties_get_string (properties, GsmDesktopFile);
+
+ if (desktop_file)
+ {
+ rcfile = xfce_rc_simple_open (desktop_file, TRUE);
+ if (rcfile)
+ {
+ xfce_rc_set_group (rcfile, "Desktop Entry");
+ app_name = xfce_rc_read_entry (rcfile, "Name", NULL);
+ }
+ }
+
+ if (!app_name)
+ app_name = figure_app_name (xfsm_properties_get_string (properties,
+ SmProgram));
+
+ xfsm_splash_screen_next (splash_screen, app_name);
+
+ if (rcfile)
+ {
+ /* delay closing because app_name belongs to the rcfile
+ * if we found it in the file */
+ xfce_rc_close (rcfile);
+ }
}
if (G_LIKELY (xfsm_startup_start_properties (properties, manager)))