]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - liblightdm-gobject/user.c
Add UID to lightdm gobject and qt bindings
[sojka/lightdm.git] / liblightdm-gobject / user.c
1 /* -*- Mode: C; indent-tabs-mode:nil; tab-width:4 -*-
2  *
3  * Copyright (C) 2010 Robert Ancell.
4  * Copyright (C) 2014 Canonical, Ltd.
5  * Authors: Robert Ancell <robert.ancell@canonical.com>
6  *          Michael Terry <michael.terry@canonical.com>
7  * 
8  * This library is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License as published by the Free
10  * Software Foundation; either version 2 or version 3 of the License.
11  * See http://www.gnu.org/copyleft/lgpl.html the full text of the license.
12  */
13
14 #include <config.h>
15
16 #include "user-list.h"
17 #include "lightdm/user.h"
18
19 enum
20 {
21     LIST_PROP_0,
22     LIST_PROP_NUM_USERS,
23     LIST_PROP_USERS,
24 };
25
26 enum
27 {
28     USER_PROP_0,
29     USER_PROP_COMMON_USER,
30     USER_PROP_NAME,
31     USER_PROP_REAL_NAME,
32     USER_PROP_DISPLAY_NAME,
33     USER_PROP_HOME_DIRECTORY,
34     USER_PROP_IMAGE,
35     USER_PROP_BACKGROUND,
36     USER_PROP_LANGUAGE,
37     USER_PROP_LAYOUT,
38     USER_PROP_LAYOUTS,
39     USER_PROP_SESSION,
40     USER_PROP_LOGGED_IN,
41     USER_PROP_HAS_MESSAGES,
42     USER_PROP_UID,
43 };
44
45 enum
46 {
47     USER_ADDED,
48     USER_CHANGED,
49     USER_REMOVED,
50     LAST_LIST_SIGNAL
51 };
52 static guint list_signals[LAST_LIST_SIGNAL] = { 0 };
53
54 enum
55 {
56     CHANGED,
57     LAST_USER_SIGNAL
58 };
59 static guint user_signals[LAST_USER_SIGNAL] = { 0 };
60
61 typedef struct
62 {
63     gboolean initialized;
64
65     /* Wrapper list, kept locally to preserve transfer-none promises */
66     GList *lightdm_list;
67 } LightDMUserListPrivate;
68
69 typedef struct
70 {
71     CommonUser *common_user;
72 } LightDMUserPrivate;
73
74 G_DEFINE_TYPE (LightDMUserList, lightdm_user_list, G_TYPE_OBJECT);
75 G_DEFINE_TYPE (LightDMUser, lightdm_user, G_TYPE_OBJECT);
76
77 #define GET_LIST_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER_LIST, LightDMUserListPrivate)
78 #define GET_USER_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER, LightDMUserPrivate)
79
80 static LightDMUserList *singleton = NULL;
81
82 /**
83  * lightdm_user_list_get_instance:
84  *
85  * Get the user list.
86  *
87  * Return value: (transfer none): the #LightDMUserList
88  **/
89 LightDMUserList *
90 lightdm_user_list_get_instance (void)
91 {
92     if (!singleton)
93         singleton = g_object_new (LIGHTDM_TYPE_USER_LIST, NULL);
94     return singleton;
95 }
96
97 static void
98 user_changed_cb (CommonUser *common_user, LightDMUser *lightdm_user)
99 {
100     g_signal_emit (lightdm_user, user_signals[CHANGED], 0);
101 }
102
103 static LightDMUser *
104 wrap_common_user (CommonUser *user)
105 {
106     LightDMUser *lightdm_user = g_object_new (LIGHTDM_TYPE_USER, "common-user", user, NULL);
107     g_signal_connect (user, "changed", G_CALLBACK (user_changed_cb), lightdm_user);
108     return lightdm_user;
109 }
110
111 static void
112 user_list_added_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
113 {
114     LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
115     GList *common_users = common_user_list_get_users (common_list);
116     LightDMUser *lightdm_user = wrap_common_user (common_user);
117     priv->lightdm_list = g_list_insert (priv->lightdm_list, lightdm_user, g_list_index (common_users, common_user));
118     g_signal_emit (user_list, list_signals[USER_ADDED], 0, lightdm_user);
119 }
120
121 static void
122 user_list_changed_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
123 {
124     LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
125     GList *common_users = common_user_list_get_users (common_list);
126     LightDMUser *lightdm_user = g_list_nth_data (priv->lightdm_list, g_list_index (common_users, common_user));
127     g_signal_emit (user_list, list_signals[USER_CHANGED], 0, lightdm_user);
128 }
129
130 static void
131 user_list_removed_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
132 {
133     LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
134     GList *link;
135
136     for (link = priv->lightdm_list; link; link = link->next)
137     {
138         LightDMUser *lightdm_user = link->data;
139         LightDMUserPrivate *user_priv = GET_USER_PRIVATE (lightdm_user);
140         if (user_priv->common_user == common_user)
141         {
142             priv->lightdm_list = g_list_delete_link (priv->lightdm_list, link);
143             g_signal_emit (user_list, list_signals[USER_REMOVED], 0, lightdm_user);
144             g_object_unref (lightdm_user);
145             break;
146         }
147     }
148 }
149
150 static void
151 initialize_user_list_if_needed (LightDMUserList *user_list)
152 {
153     LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
154     GList *common_users;
155     GList *link;
156
157     if (priv->initialized)
158         return;
159
160     common_users = common_user_list_get_users (common_user_list_get_instance ());
161     for (link = common_users; link; link = link->next)
162     {
163         CommonUser *user = link->data;
164         LightDMUser *lightdm_user = wrap_common_user (user);
165         priv->lightdm_list = g_list_prepend (priv->lightdm_list, lightdm_user);
166     }
167     priv->lightdm_list = g_list_reverse (priv->lightdm_list);
168
169     CommonUserList *common_list = common_user_list_get_instance ();
170     g_signal_connect (common_list, "user-added", G_CALLBACK (user_list_added_cb), user_list);
171     g_signal_connect (common_list, "user-changed", G_CALLBACK (user_list_changed_cb), user_list);
172     g_signal_connect (common_list, "user-removed", G_CALLBACK (user_list_removed_cb), user_list);
173
174     priv->initialized = TRUE;
175 }
176
177 /**
178  * lightdm_user_list_get_length:
179  * @user_list: a #LightDMUserList
180  *
181  * Return value: The number of users able to log in
182  **/
183 gint
184 lightdm_user_list_get_length (LightDMUserList *user_list)
185 {
186     g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), 0);
187     initialize_user_list_if_needed (user_list);
188     return g_list_length (GET_LIST_PRIVATE (user_list)->lightdm_list);
189 }
190
191 /**
192  * lightdm_user_list_get_users:
193  * @user_list: A #LightDMUserList
194  *
195  * Get a list of users to present to the user.  This list may be a subset of the
196  * available users and may be empty depending on the server configuration.
197  *
198  * Return value: (element-type LightDMUser) (transfer none): A list of #LightDMUser that should be presented to the user.
199  **/
200 GList *
201 lightdm_user_list_get_users (LightDMUserList *user_list)
202 {
203     g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), NULL);
204     initialize_user_list_if_needed (user_list);
205     return GET_LIST_PRIVATE (user_list)->lightdm_list;
206 }
207
208 /**
209  * lightdm_user_list_get_user_by_name:
210  * @user_list: A #LightDMUserList
211  * @username: Name of user to get.
212  *
213  * Get infomation about a given user or #NULL if this user doesn't exist.
214  *
215  * Return value: (transfer none): A #LightDMUser entry for the given user.
216  **/
217 LightDMUser *
218 lightdm_user_list_get_user_by_name (LightDMUserList *user_list, const gchar *username)
219 {
220     GList *link;
221
222     g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), NULL);
223     g_return_val_if_fail (username != NULL, NULL);
224
225     initialize_user_list_if_needed (user_list);
226
227     for (link = GET_LIST_PRIVATE (user_list)->lightdm_list; link; link = link->next)
228     {
229         LightDMUser *user = link->data;
230         if (g_strcmp0 (lightdm_user_get_name (user), username) == 0)
231             return user;
232     }
233
234     return NULL;
235 }
236
237 static void
238 lightdm_user_list_init (LightDMUserList *user_list)
239 {
240 }
241
242 static void
243 lightdm_user_list_set_property (GObject    *object,
244                                 guint       prop_id,
245                                 const GValue *value,
246                                 GParamSpec *pspec)
247 {
248     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
249 }
250
251 static void
252 lightdm_user_list_get_property (GObject    *object,
253                                 guint       prop_id,
254                                 GValue     *value,
255                                 GParamSpec *pspec)
256 {
257     LightDMUserList *self;
258
259     self = LIGHTDM_USER_LIST (object);
260
261     switch (prop_id)
262     {
263     case LIST_PROP_NUM_USERS:
264         g_value_set_int (value, lightdm_user_list_get_length (self));
265         break;
266     default:
267         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
268         break;
269     }
270 }
271
272 static void
273 lightdm_user_list_finalize (GObject *object)
274 {
275     LightDMUserList *self = LIGHTDM_USER_LIST (object);
276     LightDMUserListPrivate *priv = GET_LIST_PRIVATE (self);
277
278     g_list_free_full (priv->lightdm_list, g_object_unref);
279
280     G_OBJECT_CLASS (lightdm_user_list_parent_class)->finalize (object);
281 }
282
283 static void
284 lightdm_user_list_class_init (LightDMUserListClass *klass)
285 {
286     GObjectClass *object_class = G_OBJECT_CLASS (klass);
287
288     g_type_class_add_private (klass, sizeof (LightDMUserListPrivate));
289
290     object_class->set_property = lightdm_user_list_set_property;
291     object_class->get_property = lightdm_user_list_get_property;
292     object_class->finalize = lightdm_user_list_finalize;
293
294     g_object_class_install_property (object_class,
295                                      LIST_PROP_NUM_USERS,
296                                      g_param_spec_int ("num-users",
297                                                        "num-users",
298                                                        "Number of login users",
299                                                        0, G_MAXINT, 0,
300                                                        G_PARAM_READABLE));
301     /**
302      * LightDMUserList::user-added:
303      * @user_list: A #LightDMUserList
304      * @user: The #LightDM user that has been added.
305      *
306      * The ::user-added signal gets emitted when a user account is created.
307      **/
308     list_signals[USER_ADDED] =
309         g_signal_new ("user-added",
310                       G_TYPE_FROM_CLASS (klass),
311                       G_SIGNAL_RUN_LAST,
312                       G_STRUCT_OFFSET (LightDMUserListClass, user_added),
313                       NULL, NULL,
314                       NULL,
315                       G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
316
317     /**
318      * LightDMUserList::user-changed:
319      * @user_list: A #LightDMUserList
320      * @user: The #LightDM user that has been changed.
321      *
322      * The ::user-changed signal gets emitted when a user account is modified.
323      **/
324     list_signals[USER_CHANGED] =
325         g_signal_new ("user-changed",
326                       G_TYPE_FROM_CLASS (klass),
327                       G_SIGNAL_RUN_LAST,
328                       G_STRUCT_OFFSET (LightDMUserListClass, user_changed),
329                       NULL, NULL,
330                       NULL,
331                       G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
332
333     /**
334      * LightDMUserList::user-removed:
335      * @user_list: A #LightDMUserList
336      * @user: The #LightDM user that has been removed.
337      *
338      * The ::user-removed signal gets emitted when a user account is removed.
339      **/
340     list_signals[USER_REMOVED] =
341         g_signal_new ("user-removed",
342                       G_TYPE_FROM_CLASS (klass),
343                       G_SIGNAL_RUN_LAST,
344                       G_STRUCT_OFFSET (LightDMUserListClass, user_removed),
345                       NULL, NULL,
346                       NULL,
347                       G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
348 }
349
350 /**
351  * lightdm_user_get_name:
352  * @user: A #LightDMUser
353  * 
354  * Get the name of a user.
355  * 
356  * Return value: The name of the given user
357  **/
358 const gchar *
359 lightdm_user_get_name (LightDMUser *user)
360 {
361     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
362     return common_user_get_name (GET_USER_PRIVATE (user)->common_user);
363 }
364
365 /**
366  * lightdm_user_get_real_name:
367  * @user: A #LightDMUser
368  * 
369  * Get the real name of a user.
370  *
371  * Return value: The real name of the given user
372  **/
373 const gchar *
374 lightdm_user_get_real_name (LightDMUser *user)
375 {
376     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
377     return common_user_get_real_name (GET_USER_PRIVATE (user)->common_user);
378 }
379
380 /**
381  * lightdm_user_get_display_name:
382  * @user: A #LightDMUser
383  * 
384  * Get the display name of a user.
385  * 
386  * Return value: The display name of the given user
387  **/
388 const gchar *
389 lightdm_user_get_display_name (LightDMUser *user)
390 {
391     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
392     return common_user_get_display_name (GET_USER_PRIVATE (user)->common_user);
393 }
394
395 /**
396  * lightdm_user_get_home_directory:
397  * @user: A #LightDMUser
398  * 
399  * Get the home directory for a user.
400  * 
401  * Return value: The users home directory
402  */
403 const gchar *
404 lightdm_user_get_home_directory (LightDMUser *user)
405 {
406     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
407     return common_user_get_home_directory (GET_USER_PRIVATE (user)->common_user);
408 }
409
410 /**
411  * lightdm_user_get_image:
412  * @user: A #LightDMUser
413  * 
414  * Get the image URI for a user.
415  * 
416  * Return value: The image URI for the given user or #NULL if no URI
417  **/
418 const gchar *
419 lightdm_user_get_image (LightDMUser *user)
420 {
421     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
422     return common_user_get_image (GET_USER_PRIVATE (user)->common_user);
423 }
424
425 /**
426  * lightdm_user_get_background:
427  * @user: A #LightDMUser
428  * 
429  * Get the background file path for a user.
430  * 
431  * Return value: The background file path for the given user or #NULL if no path
432  **/
433 const gchar *
434 lightdm_user_get_background (LightDMUser *user)
435 {
436     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
437     return common_user_get_background (GET_USER_PRIVATE (user)->common_user);
438 }
439
440 /**
441  * lightdm_user_get_language:
442  * @user: A #LightDMUser
443  * 
444  * Get the language for a user.
445  * 
446  * Return value: The language in the form of a local specification (e.g. "de_DE.UTF-8") for the given user or #NULL if using the system default locale.
447  **/
448 const gchar *
449 lightdm_user_get_language (LightDMUser *user)
450 {
451     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
452     return common_user_get_language (GET_USER_PRIVATE (user)->common_user);
453 }
454
455 /**
456  * lightdm_user_get_layout:
457  * @user: A #LightDMUser
458  * 
459  * Get the keyboard layout for a user.
460  * 
461  * Return value: The keyboard layout for the given user or #NULL if using system defaults.  Copy the value if you want to use it long term.
462  **/
463 const gchar *
464 lightdm_user_get_layout (LightDMUser *user)
465 {
466     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
467     return common_user_get_layout (GET_USER_PRIVATE (user)->common_user);
468 }
469
470 /**
471  * lightdm_user_get_layouts:
472  * @user: A #LightDMUser
473  * 
474  * Get the configured keyboard layouts for a user.
475  * 
476  * Return value: (transfer none): A NULL-terminated array of keyboard layouts for the given user.  Copy the values if you want to use them long term.
477  **/
478 const gchar * const *
479 lightdm_user_get_layouts (LightDMUser *user)
480 {
481     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
482     return common_user_get_layouts (GET_USER_PRIVATE (user)->common_user);
483 }
484
485 /**
486  * lightdm_user_get_session:
487  * @user: A #LightDMUser
488  * 
489  * Get the session for a user.
490  * 
491  * Return value: The session for the given user or #NULL if using system defaults.
492  **/
493 const gchar *
494 lightdm_user_get_session (LightDMUser *user)
495 {
496     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
497     return common_user_get_session (GET_USER_PRIVATE (user)->common_user);
498 }
499
500 /**
501  * lightdm_user_get_logged_in:
502  * @user: A #LightDMUser
503  * 
504  * Check if a user is logged in.
505  * 
506  * Return value: #TRUE if the user is currently logged in.
507  **/
508 gboolean
509 lightdm_user_get_logged_in (LightDMUser *user)
510 {
511     g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
512     return common_user_get_logged_in (GET_USER_PRIVATE (user)->common_user);
513 }
514
515 /**
516  * lightdm_user_get_has_messages:
517  * @user: A #LightDMUser
518  * 
519  * Check if a user has waiting messages.
520  * 
521  * Return value: #TRUE if the user has waiting messages.
522  **/
523 gboolean
524 lightdm_user_get_has_messages (LightDMUser *user)
525 {
526     g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
527     return common_user_get_has_messages (GET_USER_PRIVATE (user)->common_user);
528 }
529
530 /**
531  * lightdm_user_get_uid:
532  * @user: A #LightDMUser
533  * 
534  * Get the uid of a user.
535  * 
536  * Return value: The uid of the given user
537  **/
538 uid_t
539 lightdm_user_get_display_name (LightDMUser *user)
540 {
541     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
542     return common_user_get_uid (GET_USER_PRIVATE (user)->common_user);
543 }
544
545 static void
546 lightdm_user_init (LightDMUser *user)
547 {
548 }
549
550 static void
551 lightdm_user_set_property (GObject    *object,
552                            guint       prop_id,
553                            const GValue *value,
554                            GParamSpec *pspec)
555 {
556     LightDMUser *self = LIGHTDM_USER (object);
557     LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
558
559     switch (prop_id)
560     {
561     case USER_PROP_COMMON_USER:
562         priv->common_user = g_value_dup_object (value);
563         break;
564     default:
565         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
566         break;
567     }
568 }
569
570 static void
571 lightdm_user_get_property (GObject    *object,
572                            guint       prop_id,
573                            GValue     *value,
574                            GParamSpec *pspec)
575 {
576     LightDMUser *self;
577
578     self = LIGHTDM_USER (object);
579
580     switch (prop_id)
581     {
582     case USER_PROP_NAME:
583         g_value_set_string (value, lightdm_user_get_name (self));
584         break;
585     case USER_PROP_REAL_NAME:
586         g_value_set_string (value, lightdm_user_get_real_name (self));
587         break;
588     case USER_PROP_DISPLAY_NAME:
589         g_value_set_string (value, lightdm_user_get_display_name (self));
590         break;
591     case USER_PROP_HOME_DIRECTORY:
592         g_value_set_string (value, lightdm_user_get_home_directory (self));
593         break;
594     case USER_PROP_IMAGE:
595         g_value_set_string (value, lightdm_user_get_image (self));
596         break;
597     case USER_PROP_BACKGROUND:
598         g_value_set_string (value, lightdm_user_get_background (self));
599         break;
600     case USER_PROP_LANGUAGE:
601         g_value_set_string (value, lightdm_user_get_language (self));
602         break;
603     case USER_PROP_LAYOUT:
604         g_value_set_string (value, lightdm_user_get_layout (self));
605         break;
606     case USER_PROP_LAYOUTS:
607         g_value_set_boxed (value, g_strdupv ((gchar **) lightdm_user_get_layouts (self)));
608         break;
609     case USER_PROP_SESSION:
610         g_value_set_string (value, lightdm_user_get_session (self));
611         break;
612     case USER_PROP_LOGGED_IN:
613         g_value_set_boolean (value, lightdm_user_get_logged_in (self));
614         break;
615     case USER_PROP_HAS_MESSAGES:
616         g_value_set_boolean (value, lightdm_user_get_has_messages (self));
617         break;
618     case USER_PROP_UID:
619         g_value_set_uint64 (value, lightdm_user_get_uid (self));
620         break;
621     default:
622         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
623         break;
624     }
625 }
626
627 static void
628 lightdm_user_finalize (GObject *object)
629 {
630     LightDMUser *self = LIGHTDM_USER (object);
631     LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
632
633     g_object_unref (priv->common_user);
634
635     G_OBJECT_CLASS (lightdm_user_parent_class)->finalize (object);
636 }
637
638 static void
639 lightdm_user_class_init (LightDMUserClass *klass)
640 {
641     GObjectClass *object_class = G_OBJECT_CLASS (klass);
642
643     g_type_class_add_private (klass, sizeof (LightDMUserPrivate));
644
645     object_class->set_property = lightdm_user_set_property;
646     object_class->get_property = lightdm_user_get_property;
647     object_class->finalize = lightdm_user_finalize;
648
649     g_object_class_install_property (object_class,
650                                      USER_PROP_COMMON_USER,
651                                      g_param_spec_object ("common-user",
652                                                           "common-user",
653                                                           "Internal user object",
654                                                           COMMON_TYPE_USER,
655                                                           G_PARAM_PRIVATE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_WRITABLE));
656     g_object_class_install_property (object_class,
657                                      USER_PROP_NAME,
658                                      g_param_spec_string ("name",
659                                                           "name",
660                                                           "Username",
661                                                           NULL,
662                                                           G_PARAM_READWRITE));
663     g_object_class_install_property (object_class,
664                                      USER_PROP_REAL_NAME,
665                                      g_param_spec_string ("real-name",
666                                                           "real-name",
667                                                           "Users real name",
668                                                           NULL,
669                                                           G_PARAM_READWRITE));
670     g_object_class_install_property (object_class,
671                                      USER_PROP_DISPLAY_NAME,
672                                      g_param_spec_string ("display-name",
673                                                           "display-name",
674                                                           "Users display name",
675                                                           NULL,
676                                                           G_PARAM_READABLE));
677     g_object_class_install_property (object_class,
678                                      USER_PROP_HOME_DIRECTORY,
679                                      g_param_spec_string ("home-directory",
680                                                           "home-directory",
681                                                           "Home directory",
682                                                           NULL,
683                                                           G_PARAM_READWRITE));
684     g_object_class_install_property (object_class,
685                                      USER_PROP_IMAGE,
686                                      g_param_spec_string ("image",
687                                                           "image",
688                                                           "Avatar image",
689                                                           NULL,
690                                                           G_PARAM_READWRITE));
691     g_object_class_install_property (object_class,
692                                      USER_PROP_BACKGROUND,
693                                      g_param_spec_string ("background",
694                                                           "background",
695                                                           "User background",
696                                                           NULL,
697                                                           G_PARAM_READWRITE));
698     g_object_class_install_property (object_class,
699                                      USER_PROP_LANGUAGE,
700                                      g_param_spec_string ("language",
701                                                          "language",
702                                                          "Language used by this user",
703                                                          NULL,
704                                                          G_PARAM_READABLE));
705     g_object_class_install_property (object_class,
706                                      USER_PROP_LAYOUT,
707                                      g_param_spec_string ("layout",
708                                                           "layout",
709                                                           "Keyboard layout used by this user",
710                                                           NULL,
711                                                           G_PARAM_READABLE));
712     g_object_class_install_property (object_class,
713                                      USER_PROP_LAYOUTS,
714                                      g_param_spec_boxed ("layouts",
715                                                          "layouts",
716                                                          "Keyboard layouts used by this user",
717                                                          G_TYPE_STRV,
718                                                          G_PARAM_READABLE));
719     g_object_class_install_property (object_class,
720                                      USER_PROP_SESSION,
721                                      g_param_spec_string ("session",
722                                                           "session",
723                                                           "Session used by this user",
724                                                           NULL,
725                                                           G_PARAM_READABLE));
726     g_object_class_install_property (object_class,
727                                      USER_PROP_LOGGED_IN,
728                                      g_param_spec_boolean ("logged-in",
729                                                            "logged-in",
730                                                            "TRUE if the user is currently in a session",
731                                                            FALSE,
732                                                            G_PARAM_READWRITE));
733     g_object_class_install_property (object_class,
734                                      USER_PROP_LOGGED_IN,
735                                      g_param_spec_boolean ("has-messages",
736                                                            "has-messages",
737                                                            "TRUE if the user is has waiting messages",
738                                                            FALSE,
739                                                            G_PARAM_READWRITE));
740     g_object_class_install_property (object_class,
741                                      USER_PROP_UID,
742                                      g_param_spec_string ("uid",
743                                                           "uid",
744                                                           "User UID",
745                                                           NULL,
746                                                           G_PARAM_READABLE));
747
748     /**
749      * LightDMUser::changed:
750      * @user: A #LightDMUser
751      *
752      * The ::changed signal gets emitted this user account is modified.
753      **/
754     user_signals[CHANGED] =
755         g_signal_new ("changed",
756                       G_TYPE_FROM_CLASS (klass),
757                       G_SIGNAL_RUN_LAST,
758                       G_STRUCT_OFFSET (LightDMUserClass, changed),
759                       NULL, NULL,
760                       NULL,
761                       G_TYPE_NONE, 0);
762 }