Logo Search packages:      
Sourcecode: gdm3 version File versions  Download package

gdm-layouts.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 *
 * Copyright 2008  Red Hat, Inc,
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Written by : Matthias Clasen
 */

#include "config.h"

#include <string.h>

#include <glib.h>

#include <gdk/gdkx.h>

#ifdef HAVE_LIBXKLAVIER
#include <libxklavier/xklavier.h>
#endif

#include <gconf/gconf-client.h>

#include "gdm-layouts.h"

typedef struct {
        GSList *list;
        const char *layout;
} LayoutData;

#ifdef HAVE_LIBXKLAVIER
static XklEngine         *engine = NULL;
static XklConfigRegistry *config_registry = NULL;
static XklConfigRec      *initial_config = NULL;

static void
init_xkl (void)
{
        if (config_registry == NULL) {
                engine = xkl_engine_get_instance (GDK_DISPLAY ());
                config_registry = xkl_config_registry_get_instance (engine);
                xkl_config_registry_load (config_registry, FALSE);

                initial_config = xkl_config_rec_new ();
                if (!xkl_config_rec_get_from_server (initial_config, engine)) {
                        g_warning ("failed to load XKB configuration");
                        initial_config->model = g_strdup ("pc105");
                }
        }
}

static char *
xci_desc_to_utf8 (XklConfigItem * ci)
{
        char *sd = g_strstrip (ci->description);
        return sd[0] == 0 ? g_strdup (ci->name) :
                g_locale_to_utf8 (sd, -1, NULL, NULL, NULL);
}

static void
add_variant (XklConfigRegistry   *config,
             const XklConfigItem *item,
             gpointer             data)
{
        LayoutData *ldata = data;

        ldata->list = g_slist_prepend (ldata->list, g_strdup_printf  ("%s\t%s", ldata->layout, item->name));
}

static void
add_layout (XklConfigRegistry   *config,
            const XklConfigItem *item,
            gpointer             data)
{
        LayoutData *ldata = data;

        ldata->layout = item->name;
        ldata->list = g_slist_prepend (ldata->list, g_strdup (item->name));
        xkl_config_registry_foreach_layout_variant (config, item->name, add_variant, data);
        ldata->layout = NULL;
}
#endif

gchar *
gdm_get_layout_from_name (const char *name)
{
#ifdef HAVE_LIBXKLAVIER
        XklConfigItem *item;
        char          *layout;
        char          *variant;
        char          *result;
        char          *id1;
        char          *id2;
        char          *p;

        init_xkl ();

        id1 = g_strdup (name);
        p = strchr (id1, '\t');

        if (p != NULL) {
                id2 = p + 1;
                *p = 0;
        } else {
                id2 = NULL;
        }

        item = xkl_config_item_new ();

        g_snprintf (item->name, XKL_MAX_CI_NAME_LENGTH, "%s", id1);
        if (xkl_config_registry_find_layout (config_registry, item)) {
                layout = xci_desc_to_utf8 (item);
        } else {
                layout =  g_strdup_printf ("Layout %s", id1);
        }

        if (id2 != NULL) {
                g_snprintf (item->name, XKL_MAX_CI_NAME_LENGTH, "%s", id2);
                if (xkl_config_registry_find_variant (config_registry, id1, item))
                        variant = xci_desc_to_utf8 (item);
                else
                        variant = g_strdup_printf ("Variant %s", id2);
        } else {
                variant = NULL;
        }

        g_object_unref (item);

        g_free (id1);

        if (variant != NULL) {
                result = g_strdup_printf ("%s (%s)", layout, variant);
                g_free (layout);
                g_free (variant);
        } else {
                result = layout;
        }

        return result;
#else
        return NULL;
#endif
}

char **
gdm_get_all_layout_names (void)
{
#ifdef HAVE_LIBXKLAVIER
        GSList    *l;
        int        len;
        int        i;
        char     **layouts;
        LayoutData data;

        data.list = NULL;
        data.layout = NULL;

        init_xkl ();

        xkl_config_registry_foreach_layout (config_registry, add_layout, &data);

        len = g_slist_length (data.list);

        layouts = g_new (char *, len + 1);
        layouts[len] = NULL;

        for (i = 0, l = data.list; i < len; i++, l = l->next) {
                layouts[len - i - 1] = l->data;
        }

        g_slist_free (data.list);

        return layouts;
#else
        return NULL;
#endif
}

gboolean
gdm_layout_is_valid (const char *layout_variant)
{
#ifdef HAVE_LIBXKLAVIER
        XklConfigItem *item;
        char          *layout;
        char          *variant;
        gboolean       retval;

        layout = g_strdup (layout_variant);
        variant = strchr (layout, '\t');
        if (variant != NULL) {
                variant[0] = '\0';
                variant++;
        }

        item = xkl_config_item_new ();
        g_snprintf (item->name, XKL_MAX_CI_NAME_LENGTH, "%s", layout);

        retval = xkl_config_registry_find_layout (config_registry, item);

        if (retval && variant != NULL) {
                g_snprintf (item->name, XKL_MAX_CI_NAME_LENGTH, "%s", variant);
                retval = xkl_config_registry_find_variant (config_registry, layout, item);
        }

        g_object_unref (item);
        g_free (layout);

        return retval;
#else
        return TRUE;
#endif
}

const char *
gdm_layout_get_default_layout (void)
{
#ifdef HAVE_LIBXKLAVIER
        init_xkl ();

        if (initial_config->layouts)
                return initial_config->layouts[0];
        else
                return NULL;
#else
        return NULL;
#endif
}

void
gdm_layout_activate (const char *layout)
{
#ifdef HAVE_LIBXKLAVIER
        XklConfigRec *config;
        char         *p;

        init_xkl ();

        config = xkl_config_rec_new ();
        config->model = g_strdup (initial_config->model);

        if (layout == NULL) {
                config->layouts = g_strdupv (initial_config->layouts);
                config->variants = g_strdupv (initial_config->variants);
                config->options = g_strdupv (initial_config->options);
        } else {
                config->layouts = g_new0 (char *, 2);
                config->layouts[0] = g_strdup (layout);

                p = strchr (config->layouts[0], '\t');
                if (p != NULL) {
                        config->variants = g_new0 (char *, 2);
                        config->layouts[0][p - config->layouts[0]] = 0;
                        config->variants[0] = g_strdup (p + 1);
                }
        }

        xkl_config_rec_activate (config, engine);

        g_object_unref (config);
#endif
}


Generated by  Doxygen 1.6.0   Back to index