- use G_DECLARE_ and G_DEFINE_ macros - move all data into ClassNamePrivate - use _get_instance_private() This should not introduce any functional changes or breakage. Skipped two classes (EekKeyboard and EekboardContextService) for now in order not to break the build. These two classes are used in some very funky WIP code that tries to circumvent encapsulation. (Funky code is in eekboard/key-emitter.c and eekboard/eekboard-context-service.c)
		
			
				
	
	
		
			663 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			663 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 
 | 
						|
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
						|
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
						|
 * 
 | 
						|
 * This library is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU Lesser General Public License
 | 
						|
 * as published by the Free Software Foundation; either version 2 of
 | 
						|
 * the License, or (at your option) any later version.
 | 
						|
 * 
 | 
						|
 * This library 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
 | 
						|
 * Lesser General Public License for more details.
 | 
						|
 * 
 | 
						|
 * You should have received a copy of the GNU Lesser General Public
 | 
						|
 * License along with this library; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
 * 02110-1301 USA
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * SECTION:eek-xkl-layout
 | 
						|
 * @short_description: Layout engine using Libxklavier configuration
 | 
						|
 *
 | 
						|
 * The #EekXklLayout is a simple wrapper around #EekXkbLayout class
 | 
						|
 * to use Libxklavier configuration.
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_CONFIG_H
 | 
						|
#include "config.h"
 | 
						|
#endif  /* HAVE_CONFIG_H */
 | 
						|
 | 
						|
#include <libxklavier/xklavier.h>
 | 
						|
#include <gio/gio.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include "eek-xkl-layout.h"
 | 
						|
 | 
						|
#define noKBDRAW_DEBUG
 | 
						|
 | 
						|
static GInitableIface *parent_initable_iface;
 | 
						|
 | 
						|
static void initable_iface_init (GInitableIface *initable_iface);
 | 
						|
 | 
						|
enum {
 | 
						|
    PROP_0,
 | 
						|
    PROP_MODEL,
 | 
						|
    PROP_LAYOUTS,
 | 
						|
    PROP_VARIANTS,
 | 
						|
    PROP_OPTIONS,
 | 
						|
    PROP_LAST
 | 
						|
};
 | 
						|
 | 
						|
typedef struct _EekXklLayoutPrivate
 | 
						|
{
 | 
						|
    XklEngine *engine;
 | 
						|
    XklConfigRec *config;
 | 
						|
} EekXklLayoutPrivate;
 | 
						|
 | 
						|
G_DEFINE_TYPE_EXTENDED (EekXklLayout, eek_xkl_layout, EEK_TYPE_XKB_LAYOUT,
 | 
						|
			0, /* GTypeFlags */
 | 
						|
			G_ADD_PRIVATE (EekXklLayout)
 | 
						|
                        G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
 | 
						|
                                               initable_iface_init))
 | 
						|
 | 
						|
/* from gnome-keyboard-properties-xkbpv.c:
 | 
						|
 *  BAD STYLE: Taken from xklavier_private_xkb.h
 | 
						|
 *  Any ideas on architectural improvements are WELCOME
 | 
						|
 */
 | 
						|
extern gboolean xkl_xkb_config_native_prepare (XklEngine * engine,
 | 
						|
					       const XklConfigRec * data,
 | 
						|
					       XkbComponentNamesPtr
 | 
						|
					       component_names);
 | 
						|
 | 
						|
extern void xkl_xkb_config_native_cleanup (XklEngine * engine,
 | 
						|
					   XkbComponentNamesPtr
 | 
						|
					   component_names);
 | 
						|
 | 
						|
static gboolean set_xkb_component_names (EekXklLayout *layout,
 | 
						|
                                         XklConfigRec *config);
 | 
						|
 | 
						|
static void
 | 
						|
eek_xkl_layout_dispose (GObject *object)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (
 | 
						|
		    EEK_XKL_LAYOUT (object));
 | 
						|
 | 
						|
    if (priv->config) {
 | 
						|
        g_object_unref (priv->config);
 | 
						|
        priv->config = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    G_OBJECT_CLASS (eek_xkl_layout_parent_class)->dispose (object);
 | 
						|
}
 | 
						|
 | 
						|
static void 
 | 
						|
eek_xkl_layout_set_property (GObject      *object,
 | 
						|
                             guint         prop_id,
 | 
						|
                             const GValue *value,
 | 
						|
                             GParamSpec   *pspec)
 | 
						|
{
 | 
						|
    EekXklLayout *layout = EEK_XKL_LAYOUT(object);
 | 
						|
 | 
						|
    switch (prop_id) {
 | 
						|
    case PROP_MODEL:
 | 
						|
        eek_xkl_layout_set_model (layout, g_value_get_string (value));
 | 
						|
        break;
 | 
						|
    case PROP_LAYOUTS:
 | 
						|
        eek_xkl_layout_set_layouts (layout, g_value_get_boxed (value));
 | 
						|
        break;
 | 
						|
    case PROP_VARIANTS:
 | 
						|
        eek_xkl_layout_set_variants (layout, g_value_get_boxed (value));
 | 
						|
        break;
 | 
						|
    case PROP_OPTIONS:
 | 
						|
        eek_xkl_layout_set_options (layout, g_value_get_boxed (value));
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void 
 | 
						|
eek_xkl_layout_get_property (GObject    *object,
 | 
						|
                             guint       prop_id,
 | 
						|
                             GValue     *value,
 | 
						|
                             GParamSpec *pspec)
 | 
						|
{
 | 
						|
    EekXklLayout *layout = EEK_XKL_LAYOUT(object);
 | 
						|
 | 
						|
    switch (prop_id) {
 | 
						|
    case PROP_MODEL:
 | 
						|
        g_value_set_string (value,
 | 
						|
                            eek_xkl_layout_get_model (layout));
 | 
						|
        break;
 | 
						|
    case PROP_LAYOUTS:
 | 
						|
        g_value_set_boxed (value,
 | 
						|
                           eek_xkl_layout_get_layouts (layout));
 | 
						|
        break;
 | 
						|
    case PROP_VARIANTS:
 | 
						|
        g_value_set_boxed (value,
 | 
						|
                           eek_xkl_layout_get_variants (layout));
 | 
						|
        break;
 | 
						|
    case PROP_OPTIONS:
 | 
						|
        g_value_set_boxed (value,
 | 
						|
                           eek_xkl_layout_get_options (layout));
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
eek_xkl_layout_class_init (EekXklLayoutClass *klass)
 | 
						|
{
 | 
						|
    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
						|
    GParamSpec *pspec;
 | 
						|
 | 
						|
    gobject_class->dispose = eek_xkl_layout_dispose;
 | 
						|
    gobject_class->set_property = eek_xkl_layout_set_property;
 | 
						|
    gobject_class->get_property = eek_xkl_layout_get_property;
 | 
						|
 | 
						|
    /**
 | 
						|
     * EekXklLayout:model:
 | 
						|
     *
 | 
						|
     * The libxklavier model name of #EekXklLayout.
 | 
						|
     */
 | 
						|
    pspec = g_param_spec_string ("model",
 | 
						|
                                 "Model",
 | 
						|
                                 "Libxklavier model",
 | 
						|
                                 NULL,
 | 
						|
                                 G_PARAM_READWRITE);
 | 
						|
    g_object_class_install_property (gobject_class, PROP_MODEL, pspec);
 | 
						|
 | 
						|
    /**
 | 
						|
     * EekXklLayout:layouts:
 | 
						|
     *
 | 
						|
     * The libxklavier layout names of #EekXklLayout.
 | 
						|
     */
 | 
						|
    pspec = g_param_spec_boxed ("layouts",
 | 
						|
                                "Layouts",
 | 
						|
                                "Libxklavier layouts",
 | 
						|
                                G_TYPE_STRV,
 | 
						|
                                G_PARAM_READWRITE);
 | 
						|
    g_object_class_install_property (gobject_class, PROP_LAYOUTS, pspec);
 | 
						|
 | 
						|
    /**
 | 
						|
     * EekXklLayout:variants:
 | 
						|
     *
 | 
						|
     * The libxklavier variant names of #EekXklLayout.
 | 
						|
     */
 | 
						|
    pspec = g_param_spec_boxed ("variants",
 | 
						|
                                "Variants",
 | 
						|
                                "Libxklavier variants",
 | 
						|
                                G_TYPE_STRV,
 | 
						|
                                G_PARAM_READWRITE);
 | 
						|
    g_object_class_install_property (gobject_class, PROP_VARIANTS, pspec);
 | 
						|
 | 
						|
    /**
 | 
						|
     * EekXklLayout:options:
 | 
						|
     *
 | 
						|
     * The libxklavier option names of #EekXklLayout.
 | 
						|
     */
 | 
						|
    pspec = g_param_spec_boxed ("options",
 | 
						|
                                "Options",
 | 
						|
                                "Libxklavier options",
 | 
						|
                                G_TYPE_STRV,
 | 
						|
                                G_PARAM_READWRITE);
 | 
						|
    g_object_class_install_property (gobject_class, PROP_OPTIONS, pspec);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
eek_xkl_layout_init (EekXklLayout *self)
 | 
						|
{
 | 
						|
    /* void */
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_new:
 | 
						|
 *
 | 
						|
 * Create a new #EekXklLayout.
 | 
						|
 */
 | 
						|
EekLayout *
 | 
						|
eek_xkl_layout_new (Display *display, GError **error)
 | 
						|
{
 | 
						|
    return (EekLayout *) g_initable_new (EEK_TYPE_XKL_LAYOUT,
 | 
						|
                                         NULL,
 | 
						|
                                         error,
 | 
						|
                                         "display", display,
 | 
						|
                                         NULL);
 | 
						|
}
 | 
						|
 | 
						|
G_INLINE_FUNC void
 | 
						|
merge_xkl_config_rec (XklConfigRec *dst, XklConfigRec *src)
 | 
						|
{
 | 
						|
    if (src->model) {
 | 
						|
        g_free (dst->model);
 | 
						|
        dst->model = g_strdup (src->model);
 | 
						|
    }
 | 
						|
    if (src->layouts) {
 | 
						|
        g_strfreev (dst->layouts);
 | 
						|
        dst->layouts = g_strdupv (src->layouts);
 | 
						|
    }
 | 
						|
    if (src->variants) {
 | 
						|
        g_strfreev (dst->variants);
 | 
						|
        dst->variants = g_strdupv (src->variants);
 | 
						|
    }
 | 
						|
    if (src->options) {
 | 
						|
        g_strfreev (dst->options);
 | 
						|
        dst->options = g_strdupv (src->options);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_set_config: (skip)
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 * @config: Libxklavier configuration
 | 
						|
 *
 | 
						|
 * Reconfigure @layout with @config.
 | 
						|
 * Returns: %TRUE if the current layout changed, %FALSE otherwise
 | 
						|
 */
 | 
						|
gboolean
 | 
						|
eek_xkl_layout_set_config (EekXklLayout *layout,
 | 
						|
                           XklConfigRec *config)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
    XklConfigRec *c;
 | 
						|
    gboolean retval;
 | 
						|
 | 
						|
    g_return_val_if_fail (priv, FALSE);
 | 
						|
    c = xkl_config_rec_new ();
 | 
						|
    merge_xkl_config_rec (c, priv->config);
 | 
						|
    merge_xkl_config_rec (c, config);
 | 
						|
    retval = set_xkb_component_names (layout, c);
 | 
						|
    g_object_unref (c);
 | 
						|
    merge_xkl_config_rec (priv->config, config);
 | 
						|
    return retval;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_set_config_full:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 * @model: Libxklavier model name
 | 
						|
 * @layouts: Libxklavier layouts
 | 
						|
 * @variants: Libxklavier variants
 | 
						|
 * @options: Libxklavier options
 | 
						|
 *
 | 
						|
 * Reconfigure @layout with @model, @layouts, @variants, and @options.
 | 
						|
 * This function is merely a wrapper around
 | 
						|
 * eek_xkl_layout_set_config() to avoid passing a pointer of
 | 
						|
 * XklConfigRec, which is not currently available in the
 | 
						|
 * gobject-introspection repository.
 | 
						|
 *
 | 
						|
 * Returns: %TRUE if the current layout changed, %FALSE otherwise
 | 
						|
 * Since: 0.0.2
 | 
						|
 */
 | 
						|
gboolean
 | 
						|
eek_xkl_layout_set_config_full (EekXklLayout *layout,
 | 
						|
                                gchar *model,
 | 
						|
                                gchar **layouts,
 | 
						|
                                gchar **variants,
 | 
						|
                                gchar **options)
 | 
						|
{
 | 
						|
    XklConfigRec *config;
 | 
						|
    gboolean retval;
 | 
						|
 | 
						|
    config = xkl_config_rec_new ();
 | 
						|
    config->model = g_strdup (model);
 | 
						|
    config->layouts = g_strdupv (layouts);
 | 
						|
    config->variants = g_strdupv (variants);
 | 
						|
    config->options = g_strdupv (options);
 | 
						|
    retval = eek_xkl_layout_set_config (layout, config);
 | 
						|
    g_object_unref (config);
 | 
						|
    return retval;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_set_model:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 * @model: model name
 | 
						|
 *
 | 
						|
 * Set the model name of @layout configuration (in the Libxklavier terminology).
 | 
						|
 * Returns: %TRUE if the current layout changed, %FALSE otherwise
 | 
						|
 */
 | 
						|
gboolean
 | 
						|
eek_xkl_layout_set_model (EekXklLayout *layout,
 | 
						|
                          const gchar  *model)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
    XklConfigRec *config;
 | 
						|
    gboolean retval;
 | 
						|
    
 | 
						|
    g_return_val_if_fail (priv, FALSE);
 | 
						|
    config = xkl_config_rec_new ();
 | 
						|
    /* config->model will be freed on g_object_unref (config) */
 | 
						|
    if (model)
 | 
						|
        config->model = g_strdup (model);
 | 
						|
    else
 | 
						|
        config->model = NULL;
 | 
						|
    retval = eek_xkl_layout_set_config (layout, config);
 | 
						|
    g_object_unref (config);
 | 
						|
    return retval;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_set_layouts:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 * @layouts: layout names
 | 
						|
 *
 | 
						|
 * Set the layout names of @layout (in the Libxklavier terminology).
 | 
						|
 * Returns: %TRUE if the current layout changed, %FALSE otherwise
 | 
						|
 */
 | 
						|
gboolean
 | 
						|
eek_xkl_layout_set_layouts (EekXklLayout *layout,
 | 
						|
                            gchar       **layouts)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
    XklConfigRec *config;
 | 
						|
    gboolean retval;
 | 
						|
 | 
						|
    g_return_val_if_fail (priv, FALSE);
 | 
						|
    config = xkl_config_rec_new ();
 | 
						|
    /* config->layouts will be freed on g_object_unref (config) */
 | 
						|
    if (layouts)
 | 
						|
        config->layouts = g_strdupv (layouts);
 | 
						|
    else
 | 
						|
        config->layouts = layouts;
 | 
						|
    retval = eek_xkl_layout_set_config (layout, config);
 | 
						|
    g_object_unref (config);
 | 
						|
    return retval;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_set_variants:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 * @variants: variant names
 | 
						|
 *
 | 
						|
 * Set the variant names of @layout (in the Libxklavier terminology).
 | 
						|
 * Returns: %TRUE if the current layout changed, %FALSE otherwise
 | 
						|
 */
 | 
						|
gboolean
 | 
						|
eek_xkl_layout_set_variants (EekXklLayout *layout,
 | 
						|
                             gchar       **variants)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
    XklConfigRec *config;
 | 
						|
    gboolean retval;
 | 
						|
 | 
						|
    g_return_val_if_fail (priv, FALSE);
 | 
						|
    config = xkl_config_rec_new ();
 | 
						|
    /* config->variants will be freed on g_object_unref (config) */
 | 
						|
    if (variants)
 | 
						|
        config->variants = g_strdupv (variants);
 | 
						|
    else
 | 
						|
        config->variants = NULL;
 | 
						|
    retval = eek_xkl_layout_set_config (layout, config);
 | 
						|
    g_object_unref (config);
 | 
						|
    return retval;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_set_options:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 * @options: option names
 | 
						|
 *
 | 
						|
 * Set the option names of @layout (in the Libxklavier terminology).
 | 
						|
 * Returns: %TRUE if the current layout changed, %FALSE otherwise
 | 
						|
 */
 | 
						|
gboolean
 | 
						|
eek_xkl_layout_set_options (EekXklLayout *layout,
 | 
						|
                            gchar       **options)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
    XklConfigRec *config;
 | 
						|
    gboolean retval;
 | 
						|
 | 
						|
    g_return_val_if_fail (priv, FALSE);
 | 
						|
    config = xkl_config_rec_new ();
 | 
						|
    /* config->options will be freed on g_object_unref (config) */
 | 
						|
    if (options)
 | 
						|
        config->options = options;
 | 
						|
    else
 | 
						|
        config->options = NULL;
 | 
						|
    retval = eek_xkl_layout_set_config (layout, config);
 | 
						|
    g_object_unref (config);
 | 
						|
    return retval;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_enable_option:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 * @option: option name
 | 
						|
 *
 | 
						|
 * Set the option of @layout (in the Libxklavier terminology).
 | 
						|
 * Returns: %TRUE if the current layout changed, %FALSE otherwise
 | 
						|
 */
 | 
						|
gboolean
 | 
						|
eek_xkl_layout_enable_option  (EekXklLayout *layout,
 | 
						|
                               const gchar  *option)
 | 
						|
{
 | 
						|
    gchar **options, **_options;
 | 
						|
    gint i, j;
 | 
						|
 | 
						|
    options = eek_xkl_layout_get_options (layout);
 | 
						|
    for (i = 0; options && options[i]; i++)
 | 
						|
        if (g_strcmp0 (options[i], option) == 0)
 | 
						|
            return TRUE;
 | 
						|
    _options = g_new0 (gchar *, (i + 2));
 | 
						|
    for (j = 0; j < i; j++)
 | 
						|
        _options[j] = g_strdup (options[j]);
 | 
						|
    _options[i] = g_strdup (option);
 | 
						|
    /* eek_xkl_layout_set_options() will free _options and its elements. */
 | 
						|
    return eek_xkl_layout_set_options (layout, _options);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_disable_option:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 * @option: option name
 | 
						|
 *
 | 
						|
 * Unset the option of @layout (in the Libxklavier terminology).
 | 
						|
 * Returns: %TRUE if the current layout changed, %FALSE otherwise
 | 
						|
 */
 | 
						|
gboolean
 | 
						|
eek_xkl_layout_disable_option (EekXklLayout *layout,
 | 
						|
                               const gchar  *option)
 | 
						|
{
 | 
						|
    gchar **options, **_options;
 | 
						|
    gint i, j, k;
 | 
						|
 | 
						|
    options = eek_xkl_layout_get_options (layout);
 | 
						|
    if (!options)
 | 
						|
        return TRUE;
 | 
						|
    for (i = 0, k = 0; options[i]; i++)
 | 
						|
        if (g_strcmp0 (options[i], option) == 0)
 | 
						|
            k = i;
 | 
						|
    if (options[k] == NULL)
 | 
						|
        return TRUE;
 | 
						|
    _options = g_new0 (gchar *, i);
 | 
						|
    for (j = 0; j < k; j++)
 | 
						|
        _options[j] = g_strdup (options[j]);
 | 
						|
    for (j = k + 1; j < i; j++)
 | 
						|
        _options[j] = g_strdup (options[j]);
 | 
						|
    /* eek_xkl_layout_set_options() will free _options and its elements. */
 | 
						|
    return eek_xkl_layout_set_options (layout, _options);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_get_model:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 *
 | 
						|
 * Get the model name of @layout configuration (in the Libxklavier terminology).
 | 
						|
 */
 | 
						|
gchar *
 | 
						|
eek_xkl_layout_get_model (EekXklLayout *layout)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
 | 
						|
    g_return_val_if_fail (priv, NULL);
 | 
						|
    return g_strdup (priv->config->model);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_get_layouts:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 *
 | 
						|
 * Get the layout names of @layout configuration (in the Libxklavier
 | 
						|
 * terminology).
 | 
						|
 */
 | 
						|
gchar **
 | 
						|
eek_xkl_layout_get_layouts (EekXklLayout *layout)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
 | 
						|
    g_return_val_if_fail (priv, NULL);
 | 
						|
    return g_strdupv (priv->config->layouts);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_get_variants:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 *
 | 
						|
 * Get the variant names of @layout configuration (in the Libxklavier
 | 
						|
 * terminology).
 | 
						|
 */
 | 
						|
gchar **
 | 
						|
eek_xkl_layout_get_variants (EekXklLayout *layout)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
 | 
						|
    g_return_val_if_fail (priv, NULL);
 | 
						|
    return g_strdupv (priv->config->variants);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_get_options:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 *
 | 
						|
 * Get the option names of @layout configuration (in the Libxklavier
 | 
						|
 * terminology).
 | 
						|
 */
 | 
						|
gchar **
 | 
						|
eek_xkl_layout_get_options (EekXklLayout *layout)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
 | 
						|
    g_return_val_if_fail (priv, NULL);
 | 
						|
    return g_strdupv (priv->config->options);
 | 
						|
}
 | 
						|
 | 
						|
static gboolean
 | 
						|
set_xkb_component_names (EekXklLayout *layout, XklConfigRec *config)
 | 
						|
{
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
    XkbComponentNamesRec names;
 | 
						|
    gboolean retval = FALSE;
 | 
						|
 | 
						|
#if DEBUG
 | 
						|
    if (config->layouts) {
 | 
						|
        gint i;
 | 
						|
 | 
						|
        fprintf (stderr, "layout = ");
 | 
						|
        for (i = 0; config->layouts[i] != NULL; i++)
 | 
						|
            fprintf (stderr, "\"%s\" ", config->layouts[i]);
 | 
						|
        fputc ('\n', stderr);
 | 
						|
    } else
 | 
						|
        fprintf (stderr, "layouts = NULL\n");
 | 
						|
    if (config->variants) {
 | 
						|
        gint i;
 | 
						|
 | 
						|
        fprintf (stderr, "variant = ");
 | 
						|
        for (i = 0; config->variants[i]; i++)
 | 
						|
            fprintf (stderr, "\"%s\" ", config->variants[i]);
 | 
						|
        fputc ('\n', stderr);
 | 
						|
    } else
 | 
						|
        fprintf (stderr, "variants = NULL\n");
 | 
						|
    if (config->options) {
 | 
						|
        gint i;
 | 
						|
 | 
						|
        fprintf (stderr, "option = ");
 | 
						|
        for (i = 0; config->options[i]; i++)
 | 
						|
            fprintf (stderr, "\"%s\" ", config->options[i]);
 | 
						|
        fputc ('\n', stderr);
 | 
						|
    } else
 | 
						|
        fprintf (stderr, "options = NULL\n");
 | 
						|
#endif
 | 
						|
 | 
						|
    if (xkl_xkb_config_native_prepare (priv->engine, config, &names)) {
 | 
						|
        GError *error = NULL;
 | 
						|
        retval = eek_xkb_layout_set_names (EEK_XKB_LAYOUT(layout),
 | 
						|
                                           &names,
 | 
						|
                                           &error);
 | 
						|
        if (!retval)
 | 
						|
            g_warning ("can't set XKB layout");
 | 
						|
        xkl_xkb_config_native_cleanup (priv->engine, &names);
 | 
						|
    }
 | 
						|
    return retval;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * eek_xkl_layout_get_option:
 | 
						|
 * @layout: an #EekXklLayout
 | 
						|
 * @option: option name
 | 
						|
 *
 | 
						|
 * Tell if the option of @layout (in the Libxklavier terminology) is set.
 | 
						|
 * Returns: %TRUE if the option is set, %FALSE otherwise
 | 
						|
 */
 | 
						|
gboolean
 | 
						|
eek_xkl_layout_get_option (EekXklLayout *layout,
 | 
						|
                           const gchar  *option)
 | 
						|
{
 | 
						|
    gchar **options;
 | 
						|
    gint i;
 | 
						|
 | 
						|
    options = eek_xkl_layout_get_options (layout);
 | 
						|
    for (i = 0; options && options[i]; i++)
 | 
						|
        if (g_strcmp0 (options[i], option) == 0)
 | 
						|
            return TRUE;
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
static gboolean
 | 
						|
initable_init (GInitable    *initable,
 | 
						|
               GCancellable *cancellable,
 | 
						|
               GError      **error)
 | 
						|
{
 | 
						|
    EekXklLayout *layout = EEK_XKL_LAYOUT (initable);
 | 
						|
    EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
 | 
						|
    Display *display;
 | 
						|
 | 
						|
    if (!parent_initable_iface->init (initable, cancellable, error))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    priv->config = xkl_config_rec_new ();
 | 
						|
 | 
						|
    g_object_get (G_OBJECT (initable),
 | 
						|
                  "display", &display,
 | 
						|
                  NULL);
 | 
						|
 | 
						|
    priv->engine = xkl_engine_get_instance (display);
 | 
						|
 | 
						|
    if (!xkl_config_rec_get_from_server (priv->config,
 | 
						|
                                         priv->engine)) {
 | 
						|
        g_set_error (error,
 | 
						|
                     EEK_ERROR,
 | 
						|
                     EEK_ERROR_LAYOUT_ERROR,
 | 
						|
                     "can't load libxklavier configuration");
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    set_xkb_component_names (layout, priv->config);
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
initable_iface_init (GInitableIface *initable_iface)
 | 
						|
{
 | 
						|
    parent_initable_iface = g_type_interface_peek_parent (initable_iface);
 | 
						|
    initable_iface->init = initable_init;
 | 
						|
}
 | 
						|
 |