Back to index

lightdm  1.3.2
layout.c
Go to the documentation of this file.
00001 /* -*- Mode: C; indent-tabs-mode:nil; tab-width:4 -*-
00002  *
00003  * Copyright (C) 2010 Robert Ancell.
00004  * Author: Robert Ancell <robert.ancell@canonical.com>
00005  * 
00006  * This library is free software; you can redistribute it and/or modify it under
00007  * the terms of the GNU Lesser General Public License as published by the Free
00008  * Software Foundation; either version 3 of the License, or (at your option) any
00009  * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the
00010  * license.
00011  */
00012 
00013 #include <libxklavier/xklavier.h>
00014 
00015 #include "lightdm/layout.h"
00016 
00017 enum {
00018     PROP_0,
00019     PROP_NAME,
00020     PROP_SHORT_DESCRIPTION,
00021     PROP_DESCRIPTION
00022 };
00023 
00024 typedef struct
00025 {
00026     gchar *name;
00027     gchar *short_description;
00028     gchar *description;
00029 } LightDMLayoutPrivate;
00030 
00031 G_DEFINE_TYPE (LightDMLayout, lightdm_layout, G_TYPE_OBJECT);
00032 
00033 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_LAYOUT, LightDMLayoutPrivate)
00034 
00035 static gboolean have_layouts = FALSE;
00036 static Display *display = NULL;
00037 static XklEngine *xkl_engine = NULL;
00038 static XklConfigRec *xkl_config = NULL;
00039 static GList *layouts = NULL;
00040 static LightDMLayout *default_layout = NULL;
00041 
00042 static gchar *
00043 make_layout_string (const gchar *layout, const gchar *variant)
00044 {
00045     if (!layout || layout[0] == 0)
00046         return NULL;
00047     else if (!variant || variant[0] == 0)
00048         return g_strdup (layout);
00049     else
00050         return g_strdup_printf ("%s\t%s", layout, variant);
00051 }
00052 
00053 static void
00054 parse_layout_string (const gchar *name, gchar **layout, gchar **variant)
00055 {
00056     gchar **split;
00057 
00058     *layout = NULL;
00059     *variant = NULL;
00060 
00061     if (!name)
00062         return;
00063 
00064     split = g_strsplit (name, "\t", 2);
00065     if (split[0])
00066     {
00067         *layout = g_strdup (split[0]);
00068         if (split[1])
00069             *variant = g_strdup (split[1]);
00070     }
00071     g_strfreev (split);
00072 }
00073 
00074 static void
00075 variant_cb (XklConfigRegistry *config,
00076            const XklConfigItem *item,
00077            gpointer data)
00078 {
00079     LightDMLayout *layout;
00080     gchar *full_name;
00081 
00082     full_name = make_layout_string (data, item->name);
00083 
00084     layout = g_object_new (LIGHTDM_TYPE_LAYOUT, "name", full_name, "short-description", item->short_description, "description", item->description, NULL);
00085     layouts = g_list_append (layouts, layout);
00086 
00087     g_free (full_name);
00088 }
00089 
00090 static void
00091 layout_cb (XklConfigRegistry *config,
00092            const XklConfigItem *item,
00093            gpointer data)
00094 {
00095     LightDMLayout *layout;
00096 
00097     layout = g_object_new (LIGHTDM_TYPE_LAYOUT, "name", item->name, "short-description", item->short_description, "description", item->description, NULL);
00098     layouts = g_list_append (layouts, layout);
00099 
00100     xkl_config_registry_foreach_layout_variant (config, item->name, variant_cb, (gpointer) item->name);
00101 }
00102 
00110 GList *
00111 lightdm_get_layouts (void)
00112 {
00113     XklConfigRegistry *registry;
00114 
00115     if (have_layouts)
00116         return layouts;
00117 
00118     display = XOpenDisplay (NULL);
00119     xkl_engine = xkl_engine_get_instance (display);
00120     xkl_config = xkl_config_rec_new ();
00121     if (!xkl_config_rec_get_from_server (xkl_config, xkl_engine))
00122         g_warning ("Failed to get Xkl configuration from server");
00123 
00124     registry = xkl_config_registry_get_instance (xkl_engine);
00125     xkl_config_registry_load (registry, FALSE);
00126     xkl_config_registry_foreach_layout (registry, layout_cb, NULL);
00127     g_object_unref (registry);
00128 
00129     have_layouts = TRUE;
00130 
00131     return layouts;
00132 }
00133 
00140 void
00141 lightdm_set_layout (LightDMLayout *dmlayout)
00142 {
00143     XklConfigRec *config;
00144     gchar *layout, *variant;
00145 
00146     g_return_if_fail (dmlayout != NULL);
00147 
00148     g_debug ("Setting keyboard layout to '%s'", lightdm_layout_get_name (dmlayout));
00149 
00150     parse_layout_string (lightdm_layout_get_name (dmlayout), &layout, &variant);
00151 
00152     config = xkl_config_rec_new ();
00153     config->layouts = g_malloc (sizeof (gchar *) * 2);
00154     config->variants = g_malloc (sizeof (gchar *) * 2);
00155     config->model = g_strdup (xkl_config->model);
00156     config->layouts[0] = layout;
00157     config->layouts[1] = NULL;
00158     config->variants[0] = variant;
00159     config->variants[1] = NULL;
00160     if (!xkl_config_rec_activate (config, xkl_engine))
00161         g_warning ("Failed to activate XKL config");
00162     g_object_unref (config);
00163 }
00164 
00172 LightDMLayout *
00173 lightdm_get_layout (void)
00174 {
00175     lightdm_get_layouts ();
00176 
00177     if (layouts && xkl_config && !default_layout)
00178     {
00179         gchar *full_name;
00180         GList *item;
00181 
00182         full_name = make_layout_string (xkl_config->layouts ? xkl_config->layouts[0] : NULL,
00183                                         xkl_config->variants ? xkl_config->variants[0] : NULL);
00184 
00185         for (item = layouts; item; item = item->next)
00186         {
00187             LightDMLayout *iter_layout = (LightDMLayout *) item->data;
00188             if (g_strcmp0 (lightdm_layout_get_name (iter_layout), full_name) == 0)
00189             {
00190                 default_layout = iter_layout;
00191                 break;
00192             }
00193         }
00194 
00195         g_free (full_name);
00196     }
00197 
00198     return default_layout;
00199 }
00200 
00209 const gchar *
00210 lightdm_layout_get_name (LightDMLayout *layout)
00211 {
00212     g_return_val_if_fail (LIGHTDM_IS_LAYOUT (layout), NULL);
00213     return GET_PRIVATE (layout)->name;
00214 }
00215 
00224 const gchar *
00225 lightdm_layout_get_short_description (LightDMLayout *layout)
00226 {
00227     g_return_val_if_fail (LIGHTDM_IS_LAYOUT (layout), NULL);
00228     return GET_PRIVATE (layout)->short_description;
00229 }
00230 
00239 const gchar *
00240 lightdm_layout_get_description (LightDMLayout *layout)
00241 {
00242     g_return_val_if_fail (LIGHTDM_IS_LAYOUT (layout), NULL);
00243     return GET_PRIVATE (layout)->description;
00244 }
00245 
00246 static void
00247 lightdm_layout_init (LightDMLayout *layout)
00248 {
00249 }
00250 
00251 static void
00252 lightdm_layout_set_property (GObject      *object,
00253                          guint         prop_id,
00254                          const GValue *value,
00255                          GParamSpec   *pspec)
00256 {
00257     LightDMLayout *self = LIGHTDM_LAYOUT (object);
00258     LightDMLayoutPrivate *priv = GET_PRIVATE (self);
00259 
00260     switch (prop_id) {
00261     case PROP_NAME:
00262         g_free (priv->name);
00263         priv->name = g_strdup (g_value_get_string (value));
00264         break;
00265     case PROP_SHORT_DESCRIPTION:
00266         g_free (priv->short_description);
00267         priv->short_description = g_strdup (g_value_get_string (value));
00268         break;
00269     case PROP_DESCRIPTION:
00270         g_free (priv->description);
00271         priv->description = g_strdup (g_value_get_string (value));
00272         break;
00273     default:
00274         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
00275         break;
00276     }
00277 }
00278 
00279 static void
00280 lightdm_layout_get_property (GObject    *object,
00281                          guint       prop_id,
00282                          GValue     *value,
00283                          GParamSpec *pspec)
00284 {
00285     LightDMLayout *self;
00286 
00287     self = LIGHTDM_LAYOUT (object);
00288 
00289     switch (prop_id) {
00290     case PROP_NAME:
00291         g_value_set_string (value, lightdm_layout_get_name (self));
00292         break;
00293     case PROP_SHORT_DESCRIPTION:
00294         g_value_set_string (value, lightdm_layout_get_short_description (self));
00295         break;
00296     case PROP_DESCRIPTION:
00297         g_value_set_string (value, lightdm_layout_get_description (self));
00298         break;
00299     default:
00300         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
00301         break;
00302     }
00303 }
00304 
00305 static void
00306 lightdm_layout_class_init (LightDMLayoutClass *klass)
00307 {
00308     GObjectClass *object_class = G_OBJECT_CLASS (klass);
00309   
00310     g_type_class_add_private (klass, sizeof (LightDMLayoutPrivate));
00311 
00312     object_class->set_property = lightdm_layout_set_property;
00313     object_class->get_property = lightdm_layout_get_property;
00314 
00315     g_object_class_install_property (object_class,
00316                                      PROP_NAME,
00317                                      g_param_spec_string ("name",
00318                                                           "name",
00319                                                           "Name of the layout",
00320                                                           NULL,
00321                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
00322     g_object_class_install_property (object_class,
00323                                      PROP_SHORT_DESCRIPTION,
00324                                      g_param_spec_string ("short-description",
00325                                                           "short-description",
00326                                                           "Short description of the layout",
00327                                                           NULL,
00328                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
00329     g_object_class_install_property (object_class,
00330                                      PROP_DESCRIPTION,
00331                                      g_param_spec_string ("description",
00332                                                           "description",
00333                                                           "Long description of the layout",
00334                                                           NULL,
00335                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
00336 }