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
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, "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-added", G_CALLBACK (user_list_added_cb), user_list);
170 g_signal_connect (common_list, "user-changed", G_CALLBACK (user_list_changed_cb), user_list);
171 g_signal_connect (common_list, "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 g_value_set_int (value, lightdm_user_list_get_length (self));
266 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
272 lightdm_user_list_finalize (GObject *object)
274 LightDMUserList *self = LIGHTDM_USER_LIST (object);
275 LightDMUserListPrivate *priv = GET_LIST_PRIVATE (self);
277 g_list_free_full (priv->lightdm_list, g_object_unref);
279 G_OBJECT_CLASS (lightdm_user_list_parent_class)->finalize (object);
283 lightdm_user_list_class_init (LightDMUserListClass *klass)
285 GObjectClass *object_class = G_OBJECT_CLASS (klass);
287 g_type_class_add_private (klass, sizeof (LightDMUserListPrivate));
289 object_class->set_property = lightdm_user_list_set_property;
290 object_class->get_property = lightdm_user_list_get_property;
291 object_class->finalize = lightdm_user_list_finalize;
293 g_object_class_install_property (object_class,
295 g_param_spec_int ("num-users",
297 "Number of login users",
301 * LightDMUserList::user-added:
302 * @user_list: A #LightDMUserList
303 * @user: The #LightDM user that has been added.
305 * The ::user-added signal gets emitted when a user account is created.
307 list_signals[USER_ADDED] =
308 g_signal_new ("user-added",
309 G_TYPE_FROM_CLASS (klass),
311 G_STRUCT_OFFSET (LightDMUserListClass, user_added),
314 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
317 * LightDMUserList::user-changed:
318 * @user_list: A #LightDMUserList
319 * @user: The #LightDM user that has been changed.
321 * The ::user-changed signal gets emitted when a user account is modified.
323 list_signals[USER_CHANGED] =
324 g_signal_new ("user-changed",
325 G_TYPE_FROM_CLASS (klass),
327 G_STRUCT_OFFSET (LightDMUserListClass, user_changed),
330 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
333 * LightDMUserList::user-removed:
334 * @user_list: A #LightDMUserList
335 * @user: The #LightDM user that has been removed.
337 * The ::user-removed signal gets emitted when a user account is removed.
339 list_signals[USER_REMOVED] =
340 g_signal_new ("user-removed",
341 G_TYPE_FROM_CLASS (klass),
343 G_STRUCT_OFFSET (LightDMUserListClass, user_removed),
346 G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
350 * lightdm_user_get_name:
351 * @user: A #LightDMUser
353 * Get the name of a user.
355 * Return value: The name of the given user
358 lightdm_user_get_name (LightDMUser *user)
360 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
361 return common_user_get_name (GET_USER_PRIVATE (user)->common_user);
365 * lightdm_user_get_real_name:
366 * @user: A #LightDMUser
368 * Get the real name of a user.
370 * Return value: The real name of the given user
373 lightdm_user_get_real_name (LightDMUser *user)
375 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
376 return common_user_get_real_name (GET_USER_PRIVATE (user)->common_user);
380 * lightdm_user_get_display_name:
381 * @user: A #LightDMUser
383 * Get the display name of a user.
385 * Return value: The display name of the given user
388 lightdm_user_get_display_name (LightDMUser *user)
390 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
391 return common_user_get_display_name (GET_USER_PRIVATE (user)->common_user);
395 * lightdm_user_get_home_directory:
396 * @user: A #LightDMUser
398 * Get the home directory for a user.
400 * Return value: The users home directory
403 lightdm_user_get_home_directory (LightDMUser *user)
405 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
406 return common_user_get_home_directory (GET_USER_PRIVATE (user)->common_user);
410 * lightdm_user_get_image:
411 * @user: A #LightDMUser
413 * Get the image URI for a user.
415 * Return value: The image URI for the given user or #NULL if no URI
418 lightdm_user_get_image (LightDMUser *user)
420 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
421 return common_user_get_image (GET_USER_PRIVATE (user)->common_user);
425 * lightdm_user_get_background:
426 * @user: A #LightDMUser
428 * Get the background file path for a user.
430 * Return value: The background file path for the given user or #NULL if no path
433 lightdm_user_get_background (LightDMUser *user)
435 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
436 return common_user_get_background (GET_USER_PRIVATE (user)->common_user);
440 * lightdm_user_get_language:
441 * @user: A #LightDMUser
443 * Get the language for a user.
445 * 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.
448 lightdm_user_get_language (LightDMUser *user)
450 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
451 return common_user_get_language (GET_USER_PRIVATE (user)->common_user);
455 * lightdm_user_get_layout:
456 * @user: A #LightDMUser
458 * Get the keyboard layout for a user.
460 * 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.
463 lightdm_user_get_layout (LightDMUser *user)
465 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
466 return common_user_get_layout (GET_USER_PRIVATE (user)->common_user);
470 * lightdm_user_get_layouts:
471 * @user: A #LightDMUser
473 * Get the configured keyboard layouts for a user.
475 * 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 const gchar * const *
478 lightdm_user_get_layouts (LightDMUser *user)
480 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
481 return common_user_get_layouts (GET_USER_PRIVATE (user)->common_user);
485 * lightdm_user_get_session:
486 * @user: A #LightDMUser
488 * Get the session for a user.
490 * Return value: The session for the given user or #NULL if using system defaults.
493 lightdm_user_get_session (LightDMUser *user)
495 g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
496 return common_user_get_session (GET_USER_PRIVATE (user)->common_user);
500 * lightdm_user_get_logged_in:
501 * @user: A #LightDMUser
503 * Check if a user is logged in.
505 * Return value: #TRUE if the user is currently logged in.
508 lightdm_user_get_logged_in (LightDMUser *user)
510 g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
511 return common_user_get_logged_in (GET_USER_PRIVATE (user)->common_user);
515 * lightdm_user_get_has_messages:
516 * @user: A #LightDMUser
518 * Check if a user has waiting messages.
520 * Return value: #TRUE if the user has waiting messages.
523 lightdm_user_get_has_messages (LightDMUser *user)
525 g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
526 return common_user_get_has_messages (GET_USER_PRIVATE (user)->common_user);
530 lightdm_user_init (LightDMUser *user)
535 lightdm_user_set_property (GObject *object,
540 LightDMUser *self = LIGHTDM_USER (object);
541 LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
545 case USER_PROP_COMMON_USER:
546 priv->common_user = g_value_dup_object (value);
549 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
555 lightdm_user_get_property (GObject *object,
562 self = LIGHTDM_USER (object);
567 g_value_set_string (value, lightdm_user_get_name (self));
569 case USER_PROP_REAL_NAME:
570 g_value_set_string (value, lightdm_user_get_real_name (self));
572 case USER_PROP_DISPLAY_NAME:
573 g_value_set_string (value, lightdm_user_get_display_name (self));
575 case USER_PROP_HOME_DIRECTORY:
576 g_value_set_string (value, lightdm_user_get_home_directory (self));
578 case USER_PROP_IMAGE:
579 g_value_set_string (value, lightdm_user_get_image (self));
581 case USER_PROP_BACKGROUND:
582 g_value_set_string (value, lightdm_user_get_background (self));
584 case USER_PROP_LANGUAGE:
585 g_value_set_string (value, lightdm_user_get_language (self));
587 case USER_PROP_LAYOUT:
588 g_value_set_string (value, lightdm_user_get_layout (self));
590 case USER_PROP_LAYOUTS:
591 g_value_set_boxed (value, g_strdupv ((gchar **) lightdm_user_get_layouts (self)));
593 case USER_PROP_SESSION:
594 g_value_set_string (value, lightdm_user_get_session (self));
596 case USER_PROP_LOGGED_IN:
597 g_value_set_boolean (value, lightdm_user_get_logged_in (self));
599 case USER_PROP_HAS_MESSAGES:
600 g_value_set_boolean (value, lightdm_user_get_has_messages (self));
603 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
609 lightdm_user_finalize (GObject *object)
611 LightDMUser *self = LIGHTDM_USER (object);
612 LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
614 g_object_unref (priv->common_user);
616 G_OBJECT_CLASS (lightdm_user_parent_class)->finalize (object);
620 lightdm_user_class_init (LightDMUserClass *klass)
622 GObjectClass *object_class = G_OBJECT_CLASS (klass);
624 g_type_class_add_private (klass, sizeof (LightDMUserPrivate));
626 object_class->set_property = lightdm_user_set_property;
627 object_class->get_property = lightdm_user_get_property;
628 object_class->finalize = lightdm_user_finalize;
630 g_object_class_install_property (object_class,
631 USER_PROP_COMMON_USER,
632 g_param_spec_object ("common-user",
634 "Internal user object",
636 G_PARAM_PRIVATE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_WRITABLE));
637 g_object_class_install_property (object_class,
639 g_param_spec_string ("name",
644 g_object_class_install_property (object_class,
646 g_param_spec_string ("real-name",
651 g_object_class_install_property (object_class,
652 USER_PROP_DISPLAY_NAME,
653 g_param_spec_string ("display-name",
655 "Users display name",
658 g_object_class_install_property (object_class,
659 USER_PROP_HOME_DIRECTORY,
660 g_param_spec_string ("home-directory",
665 g_object_class_install_property (object_class,
667 g_param_spec_string ("image",
672 g_object_class_install_property (object_class,
673 USER_PROP_BACKGROUND,
674 g_param_spec_string ("background",
679 g_object_class_install_property (object_class,
681 g_param_spec_string ("language",
683 "Language used by this user",
686 g_object_class_install_property (object_class,
688 g_param_spec_string ("layout",
690 "Keyboard layout used by this user",
693 g_object_class_install_property (object_class,
695 g_param_spec_boxed ("layouts",
697 "Keyboard layouts used by this user",
700 g_object_class_install_property (object_class,
702 g_param_spec_string ("session",
704 "Session used by this user",
707 g_object_class_install_property (object_class,
709 g_param_spec_boolean ("logged-in",
711 "TRUE if the user is currently in a session",
714 g_object_class_install_property (object_class,
716 g_param_spec_boolean ("has-messages",
718 "TRUE if the user is has waiting messages",
723 * LightDMUser::changed:
724 * @user: A #LightDMUser
726 * The ::changed signal gets emitted this user account is modified.
728 user_signals[CHANGED] =
729 g_signal_new ("changed",
730 G_TYPE_FROM_CLASS (klass),
732 G_STRUCT_OFFSET (LightDMUserClass, changed),