1 /* -*- Mode: C; indent-tabs-mode:nil; tab-width:4 -*-
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>
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.
16 #include "user-list.h"
17 #include "lightdm/user.h"
29 USER_PROP_COMMON_USER,
32 USER_PROP_DISPLAY_NAME,
33 USER_PROP_HOME_DIRECTORY,
41 USER_PROP_HAS_MESSAGES,
52 static guint list_signals[LAST_LIST_SIGNAL] = { 0 };
59 static guint user_signals[LAST_USER_SIGNAL] = { 0 };
65 /* Wrapper list, kept locally to preserve transfer-none promises */
67 } LightDMUserListPrivate;
71 CommonUser *common_user;
74 G_DEFINE_TYPE (LightDMUserList, lightdm_user_list, G_TYPE_OBJECT);
75 G_DEFINE_TYPE (LightDMUser, lightdm_user, G_TYPE_OBJECT);
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)
80 static LightDMUserList *singleton = NULL;
83 * lightdm_user_list_get_instance:
87 * Return value: (transfer none): the #LightDMUserList
90 lightdm_user_list_get_instance (void)
93 singleton = g_object_new (LIGHTDM_TYPE_USER_LIST, NULL);
98 user_changed_cb (CommonUser *common_user, LightDMUser *lightdm_user)
100 g_signal_emit (lightdm_user, user_signals[CHANGED], 0);
104 wrap_common_user (CommonUser *user)
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);
112 user_list_added_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
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);
122 user_list_changed_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
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);
131 user_list_removed_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
133 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
136 for (link = priv->lightdm_list; link; link = link->next)
138 LightDMUser *lightdm_user = link->data;
139 LightDMUserPrivate *user_priv = GET_USER_PRIVATE (lightdm_user);
140 if (user_priv->common_user == common_user)
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);
151 initialize_user_list_if_needed (LightDMUserList *user_list)
153 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
157 if (priv->initialized)
160 common_users = common_user_list_get_users (common_user_list_get_instance ());
161 for (link = common_users; link; link = link->next)
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);
167 priv->lightdm_list = g_list_reverse (priv->lightdm_list);
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);
174 priv->initialized = TRUE;
178 * lightdm_user_list_get_length:
179 * @user_list: a #LightDMUserList
181 * Return value: The number of users able to log in
184 lightdm_user_list_get_length (LightDMUserList *user_list)
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);
192 * lightdm_user_list_get_users:
193 * @user_list: A #LightDMUserList
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.
198 * Return value: (element-type LightDMUser) (transfer none): A list of #LightDMUser that should be presented to the user.
201 lightdm_user_list_get_users (LightDMUserList *user_list)
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;
209 * lightdm_user_list_get_user_by_name:
210 * @user_list: A #LightDMUserList
211 * @username: Name of user to get.
213 * Get infomation about a given user or #NULL if this user doesn't exist.
215 * Return value: (transfer none): A #LightDMUser entry for the given user.
218 lightdm_user_list_get_user_by_name (LightDMUserList *user_list, const gchar *username)
222 g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), NULL);
223 g_return_val_if_fail (username != NULL, NULL);
225 initialize_user_list_if_needed (user_list);
227 for (link = GET_LIST_PRIVATE (user_list)->lightdm_list; link; link = link->next)
229 LightDMUser *user = link->data;
230 if (g_strcmp0 (lightdm_user_get_name (user), username) == 0)
238 lightdm_user_list_init (LightDMUserList *user_list)
243 lightdm_user_list_set_property (GObject *object,
248 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
252 lightdm_user_list_get_property (GObject *object,
257 LightDMUserList *self;
259 self = LIGHTDM_USER_LIST (object);
263 case LIST_PROP_NUM_USERS:
264 g_value_set_int (value, lightdm_user_list_get_length (self));
267 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
273 lightdm_user_list_finalize (GObject *object)
275 LightDMUserList *self = LIGHTDM_USER_LIST (object);
276 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (self);
278 g_list_free_full (priv->lightdm_list, g_object_unref);
280 G_OBJECT_CLASS (lightdm_user_list_parent_class)->finalize (object);
284 lightdm_user_list_class_init (LightDMUserListClass *klass)
286 GObjectClass *object_class = G_OBJECT_CLASS (klass);
288 g_type_class_add_private (klass, sizeof (LightDMUserListPrivate));
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;
294 g_object_class_install_property (object_class,
296 g_param_spec_int ("num-users",
298 "Number of login users",
302 * LightDMUserList::user-added:
303 * @user_list: A #LightDMUserList
304 * @user: The #LightDM user that has been added.
306 * The ::user-added signal gets emitted when a user account is created.
308 list_signals[USER_ADDED] =
309 g_signal_new ("user-added",
310 G_TYPE_FROM_CLASS (klass),
312 G_STRUCT_OFFSET (LightDMUserListClass, user_added),
315 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
318 * LightDMUserList::user-changed:
319 * @user_list: A #LightDMUserList
320 * @user: The #LightDM user that has been changed.
322 * The ::user-changed signal gets emitted when a user account is modified.
324 list_signals[USER_CHANGED] =
325 g_signal_new ("user-changed",
326 G_TYPE_FROM_CLASS (klass),
328 G_STRUCT_OFFSET (LightDMUserListClass, user_changed),
331 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
334 * LightDMUserList::user-removed:
335 * @user_list: A #LightDMUserList
336 * @user: The #LightDM user that has been removed.
338 * The ::user-removed signal gets emitted when a user account is removed.
340 list_signals[USER_REMOVED] =
341 g_signal_new ("user-removed",
342 G_TYPE_FROM_CLASS (klass),
344 G_STRUCT_OFFSET (LightDMUserListClass, user_removed),
347 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
351 * lightdm_user_get_name:
352 * @user: A #LightDMUser
354 * Get the name of a user.
356 * Return value: The name of the given user
359 lightdm_user_get_name (LightDMUser *user)
361 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
362 return common_user_get_name (GET_USER_PRIVATE (user)->common_user);
366 * lightdm_user_get_real_name:
367 * @user: A #LightDMUser
369 * Get the real name of a user.
371 * Return value: The real name of the given user
374 lightdm_user_get_real_name (LightDMUser *user)
376 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
377 return common_user_get_real_name (GET_USER_PRIVATE (user)->common_user);
381 * lightdm_user_get_display_name:
382 * @user: A #LightDMUser
384 * Get the display name of a user.
386 * Return value: The display name of the given user
389 lightdm_user_get_display_name (LightDMUser *user)
391 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
392 return common_user_get_display_name (GET_USER_PRIVATE (user)->common_user);
396 * lightdm_user_get_home_directory:
397 * @user: A #LightDMUser
399 * Get the home directory for a user.
401 * Return value: The users home directory
404 lightdm_user_get_home_directory (LightDMUser *user)
406 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
407 return common_user_get_home_directory (GET_USER_PRIVATE (user)->common_user);
411 * lightdm_user_get_image:
412 * @user: A #LightDMUser
414 * Get the image URI for a user.
416 * Return value: The image URI for the given user or #NULL if no URI
419 lightdm_user_get_image (LightDMUser *user)
421 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
422 return common_user_get_image (GET_USER_PRIVATE (user)->common_user);
426 * lightdm_user_get_background:
427 * @user: A #LightDMUser
429 * Get the background file path for a user.
431 * Return value: The background file path for the given user or #NULL if no path
434 lightdm_user_get_background (LightDMUser *user)
436 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
437 return common_user_get_background (GET_USER_PRIVATE (user)->common_user);
441 * lightdm_user_get_language:
442 * @user: A #LightDMUser
444 * Get the language for a user.
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.
449 lightdm_user_get_language (LightDMUser *user)
451 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
452 return common_user_get_language (GET_USER_PRIVATE (user)->common_user);
456 * lightdm_user_get_layout:
457 * @user: A #LightDMUser
459 * Get the keyboard layout for a user.
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.
464 lightdm_user_get_layout (LightDMUser *user)
466 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
467 return common_user_get_layout (GET_USER_PRIVATE (user)->common_user);
471 * lightdm_user_get_layouts:
472 * @user: A #LightDMUser
474 * Get the configured keyboard layouts for a user.
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.
478 const gchar * const *
479 lightdm_user_get_layouts (LightDMUser *user)
481 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
482 return common_user_get_layouts (GET_USER_PRIVATE (user)->common_user);
486 * lightdm_user_get_session:
487 * @user: A #LightDMUser
489 * Get the session for a user.
491 * Return value: The session for the given user or #NULL if using system defaults.
494 lightdm_user_get_session (LightDMUser *user)
496 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
497 return common_user_get_session (GET_USER_PRIVATE (user)->common_user);
501 * lightdm_user_get_logged_in:
502 * @user: A #LightDMUser
504 * Check if a user is logged in.
506 * Return value: #TRUE if the user is currently logged in.
509 lightdm_user_get_logged_in (LightDMUser *user)
511 g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
512 return common_user_get_logged_in (GET_USER_PRIVATE (user)->common_user);
516 * lightdm_user_get_has_messages:
517 * @user: A #LightDMUser
519 * Check if a user has waiting messages.
521 * Return value: #TRUE if the user has waiting messages.
524 lightdm_user_get_has_messages (LightDMUser *user)
526 g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
527 return common_user_get_has_messages (GET_USER_PRIVATE (user)->common_user);
531 * lightdm_user_get_uid:
532 * @user: A #LightDMUser
534 * Get the uid of a user.
536 * Return value: The uid of the given user
539 lightdm_user_get_display_name (LightDMUser *user)
541 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
542 return common_user_get_uid (GET_USER_PRIVATE (user)->common_user);
546 lightdm_user_init (LightDMUser *user)
551 lightdm_user_set_property (GObject *object,
556 LightDMUser *self = LIGHTDM_USER (object);
557 LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
561 case USER_PROP_COMMON_USER:
562 priv->common_user = g_value_dup_object (value);
565 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
571 lightdm_user_get_property (GObject *object,
578 self = LIGHTDM_USER (object);
583 g_value_set_string (value, lightdm_user_get_name (self));
585 case USER_PROP_REAL_NAME:
586 g_value_set_string (value, lightdm_user_get_real_name (self));
588 case USER_PROP_DISPLAY_NAME:
589 g_value_set_string (value, lightdm_user_get_display_name (self));
591 case USER_PROP_HOME_DIRECTORY:
592 g_value_set_string (value, lightdm_user_get_home_directory (self));
594 case USER_PROP_IMAGE:
595 g_value_set_string (value, lightdm_user_get_image (self));
597 case USER_PROP_BACKGROUND:
598 g_value_set_string (value, lightdm_user_get_background (self));
600 case USER_PROP_LANGUAGE:
601 g_value_set_string (value, lightdm_user_get_language (self));
603 case USER_PROP_LAYOUT:
604 g_value_set_string (value, lightdm_user_get_layout (self));
606 case USER_PROP_LAYOUTS:
607 g_value_set_boxed (value, g_strdupv ((gchar **) lightdm_user_get_layouts (self)));
609 case USER_PROP_SESSION:
610 g_value_set_string (value, lightdm_user_get_session (self));
612 case USER_PROP_LOGGED_IN:
613 g_value_set_boolean (value, lightdm_user_get_logged_in (self));
615 case USER_PROP_HAS_MESSAGES:
616 g_value_set_boolean (value, lightdm_user_get_has_messages (self));
619 g_value_set_uint64 (value, lightdm_user_get_uid (self));
622 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
628 lightdm_user_finalize (GObject *object)
630 LightDMUser *self = LIGHTDM_USER (object);
631 LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
633 g_object_unref (priv->common_user);
635 G_OBJECT_CLASS (lightdm_user_parent_class)->finalize (object);
639 lightdm_user_class_init (LightDMUserClass *klass)
641 GObjectClass *object_class = G_OBJECT_CLASS (klass);
643 g_type_class_add_private (klass, sizeof (LightDMUserPrivate));
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;
649 g_object_class_install_property (object_class,
650 USER_PROP_COMMON_USER,
651 g_param_spec_object ("common-user",
653 "Internal user object",
655 G_PARAM_PRIVATE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_WRITABLE));
656 g_object_class_install_property (object_class,
658 g_param_spec_string ("name",
663 g_object_class_install_property (object_class,
665 g_param_spec_string ("real-name",
670 g_object_class_install_property (object_class,
671 USER_PROP_DISPLAY_NAME,
672 g_param_spec_string ("display-name",
674 "Users display name",
677 g_object_class_install_property (object_class,
678 USER_PROP_HOME_DIRECTORY,
679 g_param_spec_string ("home-directory",
684 g_object_class_install_property (object_class,
686 g_param_spec_string ("image",
691 g_object_class_install_property (object_class,
692 USER_PROP_BACKGROUND,
693 g_param_spec_string ("background",
698 g_object_class_install_property (object_class,
700 g_param_spec_string ("language",
702 "Language used by this user",
705 g_object_class_install_property (object_class,
707 g_param_spec_string ("layout",
709 "Keyboard layout used by this user",
712 g_object_class_install_property (object_class,
714 g_param_spec_boxed ("layouts",
716 "Keyboard layouts used by this user",
719 g_object_class_install_property (object_class,
721 g_param_spec_string ("session",
723 "Session used by this user",
726 g_object_class_install_property (object_class,
728 g_param_spec_boolean ("logged-in",
730 "TRUE if the user is currently in a session",
733 g_object_class_install_property (object_class,
735 g_param_spec_boolean ("has-messages",
737 "TRUE if the user is has waiting messages",
740 g_object_class_install_property (object_class,
742 g_param_spec_string ("uid",
749 * LightDMUser::changed:
750 * @user: A #LightDMUser
752 * The ::changed signal gets emitted this user account is modified.
754 user_signals[CHANGED] =
755 g_signal_new ("changed",
756 G_TYPE_FROM_CLASS (klass),
758 G_STRUCT_OFFSET (LightDMUserClass, changed),