You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1187 lines
44 KiB
1187 lines
44 KiB
7 years ago
|
From 5e8c5967d65f61a58241c6429eb79650870fa7d0 Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Mon, 27 Nov 2017 15:40:54 -0500
|
||
|
Subject: [PATCH 1/2] save: make sure app state is written into desktop file
|
||
|
|
||
|
There are a number of important bits of app state written into
|
||
|
an applications desktop file that needs to be restored when
|
||
|
the session is saved. For instance, the phase in which the client
|
||
|
should get started.
|
||
|
|
||
|
That state is currently stored on the GsmApp object, which is
|
||
|
inaccessible, from the client save function.
|
||
|
|
||
|
This commit adds the neccesary plumbing to route the GsmApp object
|
||
|
associated with a client to the client save function, and also
|
||
|
adds code to allow the app object to augment the client keyfile at
|
||
|
save time.
|
||
|
|
||
|
https://bugzilla.gnome.org/show_bug.cgi?id=790913
|
||
|
|
||
|
https://bugzilla.redhat.com/show_bug.cgi?id=1529175
|
||
|
---
|
||
|
gnome-session/gsm-app.c | 9 +++++
|
||
|
gnome-session/gsm-app.h | 8 +++++
|
||
|
gnome-session/gsm-autostart-app.c | 70 +++++++++++++++++++++++++++++++++++++++
|
||
|
gnome-session/gsm-client.c | 3 +-
|
||
|
gnome-session/gsm-client.h | 3 ++
|
||
|
gnome-session/gsm-dbus-client.c | 1 +
|
||
|
gnome-session/gsm-manager.c | 4 +--
|
||
|
gnome-session/gsm-session-save.c | 41 +++++++++++++++++------
|
||
|
gnome-session/gsm-session-save.h | 1 +
|
||
|
gnome-session/gsm-xsmp-client.c | 9 +++++
|
||
|
10 files changed, 135 insertions(+), 14 deletions(-)
|
||
|
|
||
|
diff --git a/gnome-session/gsm-app.c b/gnome-session/gsm-app.c
|
||
|
index 845e067a..d1ef89a8 100644
|
||
|
--- a/gnome-session/gsm-app.c
|
||
|
+++ b/gnome-session/gsm-app.c
|
||
|
@@ -531,30 +531,39 @@ gsm_app_exited (GsmApp *app,
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gsm_app_died (GsmApp *app,
|
||
|
int signal)
|
||
|
{
|
||
|
g_return_if_fail (GSM_IS_APP (app));
|
||
|
|
||
|
g_signal_emit (app, signals[DIED], 0, signal);
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
gsm_app_get_registered (GsmApp *app)
|
||
|
{
|
||
|
g_return_val_if_fail (GSM_IS_APP (app), FALSE);
|
||
|
|
||
|
return app->priv->registered;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gsm_app_set_registered (GsmApp *app,
|
||
|
gboolean registered)
|
||
|
{
|
||
|
g_return_if_fail (GSM_IS_APP (app));
|
||
|
|
||
|
if (app->priv->registered != registered) {
|
||
|
app->priv->registered = registered;
|
||
|
g_object_notify (G_OBJECT (app), "registered");
|
||
|
}
|
||
|
}
|
||
|
+
|
||
|
+gboolean
|
||
|
+gsm_app_save_to_keyfile (GsmApp *app,
|
||
|
+ GKeyFile *keyfile,
|
||
|
+ GError **error)
|
||
|
+{
|
||
|
+ g_debug ("Saving app: %s", app->priv->id);
|
||
|
+ return GSM_APP_GET_CLASS (app)->impl_save_to_keyfile (app, keyfile, error);
|
||
|
+}
|
||
|
diff --git a/gnome-session/gsm-app.h b/gnome-session/gsm-app.h
|
||
|
index 14a9f94b..f38b3be4 100644
|
||
|
--- a/gnome-session/gsm-app.h
|
||
|
+++ b/gnome-session/gsm-app.h
|
||
|
@@ -47,80 +47,88 @@ struct _GsmApp
|
||
|
};
|
||
|
|
||
|
struct _GsmAppClass
|
||
|
{
|
||
|
GObjectClass parent_class;
|
||
|
|
||
|
/* signals */
|
||
|
void (*exited) (GsmApp *app,
|
||
|
guchar exit_code);
|
||
|
void (*died) (GsmApp *app,
|
||
|
int signal);
|
||
|
|
||
|
/* virtual methods */
|
||
|
gboolean (*impl_start) (GsmApp *app,
|
||
|
GError **error);
|
||
|
gboolean (*impl_restart) (GsmApp *app,
|
||
|
GError **error);
|
||
|
gboolean (*impl_stop) (GsmApp *app,
|
||
|
GError **error);
|
||
|
gboolean (*impl_provides) (GsmApp *app,
|
||
|
const char *service);
|
||
|
char ** (*impl_get_provides) (GsmApp *app);
|
||
|
gboolean (*impl_has_autostart_condition) (GsmApp *app,
|
||
|
const char *service);
|
||
|
gboolean (*impl_is_running) (GsmApp *app);
|
||
|
|
||
|
gboolean (*impl_get_autorestart) (GsmApp *app);
|
||
|
const char *(*impl_get_app_id) (GsmApp *app);
|
||
|
gboolean (*impl_is_disabled) (GsmApp *app);
|
||
|
gboolean (*impl_is_conditionally_disabled) (GsmApp *app);
|
||
|
+
|
||
|
+ gboolean (*impl_save_to_keyfile) (GsmApp *app,
|
||
|
+ GKeyFile *keyfile,
|
||
|
+ GError **error);
|
||
|
};
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
GSM_APP_ERROR_GENERAL = 0,
|
||
|
GSM_APP_ERROR_RESTART_LIMIT,
|
||
|
GSM_APP_ERROR_START,
|
||
|
GSM_APP_ERROR_STOP,
|
||
|
GSM_APP_NUM_ERRORS
|
||
|
} GsmAppError;
|
||
|
|
||
|
#define GSM_APP_ERROR gsm_app_error_quark ()
|
||
|
|
||
|
GQuark gsm_app_error_quark (void);
|
||
|
GType gsm_app_get_type (void) G_GNUC_CONST;
|
||
|
|
||
|
gboolean gsm_app_peek_autorestart (GsmApp *app);
|
||
|
|
||
|
const char *gsm_app_peek_id (GsmApp *app);
|
||
|
const char *gsm_app_peek_app_id (GsmApp *app);
|
||
|
const char *gsm_app_peek_startup_id (GsmApp *app);
|
||
|
GsmManagerPhase gsm_app_peek_phase (GsmApp *app);
|
||
|
gboolean gsm_app_peek_is_disabled (GsmApp *app);
|
||
|
gboolean gsm_app_peek_is_conditionally_disabled (GsmApp *app);
|
||
|
|
||
|
gboolean gsm_app_start (GsmApp *app,
|
||
|
GError **error);
|
||
|
gboolean gsm_app_restart (GsmApp *app,
|
||
|
GError **error);
|
||
|
gboolean gsm_app_stop (GsmApp *app,
|
||
|
GError **error);
|
||
|
gboolean gsm_app_is_running (GsmApp *app);
|
||
|
|
||
|
void gsm_app_exited (GsmApp *app,
|
||
|
guchar exit_code);
|
||
|
void gsm_app_died (GsmApp *app,
|
||
|
int signal);
|
||
|
|
||
|
gboolean gsm_app_provides (GsmApp *app,
|
||
|
const char *service);
|
||
|
char **gsm_app_get_provides (GsmApp *app);
|
||
|
gboolean gsm_app_has_autostart_condition (GsmApp *app,
|
||
|
const char *condition);
|
||
|
gboolean gsm_app_get_registered (GsmApp *app);
|
||
|
void gsm_app_set_registered (GsmApp *app,
|
||
|
gboolean registered);
|
||
|
|
||
|
+gboolean gsm_app_save_to_keyfile (GsmApp *app,
|
||
|
+ GKeyFile *keyfile,
|
||
|
+ GError **error);
|
||
|
+
|
||
|
G_END_DECLS
|
||
|
|
||
|
#endif /* __GSM_APP_H__ */
|
||
|
diff --git a/gnome-session/gsm-autostart-app.c b/gnome-session/gsm-autostart-app.c
|
||
|
index 870b1516..9eb1db5b 100644
|
||
|
--- a/gnome-session/gsm-autostart-app.c
|
||
|
+++ b/gnome-session/gsm-autostart-app.c
|
||
|
@@ -1400,86 +1400,156 @@ gsm_autostart_app_get_autorestart (GsmApp *app)
|
||
|
static const char *
|
||
|
gsm_autostart_app_get_app_id (GsmApp *app)
|
||
|
{
|
||
|
if (GSM_AUTOSTART_APP (app)->priv->app_info == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return g_app_info_get_id (G_APP_INFO (GSM_AUTOSTART_APP (app)->priv->app_info));
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
gsm_autostart_app_initable_init (GInitable *initable,
|
||
|
GCancellable *cancellable,
|
||
|
GError **error)
|
||
|
{
|
||
|
GsmAutostartApp *app = GSM_AUTOSTART_APP (initable);
|
||
|
|
||
|
g_assert (app->priv->desktop_filename != NULL);
|
||
|
app->priv->app_info = g_desktop_app_info_new_from_filename (app->priv->desktop_filename);
|
||
|
if (app->priv->app_info == NULL) {
|
||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||
|
"Could not parse desktop file %s or it references a not found TryExec binary", app->priv->desktop_id);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
load_desktop_file (app);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
+static gboolean
|
||
|
+gsm_autostart_app_save_to_keyfile (GsmApp *base_app,
|
||
|
+ GKeyFile *keyfile,
|
||
|
+ GError **error)
|
||
|
+{
|
||
|
+ GsmAutostartApp *app = GSM_AUTOSTART_APP (base_app);
|
||
|
+ char **provides = NULL;
|
||
|
+ char *dbus_name;
|
||
|
+ char *phase;
|
||
|
+ gboolean res;
|
||
|
+
|
||
|
+ provides = gsm_app_get_provides (base_app);
|
||
|
+ if (provides != NULL) {
|
||
|
+ g_key_file_set_string_list (keyfile,
|
||
|
+ G_KEY_FILE_DESKTOP_GROUP,
|
||
|
+ GSM_AUTOSTART_APP_PROVIDES_KEY,
|
||
|
+ (const char * const *)
|
||
|
+ provides,
|
||
|
+ g_strv_length (provides));
|
||
|
+ g_strfreev (provides);
|
||
|
+ }
|
||
|
+
|
||
|
+ phase = g_desktop_app_info_get_string (app->priv->app_info,
|
||
|
+ GSM_AUTOSTART_APP_PHASE_KEY);
|
||
|
+ if (phase != NULL) {
|
||
|
+ g_key_file_set_string (keyfile,
|
||
|
+ G_KEY_FILE_DESKTOP_GROUP,
|
||
|
+ GSM_AUTOSTART_APP_PHASE_KEY,
|
||
|
+ phase);
|
||
|
+ g_free (phase);
|
||
|
+ }
|
||
|
+
|
||
|
+ dbus_name = g_desktop_app_info_get_string (app->priv->app_info,
|
||
|
+ GSM_AUTOSTART_APP_DBUS_NAME_KEY);
|
||
|
+ if (dbus_name != NULL) {
|
||
|
+ g_key_file_set_string (keyfile,
|
||
|
+ G_KEY_FILE_DESKTOP_GROUP,
|
||
|
+ GSM_AUTOSTART_APP_DBUS_NAME_KEY,
|
||
|
+ dbus_name);
|
||
|
+ g_free (dbus_name);
|
||
|
+ }
|
||
|
+
|
||
|
+ res = g_desktop_app_info_has_key (app->priv->app_info,
|
||
|
+ GSM_AUTOSTART_APP_AUTORESTART_KEY);
|
||
|
+ if (res) {
|
||
|
+ g_key_file_set_boolean (keyfile,
|
||
|
+ G_KEY_FILE_DESKTOP_GROUP,
|
||
|
+ GSM_AUTOSTART_APP_AUTORESTART_KEY,
|
||
|
+ g_desktop_app_info_get_boolean (app->priv->app_info,
|
||
|
+ GSM_AUTOSTART_APP_AUTORESTART_KEY));
|
||
|
+ }
|
||
|
+
|
||
|
+ res = g_desktop_app_info_has_key (app->priv->app_info,
|
||
|
+ GSM_AUTOSTART_APP_AUTORESTART_KEY);
|
||
|
+ if (res) {
|
||
|
+ char *autostart_condition;
|
||
|
+
|
||
|
+ autostart_condition = g_desktop_app_info_get_string (app->priv->app_info, "AutostartCondition");
|
||
|
+
|
||
|
+ g_key_file_set_string (keyfile,
|
||
|
+ G_KEY_FILE_DESKTOP_GROUP,
|
||
|
+ "AutostartCondition",
|
||
|
+ autostart_condition);
|
||
|
+ g_free (autostart_condition);
|
||
|
+ }
|
||
|
+
|
||
|
+ return TRUE;
|
||
|
+}
|
||
|
+
|
||
|
static void
|
||
|
gsm_autostart_app_initable_iface_init (GInitableIface *iface)
|
||
|
{
|
||
|
iface->init = gsm_autostart_app_initable_init;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gsm_autostart_app_class_init (GsmAutostartAppClass *klass)
|
||
|
{
|
||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||
|
GsmAppClass *app_class = GSM_APP_CLASS (klass);
|
||
|
|
||
|
object_class->set_property = gsm_autostart_app_set_property;
|
||
|
object_class->get_property = gsm_autostart_app_get_property;
|
||
|
object_class->dispose = gsm_autostart_app_dispose;
|
||
|
|
||
|
app_class->impl_is_disabled = is_disabled;
|
||
|
app_class->impl_is_conditionally_disabled = is_conditionally_disabled;
|
||
|
app_class->impl_is_running = is_running;
|
||
|
app_class->impl_start = gsm_autostart_app_start;
|
||
|
app_class->impl_restart = gsm_autostart_app_restart;
|
||
|
app_class->impl_stop = gsm_autostart_app_stop;
|
||
|
app_class->impl_provides = gsm_autostart_app_provides;
|
||
|
app_class->impl_get_provides = gsm_autostart_app_get_provides;
|
||
|
app_class->impl_has_autostart_condition = gsm_autostart_app_has_autostart_condition;
|
||
|
app_class->impl_get_app_id = gsm_autostart_app_get_app_id;
|
||
|
app_class->impl_get_autorestart = gsm_autostart_app_get_autorestart;
|
||
|
+ app_class->impl_save_to_keyfile = gsm_autostart_app_save_to_keyfile;
|
||
|
|
||
|
g_object_class_install_property (object_class,
|
||
|
PROP_DESKTOP_FILENAME,
|
||
|
g_param_spec_string ("desktop-filename",
|
||
|
"Desktop filename",
|
||
|
"Freedesktop .desktop file",
|
||
|
NULL,
|
||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||
|
signals[CONDITION_CHANGED] =
|
||
|
g_signal_new ("condition-changed",
|
||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||
|
G_SIGNAL_RUN_LAST,
|
||
|
G_STRUCT_OFFSET (GsmAutostartAppClass, condition_changed),
|
||
|
NULL, NULL, NULL,
|
||
|
G_TYPE_NONE,
|
||
|
1,
|
||
|
G_TYPE_BOOLEAN);
|
||
|
|
||
|
g_type_class_add_private (object_class, sizeof (GsmAutostartAppPrivate));
|
||
|
}
|
||
|
|
||
|
GsmApp *
|
||
|
gsm_autostart_app_new (const char *desktop_file,
|
||
|
GError **error)
|
||
|
{
|
||
|
return (GsmApp*) g_initable_new (GSM_TYPE_AUTOSTART_APP, NULL, error,
|
||
|
"desktop-filename", desktop_file,
|
||
|
NULL);
|
||
|
}
|
||
|
diff --git a/gnome-session/gsm-client.c b/gnome-session/gsm-client.c
|
||
|
index 7b78d9e1..3f216b22 100644
|
||
|
--- a/gnome-session/gsm-client.c
|
||
|
+++ b/gnome-session/gsm-client.c
|
||
|
@@ -526,47 +526,48 @@ gsm_client_end_session (GsmClient *client,
|
||
|
return GSM_CLIENT_GET_CLASS (client)->impl_end_session (client, flags, error);
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
gsm_client_stop (GsmClient *client,
|
||
|
GError **error)
|
||
|
{
|
||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
|
||
|
|
||
|
return GSM_CLIENT_GET_CLASS (client)->impl_stop (client, error);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gsm_client_disconnected (GsmClient *client)
|
||
|
{
|
||
|
g_signal_emit (client, signals[DISCONNECTED], 0);
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
gsm_client_request_save (GsmClient *client,
|
||
|
guint flags,
|
||
|
GError **error)
|
||
|
{
|
||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
|
||
|
|
||
|
return GSM_CLIENT_GET_CLASS (client)->impl_request_save (client, flags, error);
|
||
|
}
|
||
|
|
||
|
GKeyFile *
|
||
|
gsm_client_save (GsmClient *client,
|
||
|
+ GsmApp *app,
|
||
|
GError **error)
|
||
|
{
|
||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
|
||
|
|
||
|
- return GSM_CLIENT_GET_CLASS (client)->impl_save (client, error);
|
||
|
+ return GSM_CLIENT_GET_CLASS (client)->impl_save (client, app, error);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gsm_client_end_session_response (GsmClient *client,
|
||
|
gboolean is_ok,
|
||
|
gboolean do_last,
|
||
|
gboolean cancel,
|
||
|
const char *reason)
|
||
|
{
|
||
|
g_signal_emit (client, signals[END_SESSION_RESPONSE], 0,
|
||
|
is_ok, do_last, cancel, reason);
|
||
|
}
|
||
|
diff --git a/gnome-session/gsm-client.h b/gnome-session/gsm-client.h
|
||
|
index f79896b3..19c9cd8d 100644
|
||
|
--- a/gnome-session/gsm-client.h
|
||
|
+++ b/gnome-session/gsm-client.h
|
||
|
@@ -6,60 +6,61 @@
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License as
|
||
|
* published by the Free Software Foundation; either version 2 of the
|
||
|
* License, or (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#ifndef __GSM_CLIENT_H__
|
||
|
#define __GSM_CLIENT_H__
|
||
|
|
||
|
#include <glib.h>
|
||
|
#include <glib-object.h>
|
||
|
#include <sys/types.h>
|
||
|
|
||
|
G_BEGIN_DECLS
|
||
|
|
||
|
#define GSM_TYPE_CLIENT (gsm_client_get_type ())
|
||
|
#define GSM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_CLIENT, GsmClient))
|
||
|
#define GSM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_CLIENT, GsmClientClass))
|
||
|
#define GSM_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_CLIENT))
|
||
|
#define GSM_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_CLIENT))
|
||
|
#define GSM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_CLIENT, GsmClientClass))
|
||
|
|
||
|
+typedef struct _GsmApp GsmApp;
|
||
|
typedef struct _GsmClient GsmClient;
|
||
|
typedef struct _GsmClientClass GsmClientClass;
|
||
|
|
||
|
typedef struct GsmClientPrivate GsmClientPrivate;
|
||
|
|
||
|
typedef enum {
|
||
|
GSM_CLIENT_UNREGISTERED = 0,
|
||
|
GSM_CLIENT_REGISTERED,
|
||
|
GSM_CLIENT_FINISHED,
|
||
|
GSM_CLIENT_FAILED
|
||
|
} GsmClientStatus;
|
||
|
|
||
|
typedef enum {
|
||
|
GSM_CLIENT_RESTART_NEVER = 0,
|
||
|
GSM_CLIENT_RESTART_IF_RUNNING,
|
||
|
GSM_CLIENT_RESTART_ANYWAY,
|
||
|
GSM_CLIENT_RESTART_IMMEDIATELY
|
||
|
} GsmClientRestartStyle;
|
||
|
|
||
|
typedef enum {
|
||
|
GSM_CLIENT_END_SESSION_FLAG_FORCEFUL = 1 << 0,
|
||
|
GSM_CLIENT_END_SESSION_FLAG_SAVE = 1 << 1,
|
||
|
GSM_CLIENT_END_SESSION_FLAG_LAST = 1 << 2
|
||
|
} GsmClientEndSessionFlag;
|
||
|
|
||
|
struct _GsmClient
|
||
|
{
|
||
|
GObject parent;
|
||
|
GsmClientPrivate *priv;
|
||
|
};
|
||
|
@@ -67,91 +68,93 @@ struct _GsmClient
|
||
|
struct _GsmClientClass
|
||
|
{
|
||
|
GObjectClass parent_class;
|
||
|
|
||
|
/* signals */
|
||
|
void (*disconnected) (GsmClient *client);
|
||
|
void (*end_session_response) (GsmClient *client,
|
||
|
gboolean ok,
|
||
|
gboolean do_last,
|
||
|
gboolean cancel,
|
||
|
const char *reason);
|
||
|
|
||
|
/* virtual methods */
|
||
|
char * (*impl_get_app_name) (GsmClient *client);
|
||
|
GsmClientRestartStyle (*impl_get_restart_style_hint) (GsmClient *client);
|
||
|
guint (*impl_get_unix_process_id) (GsmClient *client);
|
||
|
gboolean (*impl_query_end_session) (GsmClient *client,
|
||
|
GsmClientEndSessionFlag flags,
|
||
|
GError **error);
|
||
|
gboolean (*impl_end_session) (GsmClient *client,
|
||
|
GsmClientEndSessionFlag flags,
|
||
|
GError **error);
|
||
|
gboolean (*impl_cancel_end_session) (GsmClient *client,
|
||
|
GError **error);
|
||
|
gboolean (*impl_stop) (GsmClient *client,
|
||
|
GError **error);
|
||
|
gboolean (*impl_request_save) (GsmClient *client,
|
||
|
guint flags,
|
||
|
GError **error);
|
||
|
GKeyFile * (*impl_save) (GsmClient *client,
|
||
|
+ GsmApp *app,
|
||
|
GError **error);
|
||
|
};
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
GSM_CLIENT_ERROR_GENERAL = 0,
|
||
|
GSM_CLIENT_ERROR_NOT_REGISTERED,
|
||
|
GSM_CLIENT_NUM_ERRORS
|
||
|
} GsmClientError;
|
||
|
|
||
|
#define GSM_CLIENT_ERROR gsm_client_error_quark ()
|
||
|
GQuark gsm_client_error_quark (void);
|
||
|
|
||
|
GType gsm_client_get_type (void) G_GNUC_CONST;
|
||
|
|
||
|
const char *gsm_client_peek_id (GsmClient *client);
|
||
|
|
||
|
|
||
|
const char * gsm_client_peek_startup_id (GsmClient *client);
|
||
|
const char * gsm_client_peek_app_id (GsmClient *client);
|
||
|
guint gsm_client_peek_restart_style_hint (GsmClient *client);
|
||
|
guint gsm_client_peek_status (GsmClient *client);
|
||
|
|
||
|
|
||
|
char *gsm_client_get_app_name (GsmClient *client);
|
||
|
void gsm_client_set_app_id (GsmClient *client,
|
||
|
const char *app_id);
|
||
|
void gsm_client_set_status (GsmClient *client,
|
||
|
guint status);
|
||
|
|
||
|
gboolean gsm_client_end_session (GsmClient *client,
|
||
|
guint flags,
|
||
|
GError **error);
|
||
|
gboolean gsm_client_query_end_session (GsmClient *client,
|
||
|
guint flags,
|
||
|
GError **error);
|
||
|
gboolean gsm_client_cancel_end_session (GsmClient *client,
|
||
|
GError **error);
|
||
|
|
||
|
void gsm_client_disconnected (GsmClient *client);
|
||
|
|
||
|
gboolean gsm_client_request_save (GsmClient *client,
|
||
|
guint flags,
|
||
|
GError **error);
|
||
|
GKeyFile *gsm_client_save (GsmClient *client,
|
||
|
+ GsmApp *app,
|
||
|
GError **error);
|
||
|
|
||
|
gboolean gsm_client_stop (GsmClient *client,
|
||
|
GError **error);
|
||
|
|
||
|
/* private */
|
||
|
|
||
|
void gsm_client_end_session_response (GsmClient *client,
|
||
|
gboolean is_ok,
|
||
|
gboolean do_last,
|
||
|
gboolean cancel,
|
||
|
const char *reason);
|
||
|
|
||
|
G_END_DECLS
|
||
|
|
||
|
#endif /* __GSM_CLIENT_H__ */
|
||
|
diff --git a/gnome-session/gsm-dbus-client.c b/gnome-session/gsm-dbus-client.c
|
||
|
index 050ea18f..5793f830 100644
|
||
|
--- a/gnome-session/gsm-dbus-client.c
|
||
|
+++ b/gnome-session/gsm-dbus-client.c
|
||
|
@@ -315,60 +315,61 @@ gsm_dbus_client_finalize (GObject *object)
|
||
|
|
||
|
if (client->priv->skeleton != NULL) {
|
||
|
g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (client->priv->skeleton),
|
||
|
client->priv->connection);
|
||
|
g_clear_object (&client->priv->skeleton);
|
||
|
}
|
||
|
|
||
|
g_clear_object (&client->priv->connection);
|
||
|
|
||
|
if (client->priv->watch_id != 0)
|
||
|
g_bus_unwatch_name (client->priv->watch_id);
|
||
|
|
||
|
G_OBJECT_CLASS (gsm_dbus_client_parent_class)->finalize (object);
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
dbus_client_request_save (GsmClient *client,
|
||
|
guint flags,
|
||
|
GError **error)
|
||
|
{
|
||
|
g_debug ("GsmDBusClient: sending save request to client with id %s",
|
||
|
gsm_client_peek_id (client));
|
||
|
|
||
|
/* FIXME: The protocol does not support this */
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static GKeyFile *
|
||
|
dbus_client_save (GsmClient *client,
|
||
|
+ GsmApp *app,
|
||
|
GError **error)
|
||
|
{
|
||
|
g_debug ("GsmDBusClient: saving client with id %s",
|
||
|
gsm_client_peek_id (client));
|
||
|
|
||
|
/* FIXME: We still don't support client saving for D-Bus
|
||
|
* session clients */
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
dbus_client_stop (GsmClient *client,
|
||
|
GError **error)
|
||
|
{
|
||
|
GsmDBusClient *dbus_client = (GsmDBusClient *) client;
|
||
|
gsm_exported_client_private_emit_stop (dbus_client->priv->skeleton);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static char *
|
||
|
dbus_client_get_app_name (GsmClient *client)
|
||
|
{
|
||
|
/* Always use app-id instead */
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static GsmClientRestartStyle
|
||
|
dbus_client_get_restart_style_hint (GsmClient *client)
|
||
|
{
|
||
|
diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c
|
||
|
index 29c3054d..e7f0d7f8 100644
|
||
|
--- a/gnome-session/gsm-manager.c
|
||
|
+++ b/gnome-session/gsm-manager.c
|
||
|
@@ -1260,61 +1260,61 @@ finish_pending_save_invocations (GsmManager *manager)
|
||
|
g_slist_free (manager->priv->pending_save_invocations);
|
||
|
manager->priv->pending_save_invocations = NULL;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
query_save_session_complete (GsmManager *manager)
|
||
|
{
|
||
|
GError *error = NULL;
|
||
|
|
||
|
if (g_slist_length (manager->priv->next_query_clients) > 0) {
|
||
|
ClientEndSessionData data;
|
||
|
|
||
|
data.manager = manager;
|
||
|
data.flags = GSM_CLIENT_END_SESSION_FLAG_LAST;
|
||
|
|
||
|
g_slist_foreach (manager->priv->next_query_clients,
|
||
|
(GFunc)_client_request_save,
|
||
|
&data);
|
||
|
|
||
|
g_slist_free (manager->priv->next_query_clients);
|
||
|
manager->priv->next_query_clients = NULL;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (manager->priv->query_timeout_id > 0) {
|
||
|
g_source_remove (manager->priv->query_timeout_id);
|
||
|
manager->priv->query_timeout_id = 0;
|
||
|
}
|
||
|
|
||
|
- gsm_session_save (manager->priv->clients, manager->priv->session_name, &error);
|
||
|
+ gsm_session_save (manager->priv->clients, manager->priv->apps, manager->priv->session_name, &error);
|
||
|
|
||
|
if (error) {
|
||
|
g_warning ("Error saving session: %s", error->message);
|
||
|
fail_pending_save_invocations (manager, error);
|
||
|
g_error_free (error);
|
||
|
} else {
|
||
|
finish_pending_save_invocations (manager);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static guint32
|
||
|
generate_cookie (void)
|
||
|
{
|
||
|
guint32 cookie;
|
||
|
|
||
|
cookie = (guint32)g_random_int_range (1, G_MAXINT32);
|
||
|
|
||
|
return cookie;
|
||
|
}
|
||
|
|
||
|
static guint32
|
||
|
_generate_unique_cookie (GsmManager *manager)
|
||
|
{
|
||
|
guint32 cookie;
|
||
|
|
||
|
do {
|
||
|
cookie = generate_cookie ();
|
||
|
} while (gsm_store_find (manager->priv->inhibitors, (GsmStoreFunc)_find_by_cookie, &cookie) != NULL);
|
||
|
|
||
|
return cookie;
|
||
|
@@ -1963,61 +1963,61 @@ on_xsmp_client_register_confirmed (GsmXSMPClient *client,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
auto_save_is_enabled (GsmManager *manager)
|
||
|
{
|
||
|
return g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE_ONE_SHOT)
|
||
|
|| g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
maybe_save_session (GsmManager *manager)
|
||
|
{
|
||
|
GError *error;
|
||
|
|
||
|
if (gsm_system_is_login_session (manager->priv->system))
|
||
|
return;
|
||
|
|
||
|
/* We only allow session saving when session is running or when
|
||
|
* logging out */
|
||
|
if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING &&
|
||
|
manager->priv->phase != GSM_MANAGER_PHASE_END_SESSION) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!auto_save_is_enabled (manager)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
error = NULL;
|
||
|
- gsm_session_save (manager->priv->clients, manager->priv->session_name, &error);
|
||
|
+ gsm_session_save (manager->priv->clients, manager->priv->apps, manager->priv->session_name, &error);
|
||
|
|
||
|
if (error) {
|
||
|
g_warning ("Error saving session: %s", error->message);
|
||
|
g_error_free (error);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
_handle_client_end_session_response (GsmManager *manager,
|
||
|
GsmClient *client,
|
||
|
gboolean is_ok,
|
||
|
gboolean do_last,
|
||
|
gboolean cancel,
|
||
|
const char *reason)
|
||
|
{
|
||
|
/* just ignore if we are not yet running */
|
||
|
if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
g_debug ("GsmManager: Response from end session request: is-ok=%d do-last=%d cancel=%d reason=%s", is_ok, do_last, cancel, reason ? reason :"");
|
||
|
|
||
|
if (manager->priv->phase == GSM_MANAGER_PHASE_RUNNING) {
|
||
|
/* Ignore responses when no requests were sent */
|
||
|
if (manager->priv->query_clients == NULL) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client);
|
||
|
|
||
|
diff --git a/gnome-session/gsm-session-save.c b/gnome-session/gsm-session-save.c
|
||
|
index 78b64197..35ffaae0 100644
|
||
|
--- a/gnome-session/gsm-session-save.c
|
||
|
+++ b/gnome-session/gsm-session-save.c
|
||
|
@@ -1,234 +1,253 @@
|
||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||
|
* gsm-session-save.c
|
||
|
* Copyright (C) 2008 Lucas Rocha.
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License as
|
||
|
* published by the Free Software Foundation; either version 2 of the
|
||
|
* License, or (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include <config.h>
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <glib.h>
|
||
|
#include <glib/gstdio.h>
|
||
|
#include <gio/gio.h>
|
||
|
|
||
|
+#include "gsm-app.h"
|
||
|
#include "gsm-util.h"
|
||
|
#include "gsm-autostart-app.h"
|
||
|
#include "gsm-client.h"
|
||
|
|
||
|
#include "gsm-session-save.h"
|
||
|
|
||
|
#define GSM_MANAGER_SCHEMA "org.gnome.SessionManager"
|
||
|
#define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot"
|
||
|
|
||
|
|
||
|
static gboolean gsm_session_clear_saved_session (const char *directory,
|
||
|
GHashTable *discard_hash);
|
||
|
|
||
|
typedef struct {
|
||
|
char *dir;
|
||
|
GHashTable *discard_hash;
|
||
|
+ GsmStore *app_store;
|
||
|
GError **error;
|
||
|
} SessionSaveData;
|
||
|
|
||
|
static void
|
||
|
clear_session_type (const char *save_dir)
|
||
|
{
|
||
|
char *file;
|
||
|
|
||
|
file = g_build_filename (save_dir, "type", NULL);
|
||
|
|
||
|
g_unlink (file);
|
||
|
|
||
|
g_free (file);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
set_session_type (const char *save_dir,
|
||
|
const char *type)
|
||
|
{
|
||
|
char *file;
|
||
|
GError *error;
|
||
|
|
||
|
file = g_build_filename (save_dir, "type", NULL);
|
||
|
|
||
|
error = NULL;
|
||
|
g_file_set_contents (file, type, strlen (type), &error);
|
||
|
if (error != NULL)
|
||
|
g_warning ("couldn't save session type to %s: %s",
|
||
|
type, error->message);
|
||
|
|
||
|
g_free (file);
|
||
|
}
|
||
|
|
||
|
+static gboolean
|
||
|
+_app_has_app_id (const char *id,
|
||
|
+ GsmApp *app,
|
||
|
+ const char *app_id_a)
|
||
|
+{
|
||
|
+ const char *app_id_b;
|
||
|
+
|
||
|
+ app_id_b = gsm_app_peek_app_id (app);
|
||
|
+ return g_strcmp0 (app_id_a, app_id_b) == 0;
|
||
|
+}
|
||
|
+
|
||
|
static gboolean
|
||
|
save_one_client (char *id,
|
||
|
GObject *object,
|
||
|
SessionSaveData *data)
|
||
|
{
|
||
|
GsmClient *client;
|
||
|
GKeyFile *keyfile;
|
||
|
+ GsmApp *app = NULL;
|
||
|
const char *app_id;
|
||
|
char *path = NULL;
|
||
|
char *filename = NULL;
|
||
|
char *contents = NULL;
|
||
|
gsize length = 0;
|
||
|
char *discard_exec;
|
||
|
GError *local_error;
|
||
|
|
||
|
client = GSM_CLIENT (object);
|
||
|
|
||
|
local_error = NULL;
|
||
|
|
||
|
- keyfile = gsm_client_save (client, &local_error);
|
||
|
+ app_id = gsm_client_peek_app_id (client);
|
||
|
+ if (!IS_STRING_EMPTY (app_id)) {
|
||
|
+ if (g_str_has_suffix (app_id, ".desktop"))
|
||
|
+ filename = g_strdup (app_id);
|
||
|
+ else
|
||
|
+ filename = g_strdup_printf ("%s.desktop", app_id);
|
||
|
+
|
||
|
+ path = g_build_filename (data->dir, filename, NULL);
|
||
|
+
|
||
|
+ app = (GsmApp *)gsm_store_find (data->app_store,
|
||
|
+ (GsmStoreFunc)_app_has_app_id,
|
||
|
+ (char *)app_id);
|
||
|
+ }
|
||
|
+ keyfile = gsm_client_save (client, app, &local_error);
|
||
|
|
||
|
if (keyfile == NULL || local_error) {
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
contents = g_key_file_to_data (keyfile, &length, &local_error);
|
||
|
|
||
|
if (local_error) {
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
- app_id = gsm_client_peek_app_id (client);
|
||
|
- if (!IS_STRING_EMPTY (app_id)) {
|
||
|
- if (g_str_has_suffix (app_id, ".desktop"))
|
||
|
- filename = g_strdup (app_id);
|
||
|
- else
|
||
|
- filename = g_strdup_printf ("%s.desktop", app_id);
|
||
|
-
|
||
|
- path = g_build_filename (data->dir, filename, NULL);
|
||
|
- }
|
||
|
-
|
||
|
if (!path || g_file_test (path, G_FILE_TEST_EXISTS)) {
|
||
|
if (filename)
|
||
|
g_free (filename);
|
||
|
if (path)
|
||
|
g_free (path);
|
||
|
|
||
|
filename = g_strdup_printf ("%s.desktop",
|
||
|
gsm_client_peek_startup_id (client));
|
||
|
path = g_build_filename (data->dir, filename, NULL);
|
||
|
}
|
||
|
|
||
|
g_file_set_contents (path,
|
||
|
contents,
|
||
|
length,
|
||
|
&local_error);
|
||
|
|
||
|
if (local_error) {
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
discard_exec = g_key_file_get_string (keyfile,
|
||
|
G_KEY_FILE_DESKTOP_GROUP,
|
||
|
GSM_AUTOSTART_APP_DISCARD_KEY,
|
||
|
NULL);
|
||
|
if (discard_exec) {
|
||
|
g_hash_table_insert (data->discard_hash,
|
||
|
discard_exec, discard_exec);
|
||
|
}
|
||
|
|
||
|
g_debug ("GsmSessionSave: saved client %s to %s", id, filename);
|
||
|
|
||
|
out:
|
||
|
if (keyfile != NULL) {
|
||
|
g_key_file_free (keyfile);
|
||
|
}
|
||
|
|
||
|
g_free (contents);
|
||
|
g_free (filename);
|
||
|
g_free (path);
|
||
|
|
||
|
/* in case of any error, stop saving session */
|
||
|
if (local_error) {
|
||
|
g_propagate_error (data->error, local_error);
|
||
|
g_error_free (local_error);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gsm_session_save (GsmStore *client_store,
|
||
|
+ GsmStore *app_store,
|
||
|
const char *type,
|
||
|
GError **error)
|
||
|
{
|
||
|
GSettings *settings;
|
||
|
const char *save_dir;
|
||
|
char *tmp_dir;
|
||
|
SessionSaveData data;
|
||
|
|
||
|
g_debug ("GsmSessionSave: Saving session");
|
||
|
|
||
|
/* Clear one shot key autosave in the event its set (so that it's actually
|
||
|
* one shot only)
|
||
|
*/
|
||
|
settings = g_settings_new (GSM_MANAGER_SCHEMA);
|
||
|
g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, FALSE);
|
||
|
g_object_unref (settings);
|
||
|
|
||
|
save_dir = gsm_util_get_saved_session_dir ();
|
||
|
if (save_dir == NULL) {
|
||
|
g_warning ("GsmSessionSave: cannot create saved session directory");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
tmp_dir = gsm_util_get_empty_tmp_session_dir ();
|
||
|
if (tmp_dir == NULL) {
|
||
|
g_warning ("GsmSessionSave: cannot create new saved session directory");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* save the session in a temp directory, and remember the discard
|
||
|
* commands */
|
||
|
data.dir = tmp_dir;
|
||
|
data.discard_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||
|
g_free, NULL);
|
||
|
data.error = error;
|
||
|
+ data.app_store = app_store;
|
||
|
|
||
|
gsm_store_foreach (client_store,
|
||
|
(GsmStoreFunc) save_one_client,
|
||
|
&data);
|
||
|
|
||
|
if (!*error) {
|
||
|
char *session_dir;
|
||
|
|
||
|
if (g_file_test (save_dir, G_FILE_TEST_IS_SYMLINK))
|
||
|
session_dir = g_file_read_link (save_dir, error);
|
||
|
else
|
||
|
session_dir = g_strdup (save_dir);
|
||
|
|
||
|
if (session_dir != NULL) {
|
||
|
char *absolute_session_dir;
|
||
|
|
||
|
set_session_type (tmp_dir, type);
|
||
|
|
||
|
if (g_path_is_absolute (session_dir)) {
|
||
|
absolute_session_dir = g_strdup (session_dir);
|
||
|
} else {
|
||
|
char *parent_dir;
|
||
|
|
||
|
parent_dir = g_path_get_dirname (save_dir);
|
||
|
absolute_session_dir = g_build_filename (parent_dir, session_dir, NULL);
|
||
|
g_free (parent_dir);
|
||
|
}
|
||
|
g_free (session_dir);
|
||
|
|
||
|
/* remove the old saved session */
|
||
|
diff --git a/gnome-session/gsm-session-save.h b/gnome-session/gsm-session-save.h
|
||
|
index c91b5615..b32673c4 100644
|
||
|
--- a/gnome-session/gsm-session-save.h
|
||
|
+++ b/gnome-session/gsm-session-save.h
|
||
|
@@ -1,34 +1,35 @@
|
||
|
/* gsm-session-save.h
|
||
|
* Copyright (C) 2008 Lucas Rocha.
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License as
|
||
|
* published by the Free Software Foundation; either version 2 of the
|
||
|
* License, or (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#ifndef __GSM_SESSION_SAVE_H__
|
||
|
#define __GSM_SESSION_SAVE_H__
|
||
|
|
||
|
#include <glib.h>
|
||
|
|
||
|
#include "gsm-store.h"
|
||
|
|
||
|
G_BEGIN_DECLS
|
||
|
|
||
|
void gsm_session_save (GsmStore *client_store,
|
||
|
+ GsmStore *app_store,
|
||
|
const char *type,
|
||
|
GError **error);
|
||
|
void gsm_session_save_clear (void);
|
||
|
|
||
|
G_END_DECLS
|
||
|
|
||
|
#endif /* __GSM_SESSION_SAVE_H__ */
|
||
|
diff --git a/gnome-session/gsm-xsmp-client.c b/gnome-session/gsm-xsmp-client.c
|
||
|
index 2846d9b3..cbecd68c 100644
|
||
|
--- a/gnome-session/gsm-xsmp-client.c
|
||
|
+++ b/gnome-session/gsm-xsmp-client.c
|
||
|
@@ -612,118 +612,127 @@ set_desktop_file_keys_from_client (GsmClient *client,
|
||
|
|
||
|
g_free (comment);
|
||
|
}
|
||
|
|
||
|
static GKeyFile *
|
||
|
create_client_key_file (GsmClient *client,
|
||
|
const char *desktop_file_path,
|
||
|
GError **error) {
|
||
|
GKeyFile *keyfile;
|
||
|
|
||
|
keyfile = g_key_file_new ();
|
||
|
|
||
|
if (desktop_file_path != NULL) {
|
||
|
g_key_file_load_from_file (keyfile,
|
||
|
desktop_file_path,
|
||
|
G_KEY_FILE_KEEP_COMMENTS |
|
||
|
G_KEY_FILE_KEEP_TRANSLATIONS,
|
||
|
error);
|
||
|
} else {
|
||
|
set_desktop_file_keys_from_client (client, keyfile);
|
||
|
}
|
||
|
|
||
|
return keyfile;
|
||
|
}
|
||
|
|
||
|
static GsmClientRestartStyle
|
||
|
xsmp_get_restart_style_hint (GsmClient *client);
|
||
|
|
||
|
static GKeyFile *
|
||
|
xsmp_save (GsmClient *client,
|
||
|
+ GsmApp *app,
|
||
|
GError **error)
|
||
|
{
|
||
|
GsmClientRestartStyle restart_style;
|
||
|
|
||
|
GKeyFile *keyfile = NULL;
|
||
|
char *desktop_file_path = NULL;
|
||
|
char *exec_program = NULL;
|
||
|
char *exec_discard = NULL;
|
||
|
char *startup_id = NULL;
|
||
|
GError *local_error;
|
||
|
|
||
|
g_debug ("GsmXSMPClient: saving client with id %s",
|
||
|
gsm_client_peek_id (client));
|
||
|
|
||
|
local_error = NULL;
|
||
|
|
||
|
restart_style = xsmp_get_restart_style_hint (client);
|
||
|
if (restart_style == GSM_CLIENT_RESTART_NEVER) {
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
exec_program = xsmp_get_restart_command (client);
|
||
|
if (!exec_program) {
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
desktop_file_path = get_desktop_file_path (GSM_XSMP_CLIENT (client));
|
||
|
|
||
|
/* this can accept desktop_file_path == NULL */
|
||
|
keyfile = create_client_key_file (client,
|
||
|
desktop_file_path,
|
||
|
&local_error);
|
||
|
|
||
|
if (local_error) {
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
g_object_get (client,
|
||
|
"startup-id", &startup_id,
|
||
|
NULL);
|
||
|
|
||
|
g_key_file_set_string (keyfile,
|
||
|
G_KEY_FILE_DESKTOP_GROUP,
|
||
|
GSM_AUTOSTART_APP_STARTUP_ID_KEY,
|
||
|
startup_id);
|
||
|
|
||
|
g_key_file_set_string (keyfile,
|
||
|
G_KEY_FILE_DESKTOP_GROUP,
|
||
|
G_KEY_FILE_DESKTOP_KEY_EXEC,
|
||
|
exec_program);
|
||
|
|
||
|
exec_discard = xsmp_get_discard_command (client);
|
||
|
if (exec_discard)
|
||
|
g_key_file_set_string (keyfile,
|
||
|
G_KEY_FILE_DESKTOP_GROUP,
|
||
|
GSM_AUTOSTART_APP_DISCARD_KEY,
|
||
|
exec_discard);
|
||
|
|
||
|
+ if (app != NULL) {
|
||
|
+ gsm_app_save_to_keyfile (app, keyfile, &local_error);
|
||
|
+
|
||
|
+ if (local_error) {
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
out:
|
||
|
g_free (desktop_file_path);
|
||
|
g_free (exec_program);
|
||
|
g_free (exec_discard);
|
||
|
g_free (startup_id);
|
||
|
|
||
|
if (local_error != NULL) {
|
||
|
g_propagate_error (error, local_error);
|
||
|
g_key_file_free (keyfile);
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return keyfile;
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
xsmp_stop (GsmClient *client,
|
||
|
GError **error)
|
||
|
{
|
||
|
GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
|
||
|
|
||
|
g_debug ("GsmXSMPClient: xsmp_stop ('%s')", xsmp->priv->description);
|
||
|
|
||
|
if (xsmp->priv->conn == NULL) {
|
||
|
g_set_error (error,
|
||
|
GSM_CLIENT_ERROR,
|
||
|
GSM_CLIENT_ERROR_NOT_REGISTERED,
|
||
|
"Client is not registered");
|
||
|
return FALSE;
|
||
|
--
|
||
|
2.14.3
|
||
|
|