]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - liblightdm-gobject/session.c
Start work on Mir sessions
[sojka/lightdm.git] / liblightdm-gobject / session.c
1 /*
2  * Copyright (C) 2010 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  * 
5  * This library is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License as published by the Free
7  * Software Foundation; either version 2 or version 3 of the License.
8  * See http://www.gnu.org/copyleft/lgpl.html the full text of the license.
9  */
10
11 #include <string.h>
12 #include <gio/gdesktopappinfo.h>
13
14 #include "lightdm/session.h"
15
16 enum {
17     PROP_0,
18     PROP_KEY,
19     PROP_NAME,
20     PROP_COMMENT
21 };
22
23 typedef struct
24 {
25     gchar *key;
26     gchar *name;
27     gchar *comment;
28 } LightDMSessionPrivate;
29
30 G_DEFINE_TYPE (LightDMSession, lightdm_session, G_TYPE_OBJECT);
31
32 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_SESSION, LightDMSessionPrivate)
33
34 static gboolean have_sessions = FALSE;
35 static GList *local_sessions = NULL;
36 static GList *remote_sessions = NULL;
37 static GList *mir_sessions = NULL;
38
39 static gint 
40 compare_session (gconstpointer a, gconstpointer b)
41 {
42     LightDMSessionPrivate *priv_a = GET_PRIVATE (a);
43     LightDMSessionPrivate *priv_b = GET_PRIVATE (b);
44     return strcmp (priv_a->name, priv_b->name);
45 }
46
47 static LightDMSession *
48 load_session (GKeyFile *key_file, const gchar *key)
49 {
50     gchar *domain, *name;
51     LightDMSession *session;
52     LightDMSessionPrivate *priv;
53     gchar *try_exec;
54   
55     if (g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, NULL) ||
56         g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_HIDDEN, NULL))
57         return NULL;
58
59 #ifdef G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN
60     domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN, NULL);
61 #else
62     domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL);
63 #endif
64     name = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, domain, NULL);
65     if (!name)
66     {
67         g_warning ("Ignoring session without name");
68         g_free (domain);
69         return NULL;
70     }
71
72     try_exec = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TRY_EXEC, domain, NULL);
73     if (try_exec)
74     {
75         gchar *full_path;
76
77         full_path = g_find_program_in_path (try_exec);
78         g_free (try_exec);
79
80         if (!full_path)
81         {
82             g_free (name);
83             g_free (domain);
84             return NULL;
85         }
86         g_free (full_path);
87     }
88
89     session = g_object_new (LIGHTDM_TYPE_SESSION, NULL);
90     priv = GET_PRIVATE (session);
91
92     g_free (priv->key);
93     priv->key = g_strdup (key);
94
95     g_free (priv->name);
96     priv->name = name;
97
98     g_free (priv->comment);
99     priv->comment = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, domain, NULL);
100     if (!priv->comment)
101         priv->comment = g_strdup ("");
102
103     g_free (domain);
104
105     return session;
106 }
107
108 static GList *
109 load_sessions (const gchar *sessions_dir)
110 {
111     GDir *directory;
112     GList *sessions = NULL;
113     GError *error = NULL;
114
115     directory = g_dir_open (sessions_dir, 0, &error);
116     if (error)
117         g_warning ("Failed to open sessions directory: %s", error->message);
118     g_clear_error (&error);
119     if (!directory)
120         return NULL;
121
122     while (TRUE)
123     {
124         const gchar *filename;
125         gchar *path;
126         GKeyFile *key_file;
127         gboolean result;
128
129         filename = g_dir_read_name (directory);
130         if (filename == NULL)
131             break;
132
133         if (!g_str_has_suffix (filename, ".desktop"))
134             continue;
135
136         path = g_build_filename (sessions_dir, filename, NULL);
137
138         key_file = g_key_file_new ();
139         result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
140         if (error)
141             g_warning ("Failed to load session file %s: %s:", path, error->message);
142         g_clear_error (&error);
143
144         if (result)
145         {
146             gchar *key;
147             LightDMSession *session;
148
149             key = g_strndup (filename, strlen (filename) - strlen (".desktop"));
150             session = load_session (key_file, key);
151             if (session)
152             {
153                 g_debug ("Loaded session %s (%s, %s)", path, GET_PRIVATE (session)->name, GET_PRIVATE (session)->comment);
154                 sessions = g_list_insert_sorted (sessions, session, compare_session);
155             }
156             else
157                 g_debug ("Ignoring session %s", path);
158             g_free (key);
159         }
160
161         g_free (path);
162         g_key_file_free (key_file);
163     }
164
165     g_dir_close (directory);
166   
167     return sessions;
168 }
169
170 static void
171 update_sessions (void)
172 {
173     GKeyFile *config_key_file = NULL;
174     gchar *config_path = NULL;
175     gchar *xsessions_dir;
176     gchar *remote_sessions_dir;
177     gchar *mir_sessions_dir;
178     gboolean result;
179     GError *error = NULL;
180
181     if (have_sessions)
182         return;
183
184     xsessions_dir = g_strdup (XSESSIONS_DIR);
185     remote_sessions_dir = g_strdup (REMOTE_SESSIONS_DIR);
186     mir_sessions_dir = g_strdup (MIR_SESSIONS_DIR);
187
188     /* Use session directory from configuration */
189     /* FIXME: This should be sent in the greeter connection */
190     config_path = g_build_filename (CONFIG_DIR, "lightdm.conf", NULL);
191     config_key_file = g_key_file_new ();
192     result = g_key_file_load_from_file (config_key_file, config_path, G_KEY_FILE_NONE, &error);
193     if (error)
194         g_warning ("Failed to open configuration file: %s", error->message);
195     g_clear_error (&error);
196     if (result)
197     {
198         gchar *value;
199       
200         value = g_key_file_get_string (config_key_file, "LightDM", "xsessions-directory", NULL);
201         if (value)
202         {
203             g_free (xsessions_dir);
204             xsessions_dir = value;
205         }
206
207         value = g_key_file_get_string (config_key_file, "LightDM", "remote-sessions-directory", NULL);
208         if (value)
209         {
210             g_free (remote_sessions_dir);
211             remote_sessions_dir = value;
212         }
213
214         value = g_key_file_get_string (config_key_file, "LightDM", "mir-sessions-directory", NULL);
215         if (value)
216         {
217             g_free (mir_sessions_dir);
218             mir_sessions_dir = value;
219         }
220     }
221     g_key_file_free (config_key_file);
222     g_free (config_path);
223
224     local_sessions = load_sessions (xsessions_dir);
225     remote_sessions = load_sessions (remote_sessions_dir);
226     mir_sessions = load_sessions (mir_sessions_dir);
227
228     g_free (xsessions_dir);
229     g_free (remote_sessions_dir);
230
231     have_sessions = TRUE;
232 }
233
234 /**
235  * lightdm_get_sessions:
236  *
237  * Get the available sessions.
238  *
239  * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
240  **/
241 GList *
242 lightdm_get_sessions (void)
243 {
244     update_sessions ();
245     return local_sessions;
246 }
247
248 /**
249  * lightdm_get_remote_sessions:
250  *
251  * Get the available remote sessions.
252  *
253  * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
254  **/
255 GList *
256 lightdm_get_remote_sessions (void)
257 {
258     update_sessions ();
259     return remote_sessions;
260 }
261
262 /**
263  * lightdm_get_mir_sessions:
264  *
265  * Get the available Mir sessions.
266  *
267  * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
268  **/
269 GList *
270 lightdm_get_mir_sessions (void)
271 {
272     update_sessions ();
273     return mir_sessions;
274 }
275
276 /**
277  * lightdm_session_get_key:
278  * @session: A #LightDMSession
279  * 
280  * Get the key for a session
281  * 
282  * Return value: The session key
283  **/
284 const gchar *
285 lightdm_session_get_key (LightDMSession *session)
286 {
287     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
288     return GET_PRIVATE (session)->key;
289 }
290
291 /**
292  * lightdm_session_get_name:
293  * @session: A #LightDMSession
294  * 
295  * Get the name for a session
296  * 
297  * Return value: The session name
298  **/
299 const gchar *
300 lightdm_session_get_name (LightDMSession *session)
301 {
302     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
303     return GET_PRIVATE (session)->name;
304 }
305
306 /**
307  * lightdm_session_get_comment:
308  * @session: A #LightDMSession
309  * 
310  * Get the comment for a session
311  * 
312  * Return value: The session comment
313  **/
314 const gchar *
315 lightdm_session_get_comment (LightDMSession *session)
316 {
317     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
318     return GET_PRIVATE (session)->comment;
319 }
320
321 static void
322 lightdm_session_init (LightDMSession *session)
323 {
324 }
325
326 static void
327 lightdm_session_set_property (GObject      *object,
328                           guint         prop_id,
329                           const GValue *value,
330                           GParamSpec   *pspec)
331 {
332     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
333 }
334
335 static void
336 lightdm_session_get_property (GObject    *object,
337                           guint       prop_id,
338                           GValue     *value,
339                           GParamSpec *pspec)
340 {
341     LightDMSession *self;
342
343     self = LIGHTDM_SESSION (object);
344
345     switch (prop_id) {
346     case PROP_KEY:
347         g_value_set_string (value, lightdm_session_get_key (self));
348         break;
349     case PROP_NAME:
350         g_value_set_string (value, lightdm_session_get_name (self));
351         break;
352     case PROP_COMMENT:
353         g_value_set_string (value, lightdm_session_get_comment (self));
354         break;
355     default:
356         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
357         break;
358     }
359 }
360
361 static void
362 lightdm_session_finalize (GObject *object)
363 {
364     LightDMSession *self = LIGHTDM_SESSION (object);
365     LightDMSessionPrivate *priv = GET_PRIVATE (self);
366
367     g_free (priv->key);
368     g_free (priv->name);
369     g_free (priv->comment);
370 }
371
372 static void
373 lightdm_session_class_init (LightDMSessionClass *klass)
374 {
375     GObjectClass *object_class = G_OBJECT_CLASS (klass);
376   
377     g_type_class_add_private (klass, sizeof (LightDMSessionPrivate));
378
379     object_class->set_property = lightdm_session_set_property;
380     object_class->get_property = lightdm_session_get_property;
381     object_class->finalize = lightdm_session_finalize;
382
383     g_object_class_install_property (object_class,
384                                      PROP_KEY,
385                                      g_param_spec_string ("key",
386                                                           "key",
387                                                           "Session key",
388                                                           NULL,
389                                                           G_PARAM_READABLE));
390     g_object_class_install_property (object_class,
391                                      PROP_NAME,
392                                      g_param_spec_string ("name",
393                                                           "name",
394                                                           "Session name",
395                                                           NULL,
396                                                           G_PARAM_READABLE));
397     g_object_class_install_property (object_class,
398                                      PROP_COMMENT,
399                                      g_param_spec_string ("comment",
400                                                           "comment",
401                                                           "Session comment",
402                                                           NULL,
403                                                           G_PARAM_READABLE));
404 }