1 /* -*- Mode: C; indent-tabs-mode:nil; tab-width:4 -*-
3 * Copyright (C) 2010 Robert Ancell.
4 * Author: Robert Ancell <robert.ancell@canonical.com>
6 * This library is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by the Free
8 * Software Foundation; either version 3 of the License, or (at your option) any
9 * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the
13 #include <libxklavier/xklavier.h>
15 #include "lightdm/layout.h"
20 PROP_SHORT_DESCRIPTION,
27 gchar *short_description;
29 } LightDMLayoutPrivate;
31 G_DEFINE_TYPE (LightDMLayout, lightdm_layout, G_TYPE_OBJECT);
33 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_LAYOUT, LightDMLayoutPrivate)
35 static gboolean have_layouts = FALSE;
36 static Display *display = NULL;
37 static XklEngine *xkl_engine = NULL;
38 static XklConfigRec *xkl_config = NULL;
39 static GList *layouts = NULL;
40 static LightDMLayout *default_layout = NULL;
43 make_layout_string (const gchar *layout, const gchar *variant)
45 if (!layout || layout[0] == 0)
47 else if (!variant || variant[0] == 0)
48 return g_strdup (layout);
50 return g_strdup_printf ("%s\t%s", layout, variant);
54 parse_layout_string (const gchar *name, gchar **layout, gchar **variant)
64 split = g_strsplit (name, "\t", 2);
67 *layout = g_strdup (split[0]);
69 *variant = g_strdup (split[1]);
75 variant_cb (XklConfigRegistry *config,
76 const XklConfigItem *item,
79 LightDMLayout *layout;
82 full_name = make_layout_string (data, item->name);
84 layout = g_object_new (LIGHTDM_TYPE_LAYOUT, "name", full_name, "short-description", item->short_description, "description", item->description, NULL);
85 layouts = g_list_append (layouts, layout);
91 layout_cb (XklConfigRegistry *config,
92 const XklConfigItem *item,
95 LightDMLayout *layout;
97 layout = g_object_new (LIGHTDM_TYPE_LAYOUT, "name", item->name, "short-description", item->short_description, "description", item->description, NULL);
98 layouts = g_list_append (layouts, layout);
100 xkl_config_registry_foreach_layout_variant (config, item->name, variant_cb, (gpointer) item->name);
104 * lightdm_get_layouts:
106 * Get a list of keyboard layouts to present to the user.
108 * Return value: (element-type LightDMLayout) (transfer none): A list of #LightDMLayout that should be presented to the user.
111 lightdm_get_layouts (void)
113 XklConfigRegistry *registry;
118 display = XOpenDisplay (NULL);
119 xkl_engine = xkl_engine_get_instance (display);
120 xkl_config = xkl_config_rec_new ();
121 if (!xkl_config_rec_get_from_server (xkl_config, xkl_engine))
122 g_warning ("Failed to get Xkl configuration from server");
124 registry = xkl_config_registry_get_instance (xkl_engine);
125 xkl_config_registry_load (registry, FALSE);
126 xkl_config_registry_foreach_layout (registry, layout_cb, NULL);
127 g_object_unref (registry);
135 * lightdm_set_layout:
136 * @layout: The layout to use
138 * Set the layout for this session.
141 lightdm_set_layout (LightDMLayout *dmlayout)
143 XklConfigRec *config;
144 gchar *layout, *variant;
146 g_return_if_fail (dmlayout != NULL);
148 g_debug ("Setting keyboard layout to '%s'", lightdm_layout_get_name (dmlayout));
150 parse_layout_string (lightdm_layout_get_name (dmlayout), &layout, &variant);
152 config = xkl_config_rec_new ();
153 config->layouts = g_malloc (sizeof (gchar *) * 2);
154 config->variants = g_malloc (sizeof (gchar *) * 2);
155 config->model = g_strdup (xkl_config->model);
156 config->layouts[0] = layout;
157 config->layouts[1] = NULL;
158 config->variants[0] = variant;
159 config->variants[1] = NULL;
160 if (!xkl_config_rec_activate (config, xkl_engine))
161 g_warning ("Failed to activate XKL config");
162 g_object_unref (config);
166 * lightdm_get_layout:
168 * Get the current keyboard layout.
170 * Return value: (transfer none): The currently active layout for this user.
173 lightdm_get_layout (void)
175 lightdm_get_layouts ();
177 if (layouts && xkl_config && !default_layout)
182 full_name = make_layout_string (xkl_config->layouts ? xkl_config->layouts[0] : NULL,
183 xkl_config->variants ? xkl_config->variants[0] : NULL);
185 for (item = layouts; item; item = item->next)
187 LightDMLayout *iter_layout = (LightDMLayout *) item->data;
188 if (g_strcmp0 (lightdm_layout_get_name (iter_layout), full_name) == 0)
190 default_layout = iter_layout;
198 return default_layout;
202 * lightdm_layout_get_name:
203 * @layout: A #LightDMLayout
205 * Get the name of a layout.
207 * Return value: The name of the layout
210 lightdm_layout_get_name (LightDMLayout *layout)
212 g_return_val_if_fail (LIGHTDM_IS_LAYOUT (layout), NULL);
213 return GET_PRIVATE (layout)->name;
217 * lightdm_layout_get_short_description:
218 * @layout: A #LightDMLayout
220 * Get the short description of a layout.
222 * Return value: A short description of the layout
225 lightdm_layout_get_short_description (LightDMLayout *layout)
227 g_return_val_if_fail (LIGHTDM_IS_LAYOUT (layout), NULL);
228 return GET_PRIVATE (layout)->short_description;
232 * lightdm_layout_get_description:
233 * @layout: A #LightDMLayout
235 * Get the long description of a layout.
237 * Return value: A long description of the layout
240 lightdm_layout_get_description (LightDMLayout *layout)
242 g_return_val_if_fail (LIGHTDM_IS_LAYOUT (layout), NULL);
243 return GET_PRIVATE (layout)->description;
247 lightdm_layout_init (LightDMLayout *layout)
252 lightdm_layout_set_property (GObject *object,
257 LightDMLayout *self = LIGHTDM_LAYOUT (object);
258 LightDMLayoutPrivate *priv = GET_PRIVATE (self);
263 priv->name = g_strdup (g_value_get_string (value));
265 case PROP_SHORT_DESCRIPTION:
266 g_free (priv->short_description);
267 priv->short_description = g_strdup (g_value_get_string (value));
269 case PROP_DESCRIPTION:
270 g_free (priv->description);
271 priv->description = g_strdup (g_value_get_string (value));
274 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
280 lightdm_layout_get_property (GObject *object,
287 self = LIGHTDM_LAYOUT (object);
291 g_value_set_string (value, lightdm_layout_get_name (self));
293 case PROP_SHORT_DESCRIPTION:
294 g_value_set_string (value, lightdm_layout_get_short_description (self));
296 case PROP_DESCRIPTION:
297 g_value_set_string (value, lightdm_layout_get_description (self));
300 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
306 lightdm_layout_class_init (LightDMLayoutClass *klass)
308 GObjectClass *object_class = G_OBJECT_CLASS (klass);
310 g_type_class_add_private (klass, sizeof (LightDMLayoutPrivate));
312 object_class->set_property = lightdm_layout_set_property;
313 object_class->get_property = lightdm_layout_get_property;
315 g_object_class_install_property (object_class,
317 g_param_spec_string ("name",
319 "Name of the layout",
321 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
322 g_object_class_install_property (object_class,
323 PROP_SHORT_DESCRIPTION,
324 g_param_spec_string ("short-description",
326 "Short description of the layout",
328 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
329 g_object_class_install_property (object_class,
331 g_param_spec_string ("description",
333 "Long description of the layout",
335 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));