]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - liblightdm-gobject/session.c
Use G_DECLARE_*_TYPE to simplify code and fix docs
[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 "configuration.h"
15 #include "lightdm/session.h"
16
17 enum {
18     PROP_KEY = 1,
19     PROP_NAME,
20     PROP_COMMENT
21 };
22
23 struct _LightDMSession
24 {
25     gchar *key;
26     gchar *type;
27     gchar *name;
28     gchar *comment;
29 };
30
31 G_DEFINE_TYPE (LightDMSession, lightdm_session, G_TYPE_OBJECT);
32
33 static gboolean have_sessions = FALSE;
34 static GList *local_sessions = NULL;
35 static GList *remote_sessions = NULL;
36
37 static gint
38 compare_session (gconstpointer a, gconstpointer b)
39 {
40     const LightDMSession *sa = a, *sb = b;
41     return strcmp (sa->name, sb->name);
42 }
43
44 static LightDMSession *
45 load_session (GKeyFile *key_file, const gchar *key, const gchar *default_type)
46 {
47     gchar *domain, *name, *type;
48     LightDMSession *session;
49     gchar *try_exec;
50
51     if (g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, NULL) ||
52         g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_HIDDEN, NULL))
53         return NULL;
54
55 #ifdef G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN
56     domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN, NULL);
57 #else
58     domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL);
59 #endif
60     name = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, domain, NULL);
61     if (!name)
62     {
63         g_warning ("Ignoring session without name");
64         g_free (domain);
65         return NULL;
66     }
67
68     try_exec = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TRY_EXEC, domain, NULL);
69     if (try_exec)
70     {
71         gchar *full_path;
72
73         full_path = g_find_program_in_path (try_exec);
74         g_free (try_exec);
75
76         if (!full_path)
77         {
78             g_free (name);
79             g_free (domain);
80             return NULL;
81         }
82         g_free (full_path);
83     }
84
85     type = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-LightDM-Session-Type", NULL);
86     if (!type)
87         type = strdup (default_type);
88
89     session = g_object_new (LIGHTDM_TYPE_SESSION, NULL);
90
91     g_free (session->key);
92     session->key = g_strdup (key);
93
94     g_free (session->type);
95     session->type = type;
96
97     g_free (session->name);
98     session->name = name;
99
100     g_free (session->comment);
101     session->comment = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, domain, NULL);
102     if (!session->comment)
103         session->comment = g_strdup ("");
104
105     g_free (domain);
106
107     return session;
108 }
109
110 static GList *
111 load_sessions_dir (GList *sessions, const gchar *sessions_dir, const gchar *default_type)
112 {
113     GDir *directory;
114     GError *error = NULL;
115
116     directory = g_dir_open (sessions_dir, 0, &error);
117     if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
118         g_warning ("Failed to open sessions directory: %s", error->message);
119     g_clear_error (&error);
120     if (!directory)
121         return sessions;
122
123     while (TRUE)
124     {
125         const gchar *filename;
126         gchar *path;
127         GKeyFile *key_file;
128         gboolean result;
129
130         filename = g_dir_read_name (directory);
131         if (filename == NULL)
132             break;
133
134         if (!g_str_has_suffix (filename, ".desktop"))
135             continue;
136
137         path = g_build_filename (sessions_dir, filename, NULL);
138
139         key_file = g_key_file_new ();
140         result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
141         if (error)
142             g_warning ("Failed to load session file %s: %s:", path, error->message);
143         g_clear_error (&error);
144
145         if (result)
146         {
147             gchar *key;
148             LightDMSession *session;
149
150             key = g_strndup (filename, strlen (filename) - strlen (".desktop"));
151             session = load_session (key_file, key, default_type);
152             if (session)
153             {
154                 g_debug ("Loaded session %s (%s, %s)", path, session->name, session->comment);
155                 sessions = g_list_insert_sorted (sessions, session, compare_session);
156             }
157             else
158                 g_debug ("Ignoring session %s", path);
159             g_free (key);
160         }
161
162         g_free (path);
163         g_key_file_free (key_file);
164     }
165
166     g_dir_close (directory);
167
168     return sessions;
169 }
170
171 static GList *
172 load_sessions (const gchar *sessions_dir)
173 {
174     GList *sessions = NULL;
175     gchar **dirs;
176     int i;
177
178     dirs = g_strsplit (sessions_dir, ":", -1);
179     for (i = 0; dirs[i]; i++) 
180     {
181         const gchar *default_type = "x";
182
183         if (strcmp (dirs[i], WAYLAND_SESSIONS_DIR) == 0)
184             default_type = "wayland";
185
186         sessions = load_sessions_dir (sessions, dirs[i], default_type);
187     }
188  
189     g_strfreev (dirs);
190
191     return sessions;
192 }
193
194 static void
195 update_sessions (void)
196 {
197     gchar *sessions_dir;
198     gchar *remote_sessions_dir;
199     gchar *value;
200
201     if (have_sessions)
202         return;
203
204     sessions_dir = g_strdup (SESSIONS_DIR);
205     remote_sessions_dir = g_strdup (REMOTE_SESSIONS_DIR);
206
207     /* Use session directory from configuration */
208     config_load_from_standard_locations (config_get_instance (), NULL, NULL);
209
210     value = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
211     if (value)
212     {
213         g_free (sessions_dir);
214         sessions_dir = value;
215     }
216
217     value = config_get_string (config_get_instance (), "LightDM", "remote-sessions-directory");
218     if (value)
219     {
220         g_free (remote_sessions_dir);
221         remote_sessions_dir = value;
222     }
223
224     local_sessions = load_sessions (sessions_dir);
225     remote_sessions = load_sessions (remote_sessions_dir);
226
227     g_free (sessions_dir);
228     g_free (remote_sessions_dir);
229
230     have_sessions = TRUE;
231 }
232
233 /**
234  * lightdm_get_sessions:
235  *
236  * Get the available sessions.
237  *
238  * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
239  **/
240 GList *
241 lightdm_get_sessions (void)
242 {
243     update_sessions ();
244     return local_sessions;
245 }
246
247 /**
248  * lightdm_get_remote_sessions:
249  *
250  * Get the available remote sessions.
251  *
252  * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
253  **/
254 GList *
255 lightdm_get_remote_sessions (void)
256 {
257     update_sessions ();
258     return remote_sessions;
259 }
260
261 /**
262  * lightdm_session_get_key:
263  * @session: A #LightDMSession
264  *
265  * Get the key for a session
266  *
267  * Return value: The session key
268  **/
269 const gchar *
270 lightdm_session_get_key (LightDMSession *session)
271 {
272     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
273     return session->key;
274 }
275
276 /**
277  * lightdm_session_get_session_type:
278  * @session: A #LightDMSession
279  *
280  * Get the type a session
281  *
282  * Return value: The session type, e.g. x or mir
283  **/
284 const gchar *
285 lightdm_session_get_session_type (LightDMSession *session)
286 {
287     g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL);
288     return session->type;
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 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 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
366     g_free (self->key);
367     g_free (self->type);
368     g_free (self->name);
369     g_free (self->comment);
370 }
371
372 static void
373 lightdm_session_class_init (LightDMSessionClass *klass)
374 {
375     GObjectClass *object_class = G_OBJECT_CLASS (klass);
376
377     object_class->set_property = lightdm_session_set_property;
378     object_class->get_property = lightdm_session_get_property;
379     object_class->finalize = lightdm_session_finalize;
380
381     g_object_class_install_property (object_class,
382                                      PROP_KEY,
383                                      g_param_spec_string ("key",
384                                                           "key",
385                                                           "Session key",
386                                                           NULL,
387                                                           G_PARAM_READABLE));
388     g_object_class_install_property (object_class,
389                                      PROP_NAME,
390                                      g_param_spec_string ("name",
391                                                           "name",
392                                                           "Session name",
393                                                           NULL,
394                                                           G_PARAM_READABLE));
395     g_object_class_install_property (object_class,
396                                      PROP_COMMENT,
397                                      g_param_spec_string ("comment",
398                                                           "comment",
399                                                           "Session comment",
400                                                           NULL,
401                                                           G_PARAM_READABLE));
402 }