From cb65e5bab2c9357aefbec38bb92a8ba2ead97143 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Wed, 3 Apr 2013 14:31:29 -0400 Subject: [PATCH] Add KeyboardLayouts property --- data/org.freedesktop.Accounts.User.xml | 45 +++++++++++++++++ src/libaccountsservice/act-user.c | 89 ++++++++++++++++++++++++++++++++++ src/user.c | 67 +++++++++++++++++++++++++ 3 files changed, 201 insertions(+) diff --git a/data/org.freedesktop.Accounts.User.xml b/data/org.freedesktop.Accounts.User.xml index 88198d8..2fcd1bc 100644 --- a/data/org.freedesktop.Accounts.User.xml +++ b/data/org.freedesktop.Accounts.User.xml @@ -533,6 +533,41 @@ + + + + + + The name of the keyboard layouts to use as the user's keyboard layout. The first is the default. + + + + + + + Sets the user's keyboard layouts. + + + + The caller needs one of the following PolicyKit authorizations: + + + org.freedesktop.accounts.change-own-user-data + To change his or her own keyboard layouts + + + org.freedesktop.accounts.user-administration + To change the keyboard layouts of another user + + + + + if the caller lacks the appropriate PolicyKit authorization + if the operation failed + + + + @@ -776,5 +811,15 @@ + + + + + The names of the user's keyboard layouts. + + + + + diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c index 1ad80f9..b938089 100644 --- a/src/libaccountsservice/act-user.c +++ b/src/libaccountsservice/act-user.c @@ -69,6 +69,7 @@ enum { PROP_LOGIN_HISTORY, PROP_ICON_FILE, PROP_LANGUAGE, + PROP_KEYBOARD_LAYOUTS, PROP_X_SESSION, PROP_IS_LOADED }; @@ -98,6 +99,7 @@ struct _ActUser { char *location; char *icon_file; char *language; + char **keyboard_layouts; char *x_session; GList *sessions; int login_frequency; @@ -241,6 +243,9 @@ act_user_get_property (GObject *object, case PROP_LANGUAGE: g_value_set_string (value, user->language); break; + case PROP_KEYBOARD_LAYOUTS: + g_value_set_boxed (value, g_strdupv (user->keyboard_layouts)); + break; case PROP_X_SESSION: g_value_set_string (value, user->x_session); break; @@ -394,6 +399,13 @@ act_user_class_init (ActUserClass *class) NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, + PROP_KEYBOARD_LAYOUTS, + g_param_spec_boxed ("keyboard-layouts", + "Keyboard layouts", + "The name of keyboard layouts for this user.", + G_TYPE_STRV, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, PROP_X_SESSION, g_param_spec_string ("x-session", "X session", @@ -487,6 +499,7 @@ act_user_finalize (GObject *object) g_free (user->real_name); g_free (user->icon_file); g_free (user->language); + g_strfreev (user->keyboard_layouts); g_free (user->object_path); g_free (user->password_hint); g_free (user->home_dir); @@ -919,6 +932,22 @@ act_user_get_language (ActUser *user) } /** + * act_user_get_keyboard_layouts: + * @user: a #ActUser + * + * Returns the name of the account keyboard layouts belonging to @user. + * + * Returns: (transfer none): names of keyboard layouts + */ +const char * const * +act_user_get_keyboard_layouts (ActUser *user) +{ + g_return_val_if_fail (ACT_IS_USER (user), NULL); + + return (const char * const *) user->keyboard_layouts; +} + +/** * act_user_get_x_session: * @user: a #ActUser * @@ -974,6 +1003,28 @@ act_user_get_primary_session_id (ActUser *user) return user->sessions->data; } +static gboolean +strv_equal (const char **a, const char **b) +{ + gint i; + gboolean same = TRUE; + + if (a == b) + return TRUE; + else if (a == NULL || b == NULL) + return FALSE; + + for (i = 0; a[i]; i++) { + if (g_strcmp0 (a[i], b[i]) != 0) + return FALSE; + } + + if (g_strcmp0 (a[i], b[i]) != 0) + return FALSE; + + return TRUE; +} + static void collect_props (const gchar *key, GVariant *value, @@ -1144,6 +1195,15 @@ collect_props (const gchar *key, user->language = g_strdup (new_language); g_object_notify (G_OBJECT (user), "language"); } + } else if (strcmp (key, "KeyboardLayouts") == 0) { + const char **new_keyboard_layouts; + + new_keyboard_layouts = g_variant_get_strv (value, NULL); + if (!strv_equal ((const gchar **)user->keyboard_layouts, new_keyboard_layouts)) { + g_strfreev (user->keyboard_layouts); + user->keyboard_layouts = g_strdupv ((gchar **)new_keyboard_layouts); + g_object_notify (G_OBJECT (user), "keyboard-layouts"); + } } else if (strcmp (key, "XSession") == 0) { const char *new_x_session; @@ -1530,6 +1590,35 @@ act_user_set_location (ActUser *user, } /** + * act_user_set_keyboard_layouts: + * @user: the user object to alter. + * @keyboard_layouts: names of keyboard layouts + * + * Assigns a new set of keyboard layouts for @user. + * + * Note this function is synchronous and ignores errors. + **/ +void +act_user_set_keyboard_layouts (ActUser *user, + const char * const *keyboard_layouts) +{ + GError *error = NULL; + + g_return_if_fail (ACT_IS_USER (user)); + g_return_if_fail (keyboard_layouts != NULL); + g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy)); + + if (!accounts_user_call_set_keyboard_layouts_sync (user->accounts_proxy, + keyboard_layouts, + NULL, + &error)) { + g_warning ("SetKeyboardLayouts call failed: %s", error->message); + g_error_free (error); + return; + } +} + +/** * act_user_set_user_name: * @user: the user object to alter. * @user_name: a new user name diff --git a/src/user.c b/src/user.c index bf5939c..f8fdefb 100644 --- a/src/user.c +++ b/src/user.c @@ -56,6 +56,7 @@ enum { PROP_SHELL, PROP_EMAIL, PROP_LANGUAGE, + PROP_KEYBOARD_LAYOUTS, PROP_X_SESSION, PROP_LOCATION, PROP_LOGIN_FREQUENCY, @@ -89,6 +90,7 @@ struct User { gchar *shell; gchar *email; gchar *language; + gchar **keyboard_layouts; gchar *x_session; gchar *location; guint64 login_frequency; @@ -301,6 +303,7 @@ user_update_from_keyfile (User *user, GKeyFile *keyfile) { gchar *s; + gchar **slist; g_object_freeze_notify (G_OBJECT (user)); @@ -312,6 +315,12 @@ user_update_from_keyfile (User *user, g_object_notify (G_OBJECT (user), "language"); } + slist = g_key_file_get_string_list (keyfile, "User", "KeyboardLayouts", NULL, NULL); + if (slist != NULL) { + g_strfreev (user->keyboard_layouts); + user->keyboard_layouts = slist; + } + s = g_key_file_get_string (keyfile, "User", "XSession", NULL); if (s != NULL) { g_free (user->x_session); @@ -370,6 +379,9 @@ user_save_to_keyfile (User *user, if (user->language) g_key_file_set_string (keyfile, "User", "Language", user->language); + if (user->keyboard_layouts) + g_key_file_set_string_list (keyfile, "User", "KeyboardLayouts", (const gchar * const *) user->keyboard_layouts, g_strv_length (user->keyboard_layouts)); + if (user->x_session) g_key_file_set_string (keyfile, "User", "XSession", user->x_session); @@ -790,6 +802,55 @@ user_set_language (AccountsUser *auser, } static void +user_change_keyboard_layouts_authorized_cb (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data) +{ + g_strfreev (user->keyboard_layouts); + user->keyboard_layouts = g_strdupv (data); + + save_extra_data (user); + + accounts_user_emit_changed (ACCOUNTS_USER (user)); + + g_object_notify (G_OBJECT (user), "keyboard-layouts"); + + accounts_user_complete_set_keyboard_layouts (ACCOUNTS_USER (user), context); +} + +static gboolean +user_set_keyboard_layouts (AccountsUser *auser, + GDBusMethodInvocation *context, + const gchar * const *layouts) +{ + User *user = (User*)auser; + int uid; + const gchar *action_id; + + if (!get_caller_uid (context, &uid)) { + throw_error (context, ERROR_FAILED, "identifying caller failed"); + return FALSE; + } + + if (user->uid == (uid_t) uid) + action_id = "org.freedesktop.accounts.change-own-user-data"; + else + action_id = "org.freedesktop.accounts.user-administration"; + + daemon_local_check_auth (user->daemon, + user, + action_id, + TRUE, + user_change_keyboard_layouts_authorized_cb, + context, + g_strdupv ((gchar **)layouts), + (GDestroyNotify)g_strfreev); + + return TRUE; +} + +static void user_change_x_session_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, @@ -1761,6 +1822,7 @@ user_finalize (GObject *object) g_free (user->default_icon_file); g_free (user->email); g_free (user->language); + g_strfreev (user->keyboard_layouts); g_free (user->x_session); g_free (user->location); g_free (user->password_hint); @@ -1850,6 +1912,9 @@ user_get_property (GObject *object, case PROP_LANGUAGE: g_value_set_string (value, user->language); break; + case PROP_KEYBOARD_LAYOUTS: + g_value_set_boxed (value, g_strdupv (user->keyboard_layouts)); + break; case PROP_X_SESSION: g_value_set_string (value, user->x_session); break; @@ -1923,6 +1988,7 @@ user_accounts_user_iface_init (AccountsUserIface *iface) iface->handle_set_real_name = user_set_real_name; iface->handle_set_shell = user_set_shell; iface->handle_set_user_name = user_set_user_name; + iface->handle_set_keyboard_layouts = user_set_keyboard_layouts; iface->handle_set_xsession = user_set_x_session; iface->get_uid = user_real_get_uid; iface->get_user_name = user_real_get_user_name; @@ -1959,6 +2025,7 @@ user_init (User *user) user->default_icon_file = NULL; user->email = NULL; user->language = NULL; + user->keyboard_layouts = NULL; user->x_session = NULL; user->location = NULL; user->password_mode = PASSWORD_MODE_REGULAR; -- 1.8.1.2