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"
21 LIST_PROP_NUM_USERS = 1,
28 USER_PROP_COMMON_USER = 1,
31 USER_PROP_DISPLAY_NAME,
32 USER_PROP_HOME_DIRECTORY,
40 USER_PROP_HAS_MESSAGES,
51 static guint list_signals[LAST_LIST_SIGNAL] = { 0 };
58 static guint user_signals[LAST_USER_SIGNAL] = { 0 };
64 /* Wrapper list, kept locally to preserve transfer-none promises */
66 } LightDMUserListPrivate;
70 CommonUser *common_user;
73 G_DEFINE_TYPE (LightDMUserList, lightdm_user_list, G_TYPE_OBJECT);
74 G_DEFINE_TYPE (LightDMUser, lightdm_user, G_TYPE_OBJECT);
76 #define GET_LIST_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER_LIST, LightDMUserListPrivate)
77 #define GET_USER_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER, LightDMUserPrivate)
79 static LightDMUserList *singleton = NULL;
82 * lightdm_user_list_get_instance:
86 * Return value: (transfer none): the #LightDMUserList
89 lightdm_user_list_get_instance (void)
92 singleton = g_object_new (LIGHTDM_TYPE_USER_LIST, NULL);
97 user_changed_cb (CommonUser *common_user, LightDMUser *lightdm_user)
99 g_signal_emit (lightdm_user, user_signals[CHANGED], 0);
103 wrap_common_user (CommonUser *user)
105 LightDMUser *lightdm_user = g_object_new (LIGHTDM_TYPE_USER, "common-user", user, NULL);
106 g_signal_connect (user, USER_SIGNAL_CHANGED, G_CALLBACK (user_changed_cb), lightdm_user);
111 user_list_added_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
113 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
114 GList *common_users = common_user_list_get_users (common_list);
115 LightDMUser *lightdm_user = wrap_common_user (common_user);
116 priv->lightdm_list = g_list_insert (priv->lightdm_list, lightdm_user, g_list_index (common_users, common_user));
117 g_signal_emit (user_list, list_signals[USER_ADDED], 0, lightdm_user);
121 user_list_changed_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
123 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
124 GList *common_users = common_user_list_get_users (common_list);
125 LightDMUser *lightdm_user = g_list_nth_data (priv->lightdm_list, g_list_index (common_users, common_user));
126 g_signal_emit (user_list, list_signals[USER_CHANGED], 0, lightdm_user);
130 user_list_removed_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
132 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
135 for (link = priv->lightdm_list; link; link = link->next)
137 LightDMUser *lightdm_user = link->data;
138 LightDMUserPrivate *user_priv = GET_USER_PRIVATE (lightdm_user);
139 if (user_priv->common_user == common_user)
141 priv->lightdm_list = g_list_delete_link (priv->lightdm_list, link);
142 g_signal_emit (user_list, list_signals[USER_REMOVED], 0, lightdm_user);
143 g_object_unref (lightdm_user);
150 initialize_user_list_if_needed (LightDMUserList *user_list)
152 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
156 if (priv->initialized)
159 common_users = common_user_list_get_users (common_user_list_get_instance ());
160 for (link = common_users; link; link = link->next)
162 CommonUser *user = link->data;
163 LightDMUser *lightdm_user = wrap_common_user (user);
164 priv->lightdm_list = g_list_prepend (priv->lightdm_list, lightdm_user);
166 priv->lightdm_list = g_list_reverse (priv->lightdm_list);
168 CommonUserList *common_list = common_user_list_get_instance ();
169 g_signal_connect (common_list, USER_LIST_SIGNAL_USER_ADDED, G_CALLBACK (user_list_added_cb), user_list);
170 g_signal_connect (common_list, USER_LIST_SIGNAL_USER_CHANGED, G_CALLBACK (user_list_changed_cb), user_list);
171 g_signal_connect (common_list, USER_LIST_SIGNAL_USER_REMOVED, G_CALLBACK (user_list_removed_cb), user_list);
173 priv->initialized = TRUE;
177 * lightdm_user_list_get_length:
178 * @user_list: a #LightDMUserList
180 * Return value: The number of users able to log in
183 lightdm_user_list_get_length (LightDMUserList *user_list)
185 g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), 0);
186 initialize_user_list_if_needed (user_list);
187 return g_list_length (GET_LIST_PRIVATE (user_list)->lightdm_list);
191 * lightdm_user_list_get_users:
192 * @user_list: A #LightDMUserList
194 * Get a list of users to present to the user. This list may be a subset of the
195 * available users and may be empty depending on the server configuration.
197 * Return value: (element-type LightDMUser) (transfer none): A list of #LightDMUser that should be presented to the user.
200 lightdm_user_list_get_users (LightDMUserList *user_list)
202 g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), NULL);
203 initialize_user_list_if_needed (user_list);
204 return GET_LIST_PRIVATE (user_list)->lightdm_list;
208 * lightdm_user_list_get_user_by_name:
209 * @user_list: A #LightDMUserList
210 * @username: Name of user to get.
212 * Get infomation about a given user or #NULL if this user doesn't exist.
214 * Return value: (transfer none): A #LightDMUser entry for the given user.
217 lightdm_user_list_get_user_by_name (LightDMUserList *user_list, const gchar *username)
221 g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), NULL);
222 g_return_val_if_fail (username != NULL, NULL);
224 initialize_user_list_if_needed (user_list);
226 for (link = GET_LIST_PRIVATE (user_list)->lightdm_list; link; link = link->next)
228 LightDMUser *user = link->data;
229 if (g_strcmp0 (lightdm_user_get_name (user), username) == 0)
237 lightdm_user_list_init (LightDMUserList *user_list)
242 lightdm_user_list_set_property (GObject *object,
247 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
251 lightdm_user_list_get_property (GObject *object,
256 LightDMUserList *self;
258 self = LIGHTDM_USER_LIST (object);
262 case LIST_PROP_NUM_USERS:
263 case LIST_PROP_LENGTH:
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",
300 G_PARAM_DEPRECATED | G_PARAM_READABLE));
302 g_object_class_install_property (object_class,
304 g_param_spec_int ("length",
306 "Number of login users",
310 /*g_object_class_install_property (object_class,
312 g_param_spec_int ("users",
314 "Users to present to user",
316 G_PARAM_READABLE));*/
318 * LightDMUserList::user-added:
319 * @user_list: A #LightDMUserList
320 * @user: The #LightDM user that has been added.
322 * The ::user-added signal gets emitted when a user account is created.
324 list_signals[USER_ADDED] =
325 g_signal_new (LIGHTDM_USER_LIST_SIGNAL_USER_ADDED,
326 G_TYPE_FROM_CLASS (klass),
328 G_STRUCT_OFFSET (LightDMUserListClass, user_added),
331 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
334 * LightDMUserList::user-changed:
335 * @user_list: A #LightDMUserList
336 * @user: The #LightDM user that has been changed.
338 * The ::user-changed signal gets emitted when a user account is modified.
340 list_signals[USER_CHANGED] =
341 g_signal_new (LIGHTDM_USER_LIST_SIGNAL_USER_CHANGED,
342 G_TYPE_FROM_CLASS (klass),
344 G_STRUCT_OFFSET (LightDMUserListClass, user_changed),
347 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
350 * LightDMUserList::user-removed:
351 * @user_list: A #LightDMUserList
352 * @user: The #LightDM user that has been removed.
354 * The ::user-removed signal gets emitted when a user account is removed.
356 list_signals[USER_REMOVED] =
357 g_signal_new (LIGHTDM_USER_LIST_SIGNAL_USER_REMOVED,
358 G_TYPE_FROM_CLASS (klass),
360 G_STRUCT_OFFSET (LightDMUserListClass, user_removed),
363 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
367 * lightdm_user_get_name:
368 * @user: A #LightDMUser
370 * Get the name of a user.
372 * Return value: The name of the given user
375 lightdm_user_get_name (LightDMUser *user)
377 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
378 return common_user_get_name (GET_USER_PRIVATE (user)->common_user);
382 * lightdm_user_get_real_name:
383 * @user: A #LightDMUser
385 * Get the real name of a user.
387 * Return value: The real name of the given user
390 lightdm_user_get_real_name (LightDMUser *user)
392 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
393 return common_user_get_real_name (GET_USER_PRIVATE (user)->common_user);
397 * lightdm_user_get_display_name:
398 * @user: A #LightDMUser
400 * Get the display name of a user.
402 * Return value: The display name of the given user
405 lightdm_user_get_display_name (LightDMUser *user)
407 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
408 return common_user_get_display_name (GET_USER_PRIVATE (user)->common_user);
412 * lightdm_user_get_home_directory:
413 * @user: A #LightDMUser
415 * Get the home directory for a user.
417 * Return value: The users home directory
420 lightdm_user_get_home_directory (LightDMUser *user)
422 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
423 return common_user_get_home_directory (GET_USER_PRIVATE (user)->common_user);
427 * lightdm_user_get_image:
428 * @user: A #LightDMUser
430 * Get the image URI for a user.
432 * Return value: (nullable): The image URI for the given user or #NULL if no URI
435 lightdm_user_get_image (LightDMUser *user)
437 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
438 return common_user_get_image (GET_USER_PRIVATE (user)->common_user);
442 * lightdm_user_get_background:
443 * @user: A #LightDMUser
445 * Get the background file path for a user.
447 * Return value: (nullable): The background file path for the given user or #NULL if no path
450 lightdm_user_get_background (LightDMUser *user)
452 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
453 return common_user_get_background (GET_USER_PRIVATE (user)->common_user);
457 * lightdm_user_get_language:
458 * @user: A #LightDMUser
460 * Get the language for a user.
462 * Return value: (nullable): 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.
465 lightdm_user_get_language (LightDMUser *user)
467 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
468 return common_user_get_language (GET_USER_PRIVATE (user)->common_user);
472 * lightdm_user_get_layout:
473 * @user: A #LightDMUser
475 * Get the keyboard layout for a user.
477 * Return value: (nullable): The keyboard layout for the given user or #NULL if using system defaults. Copy the value if you want to use it long term.
480 lightdm_user_get_layout (LightDMUser *user)
482 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
483 return common_user_get_layout (GET_USER_PRIVATE (user)->common_user);
487 * lightdm_user_get_layouts:
488 * @user: A #LightDMUser
490 * Get the configured keyboard layouts for a user.
492 * 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.
494 const gchar * const *
495 lightdm_user_get_layouts (LightDMUser *user)
497 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
498 return common_user_get_layouts (GET_USER_PRIVATE (user)->common_user);
502 * lightdm_user_get_session:
503 * @user: A #LightDMUser
505 * Get the session for a user.
507 * Return value: (nullable): The session for the given user or #NULL if using system defaults.
510 lightdm_user_get_session (LightDMUser *user)
512 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
513 return common_user_get_session (GET_USER_PRIVATE (user)->common_user);
517 * lightdm_user_get_logged_in:
518 * @user: A #LightDMUser
520 * Check if a user is logged in.
522 * Return value: #TRUE if the user is currently logged in.
525 lightdm_user_get_logged_in (LightDMUser *user)
527 g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
528 return common_user_get_logged_in (GET_USER_PRIVATE (user)->common_user);
532 * lightdm_user_get_has_messages:
533 * @user: A #LightDMUser
535 * Check if a user has waiting messages.
537 * Return value: #TRUE if the user has waiting messages.
540 lightdm_user_get_has_messages (LightDMUser *user)
542 g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
543 return common_user_get_has_messages (GET_USER_PRIVATE (user)->common_user);
547 * lightdm_user_get_uid:
548 * @user: A #LightDMUser
550 * Get the uid of a user.
552 * Return value: The uid of the given user
555 lightdm_user_get_uid (LightDMUser *user)
557 g_return_val_if_fail (LIGHTDM_IS_USER (user), (uid_t)-1);
558 return common_user_get_uid (GET_USER_PRIVATE (user)->common_user);
562 lightdm_user_init (LightDMUser *user)
567 lightdm_user_set_property (GObject *object,
572 LightDMUser *self = LIGHTDM_USER (object);
573 LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
577 case USER_PROP_COMMON_USER:
578 priv->common_user = g_value_dup_object (value);
581 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
587 lightdm_user_get_property (GObject *object,
594 self = LIGHTDM_USER (object);
599 g_value_set_string (value, lightdm_user_get_name (self));
601 case USER_PROP_REAL_NAME:
602 g_value_set_string (value, lightdm_user_get_real_name (self));
604 case USER_PROP_DISPLAY_NAME:
605 g_value_set_string (value, lightdm_user_get_display_name (self));
607 case USER_PROP_HOME_DIRECTORY:
608 g_value_set_string (value, lightdm_user_get_home_directory (self));
610 case USER_PROP_IMAGE:
611 g_value_set_string (value, lightdm_user_get_image (self));
613 case USER_PROP_BACKGROUND:
614 g_value_set_string (value, lightdm_user_get_background (self));
616 case USER_PROP_LANGUAGE:
617 g_value_set_string (value, lightdm_user_get_language (self));
619 case USER_PROP_LAYOUT:
620 g_value_set_string (value, lightdm_user_get_layout (self));
622 case USER_PROP_LAYOUTS:
623 g_value_set_boxed (value, g_strdupv ((gchar **) lightdm_user_get_layouts (self)));
625 case USER_PROP_SESSION:
626 g_value_set_string (value, lightdm_user_get_session (self));
628 case USER_PROP_LOGGED_IN:
629 g_value_set_boolean (value, lightdm_user_get_logged_in (self));
631 case USER_PROP_HAS_MESSAGES:
632 g_value_set_boolean (value, lightdm_user_get_has_messages (self));
635 g_value_set_uint64 (value, lightdm_user_get_uid (self));
638 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
644 lightdm_user_finalize (GObject *object)
646 LightDMUser *self = LIGHTDM_USER (object);
647 LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
649 g_object_unref (priv->common_user);
651 G_OBJECT_CLASS (lightdm_user_parent_class)->finalize (object);
655 lightdm_user_class_init (LightDMUserClass *klass)
657 GObjectClass *object_class = G_OBJECT_CLASS (klass);
659 g_type_class_add_private (klass, sizeof (LightDMUserPrivate));
661 object_class->set_property = lightdm_user_set_property;
662 object_class->get_property = lightdm_user_get_property;
663 object_class->finalize = lightdm_user_finalize;
665 g_object_class_install_property (object_class,
666 USER_PROP_COMMON_USER,
667 g_param_spec_object ("common-user",
669 "Internal user object",
671 G_PARAM_PRIVATE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_WRITABLE));
672 g_object_class_install_property (object_class,
674 g_param_spec_string ("name",
679 g_object_class_install_property (object_class,
681 g_param_spec_string ("real-name",
686 g_object_class_install_property (object_class,
687 USER_PROP_DISPLAY_NAME,
688 g_param_spec_string ("display-name",
690 "Users display name",
693 g_object_class_install_property (object_class,
694 USER_PROP_HOME_DIRECTORY,
695 g_param_spec_string ("home-directory",
700 g_object_class_install_property (object_class,
702 g_param_spec_string ("image",
707 g_object_class_install_property (object_class,
708 USER_PROP_BACKGROUND,
709 g_param_spec_string ("background",
714 g_object_class_install_property (object_class,
716 g_param_spec_string ("language",
718 "Language used by this user",
721 g_object_class_install_property (object_class,
723 g_param_spec_string ("layout",
725 "Keyboard layout used by this user",
728 g_object_class_install_property (object_class,
730 g_param_spec_boxed ("layouts",
732 "Keyboard layouts used by this user",
735 g_object_class_install_property (object_class,
737 g_param_spec_string ("session",
739 "Session used by this user",
742 g_object_class_install_property (object_class,
744 g_param_spec_boolean ("logged-in",
746 "TRUE if the user is currently in a session",
749 g_object_class_install_property (object_class,
751 g_param_spec_boolean ("has-messages",
753 "TRUE if the user is has waiting messages",
756 g_object_class_install_property (object_class,
758 g_param_spec_uint64 ("uid",
765 * LightDMUser::changed:
766 * @user: A #LightDMUser
768 * The ::changed signal gets emitted this user account is modified.
770 user_signals[CHANGED] =
771 g_signal_new (LIGHTDM_SIGNAL_USER_CHANGED,
772 G_TYPE_FROM_CLASS (klass),
774 G_STRUCT_OFFSET (LightDMUserClass, changed),