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"
30 USER_PROP_COMMON_USER,
33 USER_PROP_DISPLAY_NAME,
34 USER_PROP_HOME_DIRECTORY,
42 USER_PROP_HAS_MESSAGES,
53 static guint list_signals[LAST_LIST_SIGNAL] = { 0 };
60 static guint user_signals[LAST_USER_SIGNAL] = { 0 };
66 /* Wrapper list, kept locally to preserve transfer-none promises */
68 } LightDMUserListPrivate;
72 CommonUser *common_user;
75 G_DEFINE_TYPE (LightDMUserList, lightdm_user_list, G_TYPE_OBJECT);
76 G_DEFINE_TYPE (LightDMUser, lightdm_user, G_TYPE_OBJECT);
78 #define GET_LIST_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER_LIST, LightDMUserListPrivate)
79 #define GET_USER_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER, LightDMUserPrivate)
81 static LightDMUserList *singleton = NULL;
84 * lightdm_user_list_get_instance:
88 * Return value: (transfer none): the #LightDMUserList
91 lightdm_user_list_get_instance (void)
94 singleton = g_object_new (LIGHTDM_TYPE_USER_LIST, NULL);
99 user_changed_cb (CommonUser *common_user, LightDMUser *lightdm_user)
101 g_signal_emit (lightdm_user, user_signals[CHANGED], 0);
105 wrap_common_user (CommonUser *user)
107 LightDMUser *lightdm_user = g_object_new (LIGHTDM_TYPE_USER, "common-user", user, NULL);
108 g_signal_connect (user, USER_SIGNAL_CHANGED, G_CALLBACK (user_changed_cb), lightdm_user);
113 user_list_added_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
115 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
116 GList *common_users = common_user_list_get_users (common_list);
117 LightDMUser *lightdm_user = wrap_common_user (common_user);
118 priv->lightdm_list = g_list_insert (priv->lightdm_list, lightdm_user, g_list_index (common_users, common_user));
119 g_signal_emit (user_list, list_signals[USER_ADDED], 0, lightdm_user);
123 user_list_changed_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
125 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
126 GList *common_users = common_user_list_get_users (common_list);
127 LightDMUser *lightdm_user = g_list_nth_data (priv->lightdm_list, g_list_index (common_users, common_user));
128 g_signal_emit (user_list, list_signals[USER_CHANGED], 0, lightdm_user);
132 user_list_removed_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list)
134 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
137 for (link = priv->lightdm_list; link; link = link->next)
139 LightDMUser *lightdm_user = link->data;
140 LightDMUserPrivate *user_priv = GET_USER_PRIVATE (lightdm_user);
141 if (user_priv->common_user == common_user)
143 priv->lightdm_list = g_list_delete_link (priv->lightdm_list, link);
144 g_signal_emit (user_list, list_signals[USER_REMOVED], 0, lightdm_user);
145 g_object_unref (lightdm_user);
152 initialize_user_list_if_needed (LightDMUserList *user_list)
154 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
158 if (priv->initialized)
161 common_users = common_user_list_get_users (common_user_list_get_instance ());
162 for (link = common_users; link; link = link->next)
164 CommonUser *user = link->data;
165 LightDMUser *lightdm_user = wrap_common_user (user);
166 priv->lightdm_list = g_list_prepend (priv->lightdm_list, lightdm_user);
168 priv->lightdm_list = g_list_reverse (priv->lightdm_list);
170 CommonUserList *common_list = common_user_list_get_instance ();
171 g_signal_connect (common_list, USER_LIST_SIGNAL_USER_ADDED, G_CALLBACK (user_list_added_cb), user_list);
172 g_signal_connect (common_list, USER_LIST_SIGNAL_USER_CHANGED, G_CALLBACK (user_list_changed_cb), user_list);
173 g_signal_connect (common_list, USER_LIST_SIGNAL_USER_REMOVED, G_CALLBACK (user_list_removed_cb), user_list);
175 priv->initialized = TRUE;
179 * lightdm_user_list_get_length:
180 * @user_list: a #LightDMUserList
182 * Return value: The number of users able to log in
185 lightdm_user_list_get_length (LightDMUserList *user_list)
187 g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), 0);
188 initialize_user_list_if_needed (user_list);
189 return g_list_length (GET_LIST_PRIVATE (user_list)->lightdm_list);
193 * lightdm_user_list_get_users:
194 * @user_list: A #LightDMUserList
196 * Get a list of users to present to the user. This list may be a subset of the
197 * available users and may be empty depending on the server configuration.
199 * Return value: (element-type LightDMUser) (transfer none): A list of #LightDMUser that should be presented to the user.
202 lightdm_user_list_get_users (LightDMUserList *user_list)
204 g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), NULL);
205 initialize_user_list_if_needed (user_list);
206 return GET_LIST_PRIVATE (user_list)->lightdm_list;
210 * lightdm_user_list_get_user_by_name:
211 * @user_list: A #LightDMUserList
212 * @username: Name of user to get.
214 * Get infomation about a given user or #NULL if this user doesn't exist.
216 * Return value: (transfer none): A #LightDMUser entry for the given user.
219 lightdm_user_list_get_user_by_name (LightDMUserList *user_list, const gchar *username)
223 g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), NULL);
224 g_return_val_if_fail (username != NULL, NULL);
226 initialize_user_list_if_needed (user_list);
228 for (link = GET_LIST_PRIVATE (user_list)->lightdm_list; link; link = link->next)
230 LightDMUser *user = link->data;
231 if (g_strcmp0 (lightdm_user_get_name (user), username) == 0)
239 lightdm_user_list_init (LightDMUserList *user_list)
244 lightdm_user_list_set_property (GObject *object,
249 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
253 lightdm_user_list_get_property (GObject *object,
258 LightDMUserList *self;
260 self = LIGHTDM_USER_LIST (object);
264 case LIST_PROP_NUM_USERS:
265 case LIST_PROP_LENGTH:
266 g_value_set_int (value, lightdm_user_list_get_length (self));
269 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
275 lightdm_user_list_finalize (GObject *object)
277 LightDMUserList *self = LIGHTDM_USER_LIST (object);
278 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (self);
280 g_list_free_full (priv->lightdm_list, g_object_unref);
282 G_OBJECT_CLASS (lightdm_user_list_parent_class)->finalize (object);
286 lightdm_user_list_class_init (LightDMUserListClass *klass)
288 GObjectClass *object_class = G_OBJECT_CLASS (klass);
290 g_type_class_add_private (klass, sizeof (LightDMUserListPrivate));
292 object_class->set_property = lightdm_user_list_set_property;
293 object_class->get_property = lightdm_user_list_get_property;
294 object_class->finalize = lightdm_user_list_finalize;
296 g_object_class_install_property (object_class,
298 g_param_spec_int ("num-users",
300 "Number of login users",
302 G_PARAM_DEPRECATED | G_PARAM_READABLE));
304 g_object_class_install_property (object_class,
306 g_param_spec_int ("length",
308 "Number of login users",
312 /*g_object_class_install_property (object_class,
314 g_param_spec_int ("users",
316 "Users to present to user",
318 G_PARAM_READABLE));*/
320 * LightDMUserList::user-added:
321 * @user_list: A #LightDMUserList
322 * @user: The #LightDM user that has been added.
324 * The ::user-added signal gets emitted when a user account is created.
326 list_signals[USER_ADDED] =
327 g_signal_new (LIGHTDM_USER_LIST_SIGNAL_USER_ADDED,
328 G_TYPE_FROM_CLASS (klass),
330 G_STRUCT_OFFSET (LightDMUserListClass, user_added),
333 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
336 * LightDMUserList::user-changed:
337 * @user_list: A #LightDMUserList
338 * @user: The #LightDM user that has been changed.
340 * The ::user-changed signal gets emitted when a user account is modified.
342 list_signals[USER_CHANGED] =
343 g_signal_new (LIGHTDM_USER_LIST_SIGNAL_USER_CHANGED,
344 G_TYPE_FROM_CLASS (klass),
346 G_STRUCT_OFFSET (LightDMUserListClass, user_changed),
349 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
352 * LightDMUserList::user-removed:
353 * @user_list: A #LightDMUserList
354 * @user: The #LightDM user that has been removed.
356 * The ::user-removed signal gets emitted when a user account is removed.
358 list_signals[USER_REMOVED] =
359 g_signal_new (LIGHTDM_USER_LIST_SIGNAL_USER_REMOVED,
360 G_TYPE_FROM_CLASS (klass),
362 G_STRUCT_OFFSET (LightDMUserListClass, user_removed),
365 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
369 * lightdm_user_get_name:
370 * @user: A #LightDMUser
372 * Get the name of a user.
374 * Return value: The name of the given user
377 lightdm_user_get_name (LightDMUser *user)
379 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
380 return common_user_get_name (GET_USER_PRIVATE (user)->common_user);
384 * lightdm_user_get_real_name:
385 * @user: A #LightDMUser
387 * Get the real name of a user.
389 * Return value: The real name of the given user
392 lightdm_user_get_real_name (LightDMUser *user)
394 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
395 return common_user_get_real_name (GET_USER_PRIVATE (user)->common_user);
399 * lightdm_user_get_display_name:
400 * @user: A #LightDMUser
402 * Get the display name of a user.
404 * Return value: The display name of the given user
407 lightdm_user_get_display_name (LightDMUser *user)
409 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
410 return common_user_get_display_name (GET_USER_PRIVATE (user)->common_user);
414 * lightdm_user_get_home_directory:
415 * @user: A #LightDMUser
417 * Get the home directory for a user.
419 * Return value: The users home directory
422 lightdm_user_get_home_directory (LightDMUser *user)
424 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
425 return common_user_get_home_directory (GET_USER_PRIVATE (user)->common_user);
429 * lightdm_user_get_image:
430 * @user: A #LightDMUser
432 * Get the image URI for a user.
434 * Return value: (nullable): The image URI for the given user or #NULL if no URI
437 lightdm_user_get_image (LightDMUser *user)
439 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
440 return common_user_get_image (GET_USER_PRIVATE (user)->common_user);
444 * lightdm_user_get_background:
445 * @user: A #LightDMUser
447 * Get the background file path for a user.
449 * Return value: (nullable): The background file path for the given user or #NULL if no path
452 lightdm_user_get_background (LightDMUser *user)
454 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
455 return common_user_get_background (GET_USER_PRIVATE (user)->common_user);
459 * lightdm_user_get_language:
460 * @user: A #LightDMUser
462 * Get the language for a user.
464 * 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.
467 lightdm_user_get_language (LightDMUser *user)
469 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
470 return common_user_get_language (GET_USER_PRIVATE (user)->common_user);
474 * lightdm_user_get_layout:
475 * @user: A #LightDMUser
477 * Get the keyboard layout for a user.
479 * 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.
482 lightdm_user_get_layout (LightDMUser *user)
484 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
485 return common_user_get_layout (GET_USER_PRIVATE (user)->common_user);
489 * lightdm_user_get_layouts:
490 * @user: A #LightDMUser
492 * Get the configured keyboard layouts for a user.
494 * 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.
496 const gchar * const *
497 lightdm_user_get_layouts (LightDMUser *user)
499 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
500 return common_user_get_layouts (GET_USER_PRIVATE (user)->common_user);
504 * lightdm_user_get_session:
505 * @user: A #LightDMUser
507 * Get the session for a user.
509 * Return value: (nullable): The session for the given user or #NULL if using system defaults.
512 lightdm_user_get_session (LightDMUser *user)
514 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
515 return common_user_get_session (GET_USER_PRIVATE (user)->common_user);
519 * lightdm_user_get_logged_in:
520 * @user: A #LightDMUser
522 * Check if a user is logged in.
524 * Return value: #TRUE if the user is currently logged in.
527 lightdm_user_get_logged_in (LightDMUser *user)
529 g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
530 return common_user_get_logged_in (GET_USER_PRIVATE (user)->common_user);
534 * lightdm_user_get_has_messages:
535 * @user: A #LightDMUser
537 * Check if a user has waiting messages.
539 * Return value: #TRUE if the user has waiting messages.
542 lightdm_user_get_has_messages (LightDMUser *user)
544 g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
545 return common_user_get_has_messages (GET_USER_PRIVATE (user)->common_user);
549 * lightdm_user_get_uid:
550 * @user: A #LightDMUser
552 * Get the uid of a user.
554 * Return value: The uid of the given user
557 lightdm_user_get_uid (LightDMUser *user)
559 g_return_val_if_fail (LIGHTDM_IS_USER (user), (uid_t)-1);
560 return common_user_get_uid (GET_USER_PRIVATE (user)->common_user);
564 lightdm_user_init (LightDMUser *user)
569 lightdm_user_set_property (GObject *object,
574 LightDMUser *self = LIGHTDM_USER (object);
575 LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
579 case USER_PROP_COMMON_USER:
580 priv->common_user = g_value_dup_object (value);
583 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
589 lightdm_user_get_property (GObject *object,
596 self = LIGHTDM_USER (object);
601 g_value_set_string (value, lightdm_user_get_name (self));
603 case USER_PROP_REAL_NAME:
604 g_value_set_string (value, lightdm_user_get_real_name (self));
606 case USER_PROP_DISPLAY_NAME:
607 g_value_set_string (value, lightdm_user_get_display_name (self));
609 case USER_PROP_HOME_DIRECTORY:
610 g_value_set_string (value, lightdm_user_get_home_directory (self));
612 case USER_PROP_IMAGE:
613 g_value_set_string (value, lightdm_user_get_image (self));
615 case USER_PROP_BACKGROUND:
616 g_value_set_string (value, lightdm_user_get_background (self));
618 case USER_PROP_LANGUAGE:
619 g_value_set_string (value, lightdm_user_get_language (self));
621 case USER_PROP_LAYOUT:
622 g_value_set_string (value, lightdm_user_get_layout (self));
624 case USER_PROP_LAYOUTS:
625 g_value_set_boxed (value, g_strdupv ((gchar **) lightdm_user_get_layouts (self)));
627 case USER_PROP_SESSION:
628 g_value_set_string (value, lightdm_user_get_session (self));
630 case USER_PROP_LOGGED_IN:
631 g_value_set_boolean (value, lightdm_user_get_logged_in (self));
633 case USER_PROP_HAS_MESSAGES:
634 g_value_set_boolean (value, lightdm_user_get_has_messages (self));
637 g_value_set_uint64 (value, lightdm_user_get_uid (self));
640 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
646 lightdm_user_finalize (GObject *object)
648 LightDMUser *self = LIGHTDM_USER (object);
649 LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
651 g_object_unref (priv->common_user);
653 G_OBJECT_CLASS (lightdm_user_parent_class)->finalize (object);
657 lightdm_user_class_init (LightDMUserClass *klass)
659 GObjectClass *object_class = G_OBJECT_CLASS (klass);
661 g_type_class_add_private (klass, sizeof (LightDMUserPrivate));
663 object_class->set_property = lightdm_user_set_property;
664 object_class->get_property = lightdm_user_get_property;
665 object_class->finalize = lightdm_user_finalize;
667 g_object_class_install_property (object_class,
668 USER_PROP_COMMON_USER,
669 g_param_spec_object ("common-user",
671 "Internal user object",
673 G_PARAM_PRIVATE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_WRITABLE));
674 g_object_class_install_property (object_class,
676 g_param_spec_string ("name",
681 g_object_class_install_property (object_class,
683 g_param_spec_string ("real-name",
688 g_object_class_install_property (object_class,
689 USER_PROP_DISPLAY_NAME,
690 g_param_spec_string ("display-name",
692 "Users display name",
695 g_object_class_install_property (object_class,
696 USER_PROP_HOME_DIRECTORY,
697 g_param_spec_string ("home-directory",
702 g_object_class_install_property (object_class,
704 g_param_spec_string ("image",
709 g_object_class_install_property (object_class,
710 USER_PROP_BACKGROUND,
711 g_param_spec_string ("background",
716 g_object_class_install_property (object_class,
718 g_param_spec_string ("language",
720 "Language used by this user",
723 g_object_class_install_property (object_class,
725 g_param_spec_string ("layout",
727 "Keyboard layout used by this user",
730 g_object_class_install_property (object_class,
732 g_param_spec_boxed ("layouts",
734 "Keyboard layouts used by this user",
737 g_object_class_install_property (object_class,
739 g_param_spec_string ("session",
741 "Session used by this user",
744 g_object_class_install_property (object_class,
746 g_param_spec_boolean ("logged-in",
748 "TRUE if the user is currently in a session",
751 g_object_class_install_property (object_class,
753 g_param_spec_boolean ("has-messages",
755 "TRUE if the user is has waiting messages",
758 g_object_class_install_property (object_class,
760 g_param_spec_uint64 ("uid",
767 * LightDMUser::changed:
768 * @user: A #LightDMUser
770 * The ::changed signal gets emitted this user account is modified.
772 user_signals[CHANGED] =
773 g_signal_new (LIGHTDM_SIGNAL_USER_CHANGED,
774 G_TYPE_FROM_CLASS (klass),
776 G_STRUCT_OFFSET (LightDMUserClass, changed),