From edd999ae3841b9f4224ebb4dbd8ec4ce182ce0e7 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Mon, 27 Oct 2008 12:17:02 +0000 Subject: [PATCH] Update smclient from libegg trunk. svn path=/trunk/; revision=3239 --- cut-n-paste/smclient/eggdesktopfile.c | 189 ++++++++++++++++++------ cut-n-paste/smclient/eggdesktopfile.h | 43 +++++- cut-n-paste/smclient/eggsmclient-xsmp.c | 108 +++++++------- cut-n-paste/smclient/eggsmclient.c | 63 +++++--- 4 files changed, 270 insertions(+), 133 deletions(-) diff --git a/cut-n-paste/smclient/eggdesktopfile.c b/cut-n-paste/smclient/eggdesktopfile.c index ccc90830..e8893059 100644 --- a/cut-n-paste/smclient/eggdesktopfile.c +++ b/cut-n-paste/smclient/eggdesktopfile.c @@ -31,9 +31,8 @@ #include #include -#include -#include #include +#include struct EggDesktopFile { GKeyFile *key_file; @@ -56,7 +55,6 @@ struct EggDesktopFile { EggDesktopFile * egg_desktop_file_new (const char *desktop_file_path, GError **error) { - EggDesktopFile *desktop_file; GKeyFile *key_file; key_file = g_key_file_new (); @@ -66,13 +64,8 @@ egg_desktop_file_new (const char *desktop_file_path, GError **error) return NULL; } - desktop_file = egg_desktop_file_new_from_key_file (key_file, - desktop_file_path, - error); - if (!desktop_file) - g_key_file_free (key_file); - - return desktop_file; + return egg_desktop_file_new_from_key_file (key_file, desktop_file_path, + error); } /** @@ -106,9 +99,42 @@ egg_desktop_file_new_from_data_dirs (const char *desktop_file_path, full_path, error); g_free (full_path); - if (!desktop_file) - g_key_file_free (key_file); + return desktop_file; +} + +/** + * egg_desktop_file_new_from_dirs: + * @desktop_file_path: relative path to a Freedesktop-style Desktop file + * @search_dirs: NULL-terminated array of directories to search + * @error: error pointer + * + * Looks for @desktop_file_path in the paths returned from + * g_get_user_data_dir() and g_get_system_data_dirs(), and creates + * a new #EggDesktopFile from it. + * + * Return value: the new #EggDesktopFile, or %NULL on error. + **/ +EggDesktopFile * +egg_desktop_file_new_from_dirs (const char *desktop_file_path, + const char **search_dirs, + GError **error) +{ + EggDesktopFile *desktop_file; + GKeyFile *key_file; + char *full_path; + + key_file = g_key_file_new (); + if (!g_key_file_load_from_dirs (key_file, desktop_file_path, search_dirs, + &full_path, 0, error)) + { + g_key_file_free (key_file); + return NULL; + } + desktop_file = egg_desktop_file_new_from_key_file (key_file, + full_path, + error); + g_free (full_path); return desktop_file; } @@ -119,8 +145,8 @@ egg_desktop_file_new_from_data_dirs (const char *desktop_file_path, * @error: error pointer * * Creates a new #EggDesktopFile for @key_file. Assumes ownership of - * @key_file on success (meaning it will be freed when the desktop_file - * is freed). + * @key_file (on success or failure); you should consider @key_file to + * be freed after calling this function. * * Return value: the new #EggDesktopFile, or %NULL on error. **/ @@ -137,6 +163,7 @@ egg_desktop_file_new_from_key_file (GKeyFile *key_file, g_set_error (error, EGG_DESKTOP_FILE_ERROR, EGG_DESKTOP_FILE_ERROR_INVALID, _("File is not a valid .desktop file")); + g_key_file_free (key_file); return NULL; } @@ -160,13 +187,14 @@ egg_desktop_file_new_from_key_file (GKeyFile *key_file, EGG_DESKTOP_FILE_ERROR_INVALID, _("Unrecognized desktop file Version '%s'"), version); g_free (version); + g_key_file_free (key_file); return NULL; } - else g_free (version); } desktop_file = g_new0 (EggDesktopFile, 1); + desktop_file->key_file = key_file; if (g_path_is_absolute (source)) desktop_file->source = g_filename_to_uri (source, NULL, NULL); @@ -202,7 +230,7 @@ egg_desktop_file_new_from_key_file (GKeyFile *key_file, if (!exec) { egg_desktop_file_free (desktop_file); - g_free(type); + g_free (type); return NULL; } @@ -235,7 +263,7 @@ egg_desktop_file_new_from_key_file (GKeyFile *key_file, if (!url) { egg_desktop_file_free (desktop_file); - g_free(type); + g_free (type); return NULL; } g_free (url); @@ -245,7 +273,7 @@ egg_desktop_file_new_from_key_file (GKeyFile *key_file, else desktop_file->type = EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED; - g_free(type); + g_free (type); /* Check the Icon key */ desktop_file->icon = g_key_file_get_string (key_file, @@ -270,7 +298,6 @@ egg_desktop_file_new_from_key_file (GKeyFile *key_file, } } - desktop_file->key_file = key_file; return desktop_file; } @@ -290,22 +317,6 @@ egg_desktop_file_free (EggDesktopFile *desktop_file) g_free (desktop_file); } -/** - * egg_desktop_file_get_key_file: - * @desktop_file: an #EggDesktopFile - * - * Gets the #GKeyFile associated with @desktop_file. You must not free - * this value, and changes made to it will not be reflected by - * @desktop_file. - * - * Return value: the #GKeyFile associated with @desktop_file. - **/ -GKeyFile * -egg_desktop_file_get_key_file (EggDesktopFile *desktop_file) -{ - return desktop_file->key_file; -} - /** * egg_desktop_file_get_source: * @desktop_file: an #EggDesktopFile @@ -369,6 +380,81 @@ egg_desktop_file_get_icon (EggDesktopFile *desktop_file) return desktop_file->icon; } +gboolean +egg_desktop_file_has_key (EggDesktopFile *desktop_file, + const char *key, + GError **error) +{ + return g_key_file_has_key (desktop_file->key_file, + EGG_DESKTOP_FILE_GROUP, key, + error); +} + +char * +egg_desktop_file_get_string (EggDesktopFile *desktop_file, + const char *key, + GError **error) +{ + return g_key_file_get_string (desktop_file->key_file, + EGG_DESKTOP_FILE_GROUP, key, + error); +} + +char * +egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file, + const char *key, + const char *locale, + GError **error) +{ + return g_key_file_get_locale_string (desktop_file->key_file, + EGG_DESKTOP_FILE_GROUP, key, locale, + error); +} + +gboolean +egg_desktop_file_get_boolean (EggDesktopFile *desktop_file, + const char *key, + GError **error) +{ + return g_key_file_get_boolean (desktop_file->key_file, + EGG_DESKTOP_FILE_GROUP, key, + error); +} + +double +egg_desktop_file_get_numeric (EggDesktopFile *desktop_file, + const char *key, + GError **error) +{ + return g_key_file_get_double (desktop_file->key_file, + EGG_DESKTOP_FILE_GROUP, key, + error); +} + +char ** +egg_desktop_file_get_string_list (EggDesktopFile *desktop_file, + const char *key, + gsize *length, + GError **error) +{ + return g_key_file_get_string_list (desktop_file->key_file, + EGG_DESKTOP_FILE_GROUP, key, length, + error); +} + +char ** +egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file, + const char *key, + const char *locale, + gsize *length, + GError **error) +{ + return g_key_file_get_locale_string_list (desktop_file->key_file, + EGG_DESKTOP_FILE_GROUP, key, + locale, length, + error); +} + /** * egg_desktop_file_can_launch: * @desktop_file: an #EggDesktopFile @@ -823,7 +909,7 @@ parse_link (EggDesktopFile *desktop_file, return TRUE; } -#ifdef HAVE_GDK_X11_DISPLAY_BROADCAST_STARTUP_MESSAGE +#if GTK_CHECK_VERSION (2, 12, 0) static char * start_startup_notification (GdkDisplay *display, EggDesktopFile *desktop_file, @@ -934,21 +1020,29 @@ set_startup_notification_timeout (GdkDisplay *display, g_timeout_add (EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH, startup_notification_timeout, sn_data); } -#endif /* HAVE_GDK_X11_DISPLAY_BROADCAST_STARTUP_MESSAGE */ - -extern char **environ; +#endif /* GTK 2.12 */ static GPtrArray * array_putenv (GPtrArray *env, char *variable) { - int i, keylen; + guint i, keylen; if (!env) { + char **envp; + env = g_ptr_array_new (); - for (i = 0; environ[i]; i++) - g_ptr_array_add (env, g_strdup (environ[i])); + envp = g_listenv (); + for (i = 0; envp[i]; i++) + { + const char *value; + + value = g_getenv (envp[i]); + g_ptr_array_add (env, g_strdup_printf ("%s=%s", envp[i], + value ? value : "")); + } + g_strfreev (envp); } keylen = strcspn (variable, "="); @@ -1113,7 +1207,7 @@ egg_desktop_file_launchv (EggDesktopFile *desktop_file, } g_free (command); -#ifdef HAVE_GDK_X11_DISPLAY_BROADCAST_STARTUP_MESSAGE +#if GTK_CHECK_VERSION (2, 12, 0) startup_id = start_startup_notification (display, desktop_file, argv[0], screen_num, workspace, launch_time); @@ -1126,7 +1220,10 @@ egg_desktop_file_launchv (EggDesktopFile *desktop_file, } #else startup_id = NULL; -#endif /* HAVE_GDK_X11_DISPLAY_BROADCAST_STARTUP_MESSAGE */ +#endif /* GTK 2.12 */ + + if (env != NULL) + g_ptr_array_add (env, NULL); current_success = g_spawn_async_with_pipes (directory, @@ -1141,7 +1238,7 @@ egg_desktop_file_launchv (EggDesktopFile *desktop_file, if (startup_id) { -#ifdef HAVE_GDK_X11_DISPLAY_BROADCAST_STARTUP_MESSAGE +#if GTK_CHECK_VERSION (2, 12, 0) if (current_success) { set_startup_notification_timeout (display, startup_id); @@ -1152,7 +1249,7 @@ egg_desktop_file_launchv (EggDesktopFile *desktop_file, g_free (startup_id); } else -#endif /* HAVE_GDK_X11_DISPLAY_BROADCAST_STARTUP_MESSAGE */ +#endif /* GTK 2.12 */ g_free (startup_id); } else if (ret_startup_id) diff --git a/cut-n-paste/smclient/eggdesktopfile.h b/cut-n-paste/smclient/eggdesktopfile.h index f1305413..f8a3d3e0 100644 --- a/cut-n-paste/smclient/eggdesktopfile.h +++ b/cut-n-paste/smclient/eggdesktopfile.h @@ -31,22 +31,23 @@ typedef enum { EGG_DESKTOP_FILE_TYPE_APPLICATION, EGG_DESKTOP_FILE_TYPE_LINK, - EGG_DESKTOP_FILE_TYPE_DIRECTORY, + EGG_DESKTOP_FILE_TYPE_DIRECTORY } EggDesktopFileType; EggDesktopFile *egg_desktop_file_new (const char *desktop_file_path, GError **error); -EggDesktopFile *egg_desktop_file_new_from_data_dirs (const char *desktop_file_path, - GError **error); -EggDesktopFile *egg_desktop_file_new_from_key_file (GKeyFile *desktop, +EggDesktopFile *egg_desktop_file_new_from_data_dirs (const char *desktop_file_path, + GError **error); +EggDesktopFile *egg_desktop_file_new_from_dirs (const char *desktop_file_path, + const char **search_dirs, + GError **error); +EggDesktopFile *egg_desktop_file_new_from_key_file (GKeyFile *key_file, const char *source, GError **error); void egg_desktop_file_free (EggDesktopFile *desktop_file); -GKeyFile *egg_desktop_file_get_key_file (EggDesktopFile *desktop_file); - const char *egg_desktop_file_get_source (EggDesktopFile *desktop_file); EggDesktopFileType egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file); @@ -109,6 +110,34 @@ typedef enum { #define EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS "StartupWMClass" #define EGG_DESKTOP_FILE_KEY_URL "URL" +/* Accessors */ +gboolean egg_desktop_file_has_key (EggDesktopFile *desktop_file, + const char *key, + GError **error); +char *egg_desktop_file_get_string (EggDesktopFile *desktop_file, + const char *key, + GError **error) G_GNUC_MALLOC; +char *egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file, + const char *key, + const char *locale, + GError **error) G_GNUC_MALLOC; +gboolean egg_desktop_file_get_boolean (EggDesktopFile *desktop_file, + const char *key, + GError **error); +double egg_desktop_file_get_numeric (EggDesktopFile *desktop_file, + const char *key, + GError **error); +char **egg_desktop_file_get_string_list (EggDesktopFile *desktop_file, + const char *key, + gsize *length, + GError **error) G_GNUC_MALLOC; +char **egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file, + const char *key, + const char *locale, + gsize *length, + GError **error) G_GNUC_MALLOC; + + /* Errors */ #define EGG_DESKTOP_FILE_ERROR egg_desktop_file_error_quark() @@ -117,7 +146,7 @@ GQuark egg_desktop_file_error_quark (void); typedef enum { EGG_DESKTOP_FILE_ERROR_INVALID, EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE, - EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION, + EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION } EggDesktopFileError; /* Global application desktop file */ diff --git a/cut-n-paste/smclient/eggsmclient-xsmp.c b/cut-n-paste/smclient/eggsmclient-xsmp.c index eebce07e..e4b11f62 100644 --- a/cut-n-paste/smclient/eggsmclient-xsmp.c +++ b/cut-n-paste/smclient/eggsmclient-xsmp.c @@ -62,11 +62,10 @@ typedef enum XSMP_STATE_INTERACT, XSMP_STATE_SAVE_YOURSELF_DONE, XSMP_STATE_SHUTDOWN_CANCELLED, - XSMP_STATE_CONNECTION_CLOSED, + XSMP_STATE_CONNECTION_CLOSED } EggSMClientXSMPState; static const char *state_names[] = { - "start", "idle", "save-yourself", "interact-request", @@ -221,19 +220,14 @@ sm_client_xsmp_set_initial_properties (gpointer user_data) desktop_file = egg_get_desktop_file (); if (desktop_file) { - GKeyFile *key_file; GError *err = NULL; char *cmdline, **argv; int argc; - key_file = egg_desktop_file_get_key_file (desktop_file); - if (xsmp->restart_style == SmRestartIfRunning) { - if (g_key_file_has_key (key_file, EGG_DESKTOP_FILE_GROUP, - "X-GNOME-AutoRestart", NULL) && - g_key_file_get_boolean (key_file, EGG_DESKTOP_FILE_GROUP, - "X-GNOME-AutoRestart", NULL)) + if (egg_desktop_file_get_boolean (desktop_file, + "X-GNOME-AutoRestart", NULL)) xsmp->restart_style = SmRestartImmediately; } @@ -771,30 +765,6 @@ do_save_yourself (EggSMClientXSMP *xsmp) xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE; } -static void -merge_keyfiles (GKeyFile *dest, GKeyFile *source) -{ - int g, k; - char **groups, **keys, *value; - - groups = g_key_file_get_groups (source, NULL); - for (g = 0; groups[g]; g++) - { - keys = g_key_file_get_keys (source, groups[g], NULL, NULL); - for (k = 0; keys[k]; k++) - { - value = g_key_file_get_value (source, groups[g], keys[k], NULL); - if (value) - { - g_key_file_set_value (dest, groups[g], keys[k], value); - g_free (value); - } - } - g_strfreev (keys); - } - g_strfreev (groups); -} - static void save_state (EggSMClientXSMP *xsmp) { @@ -825,30 +795,54 @@ save_state (EggSMClientXSMP *xsmp) if (desktop_file) { GKeyFile *merged_file; - char *exec; - int i; merged_file = g_key_file_new (); - merge_keyfiles (merged_file, egg_desktop_file_get_key_file (desktop_file)); - merge_keyfiles (merged_file, state_file); - - g_key_file_free (state_file); - state_file = merged_file; - - /* Update Exec key using "--sm-client-state-file %k" */ - restart = generate_command (xsmp->restart_command, - NULL, "%k"); - for (i = 0; i < restart->len; i++) - restart->pdata[i] = g_shell_quote (restart->pdata[i]); - g_ptr_array_add (restart, NULL); - exec = g_strjoinv (" ", (char **)restart->pdata); - g_strfreev ((char **)restart->pdata); - g_ptr_array_free (restart, FALSE); - - g_key_file_set_string (state_file, EGG_DESKTOP_FILE_GROUP, - EGG_DESKTOP_FILE_KEY_EXEC, - exec); - g_free (exec); + if (g_key_file_load_from_file (merged_file, + egg_desktop_file_get_source (desktop_file), + G_KEY_FILE_KEEP_COMMENTS | + G_KEY_FILE_KEEP_TRANSLATIONS, NULL)) + { + guint g, k, i; + char **groups, **keys, *value, *exec; + + groups = g_key_file_get_groups (state_file, NULL); + for (g = 0; groups[g]; g++) + { + keys = g_key_file_get_keys (state_file, groups[g], NULL, NULL); + for (k = 0; keys[k]; k++) + { + value = g_key_file_get_value (state_file, groups[g], + keys[k], NULL); + if (value) + { + g_key_file_set_value (merged_file, groups[g], + keys[k], value); + g_free (value); + } + } + g_strfreev (keys); + } + g_strfreev (groups); + + g_key_file_free (state_file); + state_file = merged_file; + + /* Update Exec key using "--sm-client-state-file %k" */ + restart = generate_command (xsmp->restart_command, + NULL, "%k"); + for (i = 0; i < restart->len; i++) + restart->pdata[i] = g_shell_quote (restart->pdata[i]); + g_ptr_array_add (restart, NULL); + exec = g_strjoinv (" ", (char **)restart->pdata); + g_strfreev ((char **)restart->pdata); + g_ptr_array_free (restart, FALSE); + + g_key_file_set_string (state_file, EGG_DESKTOP_FILE_GROUP, + EGG_DESKTOP_FILE_KEY_EXEC, + exec); + g_free (exec); + + } } /* Now write state_file to disk. (We can't use mktemp(), because @@ -1077,7 +1071,7 @@ set_properties (EggSMClientXSMP *xsmp, ...) GPtrArray *props; SmProp *prop; va_list ap; - int i; + guint i; props = g_ptr_array_new (); @@ -1170,7 +1164,7 @@ ptrarray_prop (const char *name, GPtrArray *values) SmProp *prop; SmPropValue pv; GArray *vals; - int i; + guint i; prop = g_new (SmProp, 1); prop->name = (char *)name; diff --git a/cut-n-paste/smclient/eggsmclient.c b/cut-n-paste/smclient/eggsmclient.c index 642703fa..8e2254f0 100644 --- a/cut-n-paste/smclient/eggsmclient.c +++ b/cut-n-paste/smclient/eggsmclient.c @@ -38,7 +38,7 @@ enum { LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL]; struct _EggSMClientPrivate { GKeyFile *state_file; @@ -179,19 +179,6 @@ static gboolean sm_client_disable = FALSE; static char *sm_client_state_file = NULL; static char *sm_client_id = NULL; -static GOptionEntry entries[] = { - { "sm-client-disable", 0, 0, - G_OPTION_ARG_NONE, &sm_client_disable, - N_("Disable connection to session manager"), NULL }, - { "sm-client-state-file", 0, 0, - G_OPTION_ARG_STRING, &sm_client_state_file, - N_("Specify file containing saved configuration"), N_("FILE") }, - { "sm-client-id", 0, 0, - G_OPTION_ARG_STRING, &sm_client_id, - N_("Specify session management ID"), N_("ID") }, - { NULL } -}; - static gboolean sm_client_post_parse_func (GOptionContext *context, GOptionGroup *group, @@ -200,6 +187,20 @@ sm_client_post_parse_func (GOptionContext *context, { EggSMClient *client = egg_sm_client_get (); + if (sm_client_id == NULL) + { + const gchar *desktop_autostart_id; + + desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID"); + + if (desktop_autostart_id != NULL) + sm_client_id = g_strdup (desktop_autostart_id); + } + + /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to + * use the same client id. */ + g_unsetenv ("DESKTOP_AUTOSTART_ID"); + if (EGG_SM_CLIENT_GET_CLASS (client)->startup) EGG_SM_CLIENT_GET_CLASS (client)->startup (client, sm_client_id); return TRUE; @@ -217,6 +218,22 @@ sm_client_post_parse_func (GOptionContext *context, GOptionGroup * egg_sm_client_get_option_group (void) { + const GOptionEntry entries[] = { + { "sm-client-disable", 0, 0, + G_OPTION_ARG_NONE, &sm_client_disable, + N_("Disable connection to session manager"), NULL }, + { "sm-client-state-file", 0, 0, + G_OPTION_ARG_FILENAME, &sm_client_state_file, + N_("Specify file containing saved configuration"), N_("FILE") }, + { "sm-client-id", 0, 0, + G_OPTION_ARG_STRING, &sm_client_id, + N_("Specify session management ID"), N_("ID") }, + /* Compatibility options */ + { "sm-disable", 0, G_OPTION_FLAG_HIDDEN, + G_OPTION_ARG_NONE, &sm_client_disable, + NULL, NULL }, + { NULL } + }; GOptionGroup *group; /* Use our own debug handler for the "EggSMClient" domain. */ @@ -224,8 +241,8 @@ egg_sm_client_get_option_group (void) egg_sm_client_debug_handler, NULL); group = g_option_group_new ("sm-client", - _("Session Management Options"), - _("Show Session Management options"), + _("Session management options:"), + _("Show session management options"), NULL, NULL); g_option_group_add_entries (group, entries); g_option_group_set_parse_hooks (group, NULL, sm_client_post_parse_func); @@ -300,16 +317,16 @@ egg_sm_client_get (void) #elif defined (GDK_WINDOWING_QUARTZ) global_client = egg_sm_client_osx_new (); #else - /* If both D-Bus and XSMP are compiled in, try D-Bus first - * and fall back to XSMP if D-Bus session management isn't - * available. + /* If both D-Bus and XSMP are compiled in, try XSMP first + * (since it supports state saving) and fall back to D-Bus + * if XSMP isn't available. */ -# ifdef EGG_SM_CLIENT_BACKEND_DBUS - global_client = egg_sm_client_dbus_new (); -# endif # ifdef EGG_SM_CLIENT_BACKEND_XSMP + global_client = egg_sm_client_xsmp_new (); +# endif +# ifdef EGG_SM_CLIENT_BACKEND_DBUS if (!global_client) - global_client = egg_sm_client_xsmp_new (); + global_client = egg_sm_client_dbus_new (); # endif #endif } -- 2.43.5