Remove unused files and functions
This commit is contained in:
@ -1,30 +0,0 @@
|
||||
# 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
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libeek-xkb
|
||||
Description: A Library to Create Keyboard-like UI (XKB Support)
|
||||
URL: http://fedorahosted.org/eekboard/
|
||||
Version: @VERSION@
|
||||
Requires: eek-@EEK_API_VERSION@ gtk+-x11-@GTK_API_VERSION@
|
||||
Libs: -L${libdir} -leek-xkb
|
||||
Cflags: -I${includedir}/eek-@EEK_API_VERSION@
|
||||
@ -1,684 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
|
||||
* 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-xkb-layout
|
||||
* @short_description: Layout engine using XKB configuration
|
||||
*
|
||||
* The #EekXkbLayout inherits #EekLayout class and arranges keyboard
|
||||
* elements using XKB.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include "eek-xkb-layout.h"
|
||||
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/extensions/XKBgeom.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "eek-keyboard.h"
|
||||
#include "eek-section.h"
|
||||
#include "eek-key.h"
|
||||
#include "eek-keysym.h"
|
||||
|
||||
#define XKB_COMPONENT_MASK (XkbGBN_GeometryMask | \
|
||||
XkbGBN_KeyNamesMask | \
|
||||
XkbGBN_OtherNamesMask | \
|
||||
XkbGBN_SymbolsMask | \
|
||||
XkbGBN_IndicatorMapMask)
|
||||
|
||||
static void initable_iface_init (GInitableIface *initable_iface);
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_DISPLAY,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
typedef struct _EekXkbLayoutPrivate
|
||||
{
|
||||
/* Configuration names that should synch'ed to the symbolic names
|
||||
in priv->xkb->names. Since we use GLib's memory allocator,
|
||||
don't store any address returned from the X server here. */
|
||||
XkbComponentNamesRec names;
|
||||
|
||||
Display *display;
|
||||
|
||||
/* Actual XKB configuration of DISPLAY. */
|
||||
XkbDescRec *xkb;
|
||||
|
||||
/* Hash table to cache orefs by shape address. */
|
||||
GHashTable *shape_oref_hash;
|
||||
|
||||
gint scale_numerator;
|
||||
gint scale_denominator;
|
||||
} EekXkbLayoutPrivate;
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (EekXkbLayout, eek_xkb_layout, EEK_TYPE_LAYOUT,
|
||||
0, /* GTypeFlags */
|
||||
G_ADD_PRIVATE(EekXkbLayout)
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
|
||||
initable_iface_init))
|
||||
|
||||
static guint find_keycode (EekXkbLayout *layout,
|
||||
gchar *key_name);
|
||||
|
||||
static gboolean get_keyboard_from_server (EekXkbLayout *layout,
|
||||
GError **error);
|
||||
|
||||
static gboolean get_names_from_server (EekXkbLayout *layout,
|
||||
GError **error);
|
||||
|
||||
static void setup_scaling (EekXkbLayout *layout,
|
||||
gdouble width,
|
||||
gdouble height);
|
||||
|
||||
G_INLINE_FUNC gint
|
||||
xkb_to_pixmap_coord (EekXkbLayout *layout,
|
||||
gint n)
|
||||
{
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
return n * priv->scale_numerator / priv->scale_denominator;
|
||||
}
|
||||
|
||||
G_INLINE_FUNC gdouble
|
||||
xkb_to_pixmap_double (EekXkbLayout *layout,
|
||||
gdouble d)
|
||||
{
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
return d * priv->scale_numerator / priv->scale_denominator;
|
||||
}
|
||||
|
||||
static void
|
||||
create_key (EekXkbLayout *layout,
|
||||
EekKeyboard *keyboard,
|
||||
EekSection *section,
|
||||
gint column,
|
||||
gint row,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
XkbKeyRec *xkbkey)
|
||||
{
|
||||
XkbGeometryRec *xkbgeometry;
|
||||
XkbBoundsRec *xkbbounds;
|
||||
XkbShapeRec *xkbshape;
|
||||
XkbOutlineRec *xkboutline;
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
EekKey *key;
|
||||
EekBounds bounds;
|
||||
EekSymbolMatrix *matrix = NULL;
|
||||
gchar name[XkbKeyNameLength + 1];
|
||||
KeyCode keycode;
|
||||
gint num_groups, num_levels;
|
||||
guint oref;
|
||||
gpointer v;
|
||||
|
||||
xkbgeometry = priv->xkb->geom;
|
||||
xkbshape = &xkbgeometry->shapes[xkbkey->shape_ndx];
|
||||
if (g_hash_table_lookup_extended (priv->shape_oref_hash, xkbshape,
|
||||
NULL, &v)) {
|
||||
oref = GPOINTER_TO_UINT(v);
|
||||
} else {
|
||||
EekOutline *outline;
|
||||
|
||||
xkboutline = xkbshape->primary == NULL ? &xkbshape->outlines[0] :
|
||||
xkbshape->primary;
|
||||
|
||||
outline = g_slice_new (EekOutline);
|
||||
outline->corner_radius = xkb_to_pixmap_coord(layout,
|
||||
xkboutline->corner_radius);
|
||||
|
||||
if (xkboutline->num_points <= 2) { /* rectangular */
|
||||
gdouble x1, y1, x2, y2;
|
||||
|
||||
outline->num_points = 4;
|
||||
outline->points = g_slice_alloc0 (sizeof (EekPoint) *
|
||||
outline->num_points);
|
||||
if (xkboutline->num_points == 1) {
|
||||
x1 = xkb_to_pixmap_coord(layout, xkbshape->bounds.x1);
|
||||
y1 = xkb_to_pixmap_coord(layout, xkbshape->bounds.y1);
|
||||
x2 = xkb_to_pixmap_coord(layout, xkboutline->points[0].x);
|
||||
y2 = xkb_to_pixmap_coord(layout, xkboutline->points[0].y);
|
||||
} else {
|
||||
x1 = xkb_to_pixmap_coord(layout, xkboutline->points[0].x);
|
||||
y1 = xkb_to_pixmap_coord(layout, xkboutline->points[0].y);
|
||||
x2 = xkb_to_pixmap_coord(layout, xkboutline->points[1].x);
|
||||
y2 = xkb_to_pixmap_coord(layout, xkboutline->points[1].y);
|
||||
}
|
||||
outline->points[0].x = outline->points[3].x = x1;
|
||||
outline->points[0].y = outline->points[1].y = y1;
|
||||
outline->points[1].x = outline->points[2].x = x2;
|
||||
outline->points[2].y = outline->points[3].y = y2;
|
||||
} else { /* polygon */
|
||||
gint i;
|
||||
|
||||
outline->num_points = xkboutline->num_points;
|
||||
outline->points = g_new0 (EekPoint, outline->num_points);
|
||||
for (i = 0; i < xkboutline->num_points; i++) {
|
||||
outline->points[i].x =
|
||||
xkb_to_pixmap_coord(layout, xkboutline->points[i].x);
|
||||
outline->points[i].y =
|
||||
xkb_to_pixmap_coord(layout, xkboutline->points[i].y);
|
||||
}
|
||||
}
|
||||
oref = eek_keyboard_add_outline (keyboard, outline);
|
||||
eek_outline_free (outline);
|
||||
g_hash_table_insert (priv->shape_oref_hash, xkbshape,
|
||||
GUINT_TO_POINTER(oref));
|
||||
}
|
||||
|
||||
memset (name, 0, sizeof name);
|
||||
memcpy (name, xkbkey->name.name, sizeof name - 1);
|
||||
|
||||
xkbbounds = &xkbgeometry->shapes[xkbkey->shape_ndx].bounds;
|
||||
bounds.x = xkb_to_pixmap_coord(layout, xkbbounds->x1 + x);
|
||||
bounds.y = xkb_to_pixmap_coord(layout, xkbbounds->y1 + y);
|
||||
bounds.width = xkb_to_pixmap_coord(layout, xkbbounds->x2 - xkbbounds->x1);
|
||||
bounds.height = xkb_to_pixmap_coord(layout, xkbbounds->y2 - xkbbounds->y1);
|
||||
|
||||
keycode = find_keycode (layout, name);
|
||||
if (keycode == EEK_INVALID_KEYCODE) {
|
||||
num_groups = num_levels = 0;
|
||||
matrix = eek_symbol_matrix_new (0, 0);
|
||||
} else {
|
||||
KeySym keysym;
|
||||
gint i, j;
|
||||
|
||||
num_groups = XkbKeyNumGroups (priv->xkb, keycode);
|
||||
num_levels = XkbKeyGroupsWidth (priv->xkb, keycode);
|
||||
matrix = eek_symbol_matrix_new (num_groups, num_levels);
|
||||
for (i = 0; i < num_groups; i++)
|
||||
for (j = 0; j < num_levels; j++) {
|
||||
EekModifierType modifier;
|
||||
|
||||
keysym = XkbKeySymEntry (priv->xkb, keycode, j, i);
|
||||
modifier = XkbKeysymToModifiers (priv->display, keysym);
|
||||
matrix->data[i * num_levels + j] =
|
||||
EEK_SYMBOL(eek_keysym_new_with_modifier (keysym,
|
||||
modifier));
|
||||
}
|
||||
}
|
||||
|
||||
key = eek_section_create_key (section, keycode, column, row);
|
||||
eek_element_set_name (EEK_ELEMENT(key), name);
|
||||
eek_element_set_bounds (EEK_ELEMENT(key), &bounds);
|
||||
eek_key_set_symbol_matrix (key, matrix);
|
||||
eek_symbol_matrix_free (matrix);
|
||||
eek_key_set_oref (key, oref);
|
||||
}
|
||||
|
||||
static void
|
||||
create_section (EekXkbLayout *layout,
|
||||
EekKeyboard *keyboard,
|
||||
XkbSectionRec *xkbsection)
|
||||
{
|
||||
XkbGeometryRec *xkbgeometry;
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
EekSection *section;
|
||||
EekBounds bounds;
|
||||
gchar *name;
|
||||
gfloat left, top;
|
||||
gint i, j;
|
||||
|
||||
bounds.x = xkb_to_pixmap_coord(layout, xkbsection->left);
|
||||
bounds.y = xkb_to_pixmap_coord(layout, xkbsection->top);
|
||||
bounds.width = xkb_to_pixmap_coord(layout, xkbsection->width);
|
||||
bounds.height = xkb_to_pixmap_coord(layout, xkbsection->height);
|
||||
|
||||
xkbgeometry = priv->xkb->geom;
|
||||
section = eek_keyboard_create_section (keyboard);
|
||||
name = XGetAtomName (priv->display, xkbsection->name);
|
||||
eek_element_set_name (EEK_ELEMENT(section), name);
|
||||
XFree (name);
|
||||
eek_element_set_bounds (EEK_ELEMENT(section), &bounds);
|
||||
eek_section_set_angle (section,
|
||||
/* angle is in tenth of degree */
|
||||
xkbsection->angle / 10);
|
||||
|
||||
for (i = 0; i < xkbsection->num_rows; i++) {
|
||||
XkbRowRec *xkbrow;
|
||||
|
||||
xkbrow = &xkbsection->rows[i];
|
||||
left = xkbrow->left;
|
||||
top = xkbrow->top;
|
||||
eek_section_add_row (section,
|
||||
xkbrow->num_keys,
|
||||
xkbrow->vertical ?
|
||||
EEK_ORIENTATION_VERTICAL :
|
||||
EEK_ORIENTATION_HORIZONTAL);
|
||||
for (j = 0; j < xkbrow->num_keys; j++) {
|
||||
XkbKeyRec *xkbkey;
|
||||
XkbBoundsRec *xkbbounds;
|
||||
|
||||
xkbkey = &xkbrow->keys[j];
|
||||
if (xkbrow->vertical)
|
||||
top += xkbkey->gap;
|
||||
else
|
||||
left += xkbkey->gap;
|
||||
create_key (layout, keyboard, section, j, i, left, top, xkbkey);
|
||||
xkbbounds = &xkbgeometry->shapes[xkbkey->shape_ndx].bounds;
|
||||
if (xkbrow->vertical)
|
||||
top += xkbbounds->y2 - xkbbounds->y1;
|
||||
else
|
||||
left += xkbbounds->x2 - xkbbounds->x1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
create_keyboard (EekXkbLayout *layout, EekKeyboard *keyboard)
|
||||
{
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
XkbGeometryRec *xkbgeometry;
|
||||
EekBounds bounds;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (priv->xkb);
|
||||
g_return_if_fail (priv->xkb->geom);
|
||||
|
||||
xkbgeometry = priv->xkb->geom;
|
||||
|
||||
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
|
||||
setup_scaling (EEK_XKB_LAYOUT(layout), bounds.width, bounds.height);
|
||||
|
||||
bounds.x = bounds.y = 0;
|
||||
bounds.width = xkb_to_pixmap_coord(layout, xkbgeometry->width_mm);
|
||||
bounds.height = xkb_to_pixmap_coord(layout, xkbgeometry->height_mm);
|
||||
|
||||
for (i = 0; i < xkbgeometry->num_sections; i++) {
|
||||
XkbSectionRec *xkbsection;
|
||||
|
||||
xkbsection = &xkbgeometry->sections[i];
|
||||
create_section (layout, keyboard, xkbsection);
|
||||
}
|
||||
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
|
||||
}
|
||||
|
||||
static EekKeyboard *
|
||||
eek_xkb_layout_real_create_keyboard (EekboardContextService *manager,
|
||||
EekLayout *self,
|
||||
gdouble initial_width,
|
||||
gdouble initial_height)
|
||||
{
|
||||
EekKeyboard *keyboard = g_object_new (EEK_TYPE_KEYBOARD, "layout", self, NULL);
|
||||
keyboard->manager = manager;
|
||||
|
||||
EekBounds bounds = {
|
||||
.x = 0.0,
|
||||
.y = 0.0,
|
||||
.width = initial_width,
|
||||
.height = initial_height
|
||||
};
|
||||
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
|
||||
|
||||
/* resolve modifiers dynamically assigned at run time */
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (
|
||||
EEK_XKB_LAYOUT(self));
|
||||
eek_keyboard_set_num_lock_mask (keyboard,
|
||||
XkbKeysymToModifiers (priv->display,
|
||||
XK_Num_Lock));
|
||||
eek_keyboard_set_alt_gr_mask (keyboard,
|
||||
XkbKeysymToModifiers (priv->display,
|
||||
XK_ISO_Level3_Shift));
|
||||
|
||||
if (priv->shape_oref_hash)
|
||||
g_hash_table_destroy (priv->shape_oref_hash);
|
||||
|
||||
priv->shape_oref_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
create_keyboard (EEK_XKB_LAYOUT(self), keyboard);
|
||||
g_hash_table_destroy (priv->shape_oref_hash);
|
||||
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
static void
|
||||
eek_xkb_layout_finalize (GObject *object)
|
||||
{
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (
|
||||
EEK_XKB_LAYOUT (object));
|
||||
|
||||
g_free (priv->names.keycodes);
|
||||
g_free (priv->names.geometry);
|
||||
g_free (priv->names.symbols);
|
||||
XkbFreeKeyboard (priv->xkb, 0, TRUE); /* free_all = TRUE */
|
||||
G_OBJECT_CLASS (eek_xkb_layout_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_xkb_layout_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
EekXkbLayout *layout = EEK_XKB_LAYOUT (object);
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DISPLAY:
|
||||
priv->display = g_value_get_pointer (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eek_xkb_layout_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
EekXkbLayout *layout = EEK_XKB_LAYOUT (object);
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_pointer (value, priv->display);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eek_xkb_layout_class_init (EekXkbLayoutClass *klass)
|
||||
{
|
||||
EekLayoutClass *layout_class = EEK_LAYOUT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
layout_class->create_keyboard = eek_xkb_layout_real_create_keyboard;
|
||||
|
||||
gobject_class->finalize = eek_xkb_layout_finalize;
|
||||
gobject_class->set_property = eek_xkb_layout_set_property;
|
||||
gobject_class->get_property = eek_xkb_layout_get_property;
|
||||
|
||||
pspec = g_param_spec_pointer ("display",
|
||||
"Display",
|
||||
"X Display",
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class, PROP_DISPLAY, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_xkb_layout_init (EekXkbLayout *self)
|
||||
{
|
||||
/* void */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_names_from_server (EekXkbLayout *layout,
|
||||
GError **error)
|
||||
{
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
gchar *name;
|
||||
|
||||
XkbGetNames (priv->display, XkbAllNamesMask, priv->xkb);
|
||||
|
||||
if (priv->xkb->names->keycodes <= 0)
|
||||
g_warning ("XKB keycodes setting is not loaded properly");
|
||||
else {
|
||||
name = XGetAtomName (priv->display, priv->xkb->names->keycodes);
|
||||
if (!name)
|
||||
g_warning ("Can't get the name of keycodes");
|
||||
else if (!priv->names.keycodes ||
|
||||
g_strcmp0 (name, priv->names.keycodes)) {
|
||||
g_free (priv->names.keycodes);
|
||||
priv->names.keycodes = g_strdup (name);
|
||||
XFree (name);
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->xkb->names->geometry <= 0)
|
||||
g_warning ("XKB geometry setting is not loaded");
|
||||
else {
|
||||
name = XGetAtomName (priv->display, priv->xkb->names->geometry);
|
||||
if (!name)
|
||||
g_warning ("Can't get the name of geometry");
|
||||
else if (!priv->names.geometry ||
|
||||
g_strcmp0 (name, priv->names.geometry)) {
|
||||
g_free (priv->names.geometry);
|
||||
priv->names.geometry = g_strdup (name);
|
||||
XFree (name);
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->xkb->names->symbols <= 0)
|
||||
g_warning ("XKB symbols setting is not loaded");
|
||||
else {
|
||||
name = XGetAtomName (priv->display, priv->xkb->names->symbols);
|
||||
if (!name)
|
||||
g_warning ("Can't get the name of symbols");
|
||||
else if (!priv->names.symbols ||
|
||||
g_strcmp0 (name, priv->names.symbols)) {
|
||||
g_free (priv->names.symbols);
|
||||
priv->names.symbols = g_strdup (name);
|
||||
XFree (name);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_xkb_layout_new:
|
||||
*
|
||||
* Create a new #EekXkbLayout.
|
||||
*/
|
||||
EekLayout *
|
||||
eek_xkb_layout_new (Display *display,
|
||||
GError **error)
|
||||
{
|
||||
return (EekLayout *) g_initable_new (EEK_TYPE_XKB_LAYOUT,
|
||||
NULL,
|
||||
error,
|
||||
"display", display,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_xkb_layout_set_names: (skip)
|
||||
* @layout: an #EekXkbLayout
|
||||
* @names: XKB component names
|
||||
* @error: a #GError
|
||||
*
|
||||
* Set the XKB component names to @layout.
|
||||
* Returns: %TRUE if the component names are successfully set, %FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
eek_xkb_layout_set_names (EekXkbLayout *layout,
|
||||
XkbComponentNamesRec *names,
|
||||
GError **error)
|
||||
{
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
|
||||
if (g_strcmp0 (names->keycodes, priv->names.keycodes)) {
|
||||
g_free (priv->names.keycodes);
|
||||
priv->names.keycodes = g_strdup (names->keycodes);
|
||||
}
|
||||
|
||||
if (g_strcmp0 (names->geometry, priv->names.geometry)) {
|
||||
g_free (priv->names.geometry);
|
||||
priv->names.geometry = g_strdup (names->geometry);
|
||||
}
|
||||
|
||||
if (g_strcmp0 (names->symbols, priv->names.symbols)) {
|
||||
g_free (priv->names.symbols);
|
||||
priv->names.symbols = g_strdup (names->symbols);
|
||||
}
|
||||
|
||||
return get_keyboard_from_server (layout, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_keyboard_from_server (EekXkbLayout *layout,
|
||||
GError **error)
|
||||
{
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
|
||||
if (priv->xkb) {
|
||||
XkbFreeKeyboard (priv->xkb, 0, True);
|
||||
priv->xkb = NULL;
|
||||
}
|
||||
|
||||
if (priv->names.keycodes && priv->names.geometry && priv->names.symbols) {
|
||||
priv->xkb = XkbGetKeyboardByName (priv->display,
|
||||
XkbUseCoreKbd,
|
||||
&priv->names,
|
||||
0,
|
||||
XKB_COMPONENT_MASK,
|
||||
False);
|
||||
} else {
|
||||
priv->xkb = XkbGetKeyboard (priv->display,
|
||||
XKB_COMPONENT_MASK,
|
||||
XkbUseCoreKbd);
|
||||
if (!get_names_from_server (layout, error)) {
|
||||
XkbFreeKeyboard (priv->xkb, 0, True);
|
||||
priv->xkb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->xkb == NULL) {
|
||||
g_set_error (error,
|
||||
EEK_ERROR,
|
||||
EEK_ERROR_LAYOUT_ERROR,
|
||||
"can't get keyboard from server");
|
||||
g_free (priv->names.keycodes);
|
||||
priv->names.keycodes = NULL;
|
||||
g_free (priv->names.geometry);
|
||||
priv->names.geometry = NULL;
|
||||
g_free (priv->names.symbols);
|
||||
priv->names.symbols = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static guint
|
||||
find_keycode (EekXkbLayout *layout, gchar *key_name)
|
||||
{
|
||||
#define KEYSYM_NAME_MAX_LENGTH 4
|
||||
guint keycode;
|
||||
gint i, j;
|
||||
XkbKeyNamePtr pkey;
|
||||
XkbKeyAliasPtr palias;
|
||||
guint is_name_matched;
|
||||
gchar *src, *dst;
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
|
||||
if (!priv->xkb)
|
||||
return EEK_INVALID_KEYCODE;
|
||||
|
||||
pkey = priv->xkb->names->keys + priv->xkb->min_key_code;
|
||||
for (keycode = priv->xkb->min_key_code;
|
||||
keycode <= priv->xkb->max_key_code; keycode++) {
|
||||
is_name_matched = 1;
|
||||
src = key_name;
|
||||
dst = pkey->name;
|
||||
for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
|
||||
if ('\0' == *src)
|
||||
break;
|
||||
if (*src++ != *dst++) {
|
||||
is_name_matched = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_name_matched)
|
||||
return keycode;
|
||||
pkey++;
|
||||
}
|
||||
|
||||
palias = priv->xkb->names->key_aliases;
|
||||
for (j = priv->xkb->names->num_key_aliases; --j >= 0;) {
|
||||
is_name_matched = 1;
|
||||
src = key_name;
|
||||
dst = palias->alias;
|
||||
for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
|
||||
if ('\0' == *src)
|
||||
break;
|
||||
if (*src++ != *dst++) {
|
||||
is_name_matched = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_name_matched) {
|
||||
keycode = find_keycode (layout, palias->real);
|
||||
return keycode;
|
||||
}
|
||||
palias++;
|
||||
}
|
||||
|
||||
return EEK_INVALID_KEYCODE;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_scaling (EekXkbLayout *layout,
|
||||
gdouble width,
|
||||
gdouble height)
|
||||
{
|
||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
||||
|
||||
g_return_if_fail (priv->xkb);
|
||||
|
||||
g_return_if_fail (priv->xkb->geom->width_mm > 0);
|
||||
g_return_if_fail (priv->xkb->geom->height_mm > 0);
|
||||
|
||||
if (width * priv->xkb->geom->height_mm <
|
||||
height * priv->xkb->geom->width_mm) {
|
||||
priv->scale_numerator = width;
|
||||
priv->scale_denominator = priv->xkb->geom->width_mm;
|
||||
} else {
|
||||
priv->scale_numerator = height;
|
||||
priv->scale_denominator = priv->xkb->geom->height_mm;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
initable_init (GInitable *initable,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
EekXkbLayout *layout = EEK_XKB_LAYOUT (initable);
|
||||
|
||||
if (!get_keyboard_from_server (layout, error))
|
||||
return FALSE;
|
||||
|
||||
if (!get_names_from_server (layout, error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
initable_iface_init (GInitableIface *initable_iface)
|
||||
{
|
||||
initable_iface->init = initable_init;
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
|
||||
#error "Only <eek/eek-xkb.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef EEK_XKB_LAYOUT_H
|
||||
#define EEK_XKB_LAYOUT_H 1
|
||||
|
||||
#include <X11/XKBlib.h>
|
||||
#include "eek-layout.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define EEK_TYPE_XKB_LAYOUT (eek_xkb_layout_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE (EekXkbLayout, eek_xkb_layout, EEK, XKB_LAYOUT, EekLayout)
|
||||
|
||||
struct _EekXkbLayoutClass
|
||||
{
|
||||
/*< private >*/
|
||||
EekLayoutClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[24];
|
||||
};
|
||||
|
||||
GType eek_xkb_layout_get_type (void) G_GNUC_CONST;
|
||||
EekLayout *eek_xkb_layout_new (Display *display,
|
||||
GError **error);
|
||||
|
||||
gboolean eek_xkb_layout_set_names (EekXkbLayout *layout,
|
||||
XkbComponentNamesRec *names,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* #ifndef EEK_XKB_LAYOUT_H */
|
||||
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
#ifndef EEK_XKB_H
|
||||
#define EEK_XKB_H 1
|
||||
|
||||
#include "eek.h"
|
||||
#include "eek-xkb-layout.h"
|
||||
|
||||
#endif /* EEK_XKB_H */
|
||||
@ -1,30 +0,0 @@
|
||||
# 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
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libeek-xkl
|
||||
Description: A Library to Create Keyboard-like UI (Libxklavier Support)
|
||||
URL: http://fedorahosted.org/eekboard/
|
||||
Version: @VERSION@
|
||||
Requires: eek-@EEK_API_VERSION@ libxklavier
|
||||
Libs: -L${libdir} -leek-xkl
|
||||
Cflags: -I${includedir}/eek-@EEK_API_VERSION@
|
||||
@ -1,662 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
|
||||
#error "Only <eek/eek-xkl.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef EEK_XKL_LAYOUT_H
|
||||
#define EEK_XKL_LAYOUT_H 1
|
||||
|
||||
#include <libxklavier/xklavier.h>
|
||||
#include "eek-xkb-layout.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define EEK_TYPE_XKL_LAYOUT (eek_xkl_layout_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE (EekXklLayout, eek_xkl_layout, EEK, XKL_LAYOUT, EekLayout)
|
||||
|
||||
struct _EekXklLayoutClass
|
||||
{
|
||||
/*< private >*/
|
||||
EekXkbLayoutClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[24];
|
||||
};
|
||||
|
||||
GType eek_xkl_layout_get_type (void) G_GNUC_CONST;
|
||||
|
||||
EekLayout *eek_xkl_layout_new (Display *display,
|
||||
GError **error);
|
||||
|
||||
gboolean eek_xkl_layout_set_config (EekXklLayout *layout,
|
||||
XklConfigRec *config);
|
||||
|
||||
gboolean eek_xkl_layout_set_config_full (EekXklLayout *layout,
|
||||
gchar *model,
|
||||
gchar **layouts,
|
||||
gchar **variants,
|
||||
gchar **options);
|
||||
|
||||
gboolean eek_xkl_layout_set_model (EekXklLayout *layout,
|
||||
const gchar *model);
|
||||
gboolean eek_xkl_layout_set_layouts (EekXklLayout *layout,
|
||||
gchar **layouts);
|
||||
gboolean eek_xkl_layout_set_variants (EekXklLayout *layout,
|
||||
gchar **variants);
|
||||
gboolean eek_xkl_layout_set_options (EekXklLayout *layout,
|
||||
gchar **options);
|
||||
gboolean eek_xkl_layout_enable_option (EekXklLayout *layout,
|
||||
const gchar *option);
|
||||
gboolean eek_xkl_layout_disable_option (EekXklLayout *layout,
|
||||
const gchar *option);
|
||||
|
||||
gchar *eek_xkl_layout_get_model (EekXklLayout *layout);
|
||||
gchar **eek_xkl_layout_get_layouts (EekXklLayout *layout);
|
||||
gchar **eek_xkl_layout_get_variants (EekXklLayout *layout);
|
||||
gchar **eek_xkl_layout_get_options (EekXklLayout *layout);
|
||||
gboolean eek_xkl_layout_get_option (EekXklLayout *layout,
|
||||
const gchar *option);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* #ifndef EEK_XKL_LAYOUT_H */
|
||||
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
#ifndef EEK_XKL_H
|
||||
#define EEK_XKL_H 1
|
||||
|
||||
#include "eek.h"
|
||||
#include "eek-xkl-layout.h"
|
||||
|
||||
#endif /* EEK_XKL_H */
|
||||
@ -1,404 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2011 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:eekboard-client
|
||||
* @short_description: client interface of eekboard service
|
||||
*
|
||||
* The #EekboardClient class provides a client side access to eekboard-server.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include "eekboard/eekboard-client.h"
|
||||
|
||||
enum {
|
||||
DESTROYED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
typedef struct _EekboardClientPrivate
|
||||
{
|
||||
GHashTable *context_hash;
|
||||
} EekboardClientPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EekboardClient, eekboard_client, G_TYPE_DBUS_PROXY)
|
||||
|
||||
static void send_destroy_context (EekboardClient *client,
|
||||
EekboardContext *context,
|
||||
GCancellable *cancellable);
|
||||
|
||||
static void
|
||||
eekboard_client_real_destroyed (EekboardClient *self)
|
||||
{
|
||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (self);
|
||||
|
||||
// g_debug ("eekboard_client_real_destroyed");
|
||||
g_hash_table_remove_all (priv->context_hash);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_client_dispose (GObject *object)
|
||||
{
|
||||
EekboardClient *client = EEKBOARD_CLIENT(object);
|
||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
|
||||
|
||||
if (priv->context_hash) {
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->context_hash);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||
send_destroy_context (client, (EekboardContext *)value, NULL);
|
||||
g_hash_table_iter_remove (&iter);
|
||||
}
|
||||
g_hash_table_destroy (priv->context_hash);
|
||||
priv->context_hash = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (eekboard_client_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_client_class_init (EekboardClientClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->destroyed = eekboard_client_real_destroyed;
|
||||
|
||||
gobject_class->dispose = eekboard_client_dispose;
|
||||
|
||||
/**
|
||||
* EekboardClient::destroyed:
|
||||
* @eekboard: an #EekboardClient
|
||||
*
|
||||
* The ::destroyed signal is emitted each time the name of remote
|
||||
* end is vanished.
|
||||
*/
|
||||
signals[DESTROYED] =
|
||||
g_signal_new (I_("destroyed"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(EekboardClientClass, destroyed),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_client_init (EekboardClient *self)
|
||||
{
|
||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (self);
|
||||
|
||||
priv->context_hash =
|
||||
g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
(GDestroyNotify)g_free,
|
||||
(GDestroyNotify)g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_name_vanished_callback (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
EekboardClient *client = user_data;
|
||||
g_signal_emit_by_name (client, "destroyed", NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_client_new:
|
||||
* @connection: a #GDBusConnection
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Create a client.
|
||||
*/
|
||||
EekboardClient *
|
||||
eekboard_client_new (GDBusConnection *connection,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GInitable *initable;
|
||||
GError *error;
|
||||
|
||||
g_assert (G_IS_DBUS_CONNECTION(connection));
|
||||
|
||||
error = NULL;
|
||||
initable =
|
||||
g_initable_new (EEKBOARD_TYPE_CLIENT,
|
||||
cancellable,
|
||||
&error,
|
||||
"g-connection", connection,
|
||||
"g-name", "org.fedorahosted.Eekboard",
|
||||
"g-interface-name", "org.fedorahosted.Eekboard",
|
||||
"g-object-path", "/org/fedorahosted/Eekboard",
|
||||
NULL);
|
||||
if (initable != NULL) {
|
||||
EekboardClient *client = EEKBOARD_CLIENT (initable);
|
||||
gchar *name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY(client));
|
||||
if (name_owner == NULL) {
|
||||
g_object_unref (client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* the vanished callback is called when the server is disconnected */
|
||||
g_bus_watch_name_on_connection (connection,
|
||||
name_owner,
|
||||
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||
NULL,
|
||||
eekboard_name_vanished_callback,
|
||||
client,
|
||||
NULL);
|
||||
g_free (name_owner);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
g_warning ("can't create client: %s", error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_context_destroyed (EekboardContext *context,
|
||||
gpointer user_data)
|
||||
{
|
||||
EekboardClient *client = user_data;
|
||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
|
||||
|
||||
g_hash_table_remove (priv->context_hash,
|
||||
g_dbus_proxy_get_object_path (G_DBUS_PROXY(context)));
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_client_create_context:
|
||||
* @eekboard: an #EekboardClient
|
||||
* @client_name: name of the client
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Create a new input context.
|
||||
*
|
||||
* Return value: (transfer full): a newly created #EekboardContext.
|
||||
*/
|
||||
EekboardContext *
|
||||
eekboard_client_create_context (EekboardClient *client,
|
||||
const gchar *client_name,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GVariant *variant;
|
||||
const gchar *object_path;
|
||||
EekboardContext *context;
|
||||
GError *error;
|
||||
GDBusConnection *connection;
|
||||
|
||||
g_assert (EEKBOARD_IS_CLIENT(client));
|
||||
g_assert (client_name);
|
||||
|
||||
error = NULL;
|
||||
variant = g_dbus_proxy_call_sync (G_DBUS_PROXY(client),
|
||||
"CreateContext",
|
||||
g_variant_new ("(s)", client_name),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
&error);
|
||||
if (!variant) {
|
||||
g_warning ("failed to call CreateContext: %s", error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_variant_get (variant, "(&s)", &object_path);
|
||||
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY(client));
|
||||
context = eekboard_context_new (connection, object_path, cancellable);
|
||||
if (!context) {
|
||||
g_variant_unref (variant);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
|
||||
|
||||
g_hash_table_insert (priv->context_hash,
|
||||
g_strdup (object_path),
|
||||
g_object_ref (context));
|
||||
g_signal_connect (context, "destroyed",
|
||||
G_CALLBACK(on_context_destroyed), client);
|
||||
return context;
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_async_ready_callback (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GVariant *result;
|
||||
|
||||
result = g_dbus_proxy_call_finish (G_DBUS_PROXY(source_object),
|
||||
res,
|
||||
&error);
|
||||
if (result)
|
||||
g_variant_unref (result);
|
||||
else {
|
||||
g_warning ("error in D-Bus proxy call: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_client_push_context:
|
||||
* @eekboard: an #EekboardClient
|
||||
* @context: an #EekboardContext
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Enable the input context @context and disable the others.
|
||||
*/
|
||||
void
|
||||
eekboard_client_push_context (EekboardClient *client,
|
||||
EekboardContext *context,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
const gchar *object_path;
|
||||
|
||||
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
|
||||
|
||||
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(context));
|
||||
|
||||
context = g_hash_table_lookup (priv->context_hash,
|
||||
object_path);
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
eekboard_context_set_enabled (context, TRUE);
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(client),
|
||||
"PushContext",
|
||||
g_variant_new ("(s)", object_path),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
eekboard_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_client_pop_context:
|
||||
* @eekboard: an #EekboardClient
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Disable the current input context and enable the previous one.
|
||||
*/
|
||||
void
|
||||
eekboard_client_pop_context (EekboardClient *client,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
|
||||
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(client),
|
||||
"PopContext",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
eekboard_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
eekboard_client_show_keyboard (EekboardClient *client,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
|
||||
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(client),
|
||||
"ShowKeyboard",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
eekboard_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
eekboard_client_hide_keyboard (EekboardClient *client,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
|
||||
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(client),
|
||||
"HideKeyboard",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
eekboard_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
send_destroy_context (EekboardClient *client,
|
||||
EekboardContext *context,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
const gchar *object_path;
|
||||
|
||||
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(context));
|
||||
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(client),
|
||||
"DestroyContext",
|
||||
g_variant_new ("(s)", object_path),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
eekboard_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_client_destroy_context:
|
||||
* @eekboard: an #EekboardClient
|
||||
* @context: an #EekboardContext
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Remove @context from @eekboard.
|
||||
*/
|
||||
void
|
||||
eekboard_client_destroy_context (EekboardClient *client,
|
||||
EekboardContext *context,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
const gchar *object_path;
|
||||
|
||||
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
|
||||
|
||||
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(context));
|
||||
g_hash_table_remove (priv->context_hash, object_path);
|
||||
|
||||
send_destroy_context (client, context, cancellable);
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef EEKBOARD_CLIENT_H
|
||||
#define EEKBOARD_CLIENT_H 1
|
||||
|
||||
#define __EEKBOARD_CLIENT_H_INSIDE__ 1
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include "eekboard/eekboard-context.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define EEKBOARD_TYPE_CLIENT (eekboard_client_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE (EekboardClient, eekboard_client, EEKBOARD, CLIENT, GDBusProxy)
|
||||
|
||||
struct _EekboardClientClass {
|
||||
/*< private >*/
|
||||
GDBusProxyClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (* destroyed) (EekboardClient *self);
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[23];
|
||||
};
|
||||
|
||||
GType eekboard_client_get_type (void) G_GNUC_CONST;
|
||||
|
||||
EekboardClient *eekboard_client_new (GDBusConnection *connection,
|
||||
GCancellable *cancellable);
|
||||
EekboardContext *eekboard_client_create_context (EekboardClient *eekboard,
|
||||
const gchar *client_name,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_client_push_context (EekboardClient *eekboard,
|
||||
EekboardContext *context,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_client_pop_context (EekboardClient *eekboard,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_client_show_keyboard (EekboardClient *eekboard,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_client_hide_keyboard (EekboardClient *eekboard,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_client_destroy_context (EekboardClient *eekboard,
|
||||
EekboardContext *context,
|
||||
GCancellable *cancellable);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEKBOARD_CLIENT_H */
|
||||
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 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
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "eekboard/eekboard-xklutil.h"
|
||||
|
||||
XklConfigRec *
|
||||
eekboard_xkl_config_rec_from_string (const gchar *layouts)
|
||||
{
|
||||
XklConfigRec *rec;
|
||||
gchar **strv, **l, **v;
|
||||
gint i;
|
||||
|
||||
strv = g_strsplit (layouts, "/", -1);
|
||||
g_return_val_if_fail (g_strv_length (strv) == 3, NULL);
|
||||
|
||||
l = g_strsplit (strv[1], ";", -1);
|
||||
v = g_strdupv (l);
|
||||
for (i = 0; l[i]; i++) {
|
||||
gchar *layout = l[i], *variant = v[i],
|
||||
*variant_start, *variant_end;
|
||||
|
||||
variant_start = strchr (layout, '(');
|
||||
variant_end = strrchr (layout, ')');
|
||||
if (variant_start && variant_end) {
|
||||
*variant_start++ = '\0';
|
||||
g_strlcpy (variant, variant_start,
|
||||
variant_end - variant_start + 1);
|
||||
} else
|
||||
*variant = '\0';
|
||||
}
|
||||
|
||||
rec = xkl_config_rec_new ();
|
||||
rec->model = g_strdup (strv[0]);
|
||||
rec->layouts = l;
|
||||
rec->variants = v;
|
||||
rec->options = g_strsplit (strv[2], ";", -1);
|
||||
g_strfreev (strv);
|
||||
|
||||
return rec;
|
||||
}
|
||||
|
||||
gchar *
|
||||
eekboard_xkl_config_rec_to_string (XklConfigRec *rec)
|
||||
{
|
||||
gchar **strv, **sp, **lp, **vp, *p;
|
||||
gint n_layouts;
|
||||
GString *str;
|
||||
|
||||
n_layouts = g_strv_length (rec->layouts);
|
||||
strv = g_malloc0_n (n_layouts + 2, sizeof (gchar *));
|
||||
for (sp = strv, lp = rec->layouts, vp = rec->variants; *lp; sp++, lp++) {
|
||||
if (*vp != NULL && **vp != '\0')
|
||||
*sp = g_strdup_printf ("%s(%s)", *lp, *vp++);
|
||||
else
|
||||
*sp = g_strdup_printf ("%s", *lp);
|
||||
}
|
||||
|
||||
/* MODEL/L0(V0);L1(V1);...;Ln(Vn)/O0;O1;...;On */
|
||||
str = g_string_new (rec->model);
|
||||
|
||||
g_string_append_c (str, '/');
|
||||
p = g_strjoinv (";", strv);
|
||||
g_strfreev (strv);
|
||||
g_string_append (str, p);
|
||||
g_free (p);
|
||||
|
||||
g_string_append_c (str, '/');
|
||||
p = g_strjoinv (";", rec->options);
|
||||
g_string_append (str, p);
|
||||
g_free (p);
|
||||
|
||||
return g_string_free (str,FALSE);
|
||||
}
|
||||
|
||||
static XklConfigItem *
|
||||
xkl_config_item_copy (const XklConfigItem *item)
|
||||
{
|
||||
XklConfigItem *_item = xkl_config_item_new ();
|
||||
memcpy (_item->name,
|
||||
item->name,
|
||||
sizeof (item->name));
|
||||
memcpy (_item->short_description,
|
||||
item->short_description,
|
||||
sizeof (item->short_description));
|
||||
memcpy (_item->description,
|
||||
item->description,
|
||||
sizeof (item->description));
|
||||
return _item;
|
||||
}
|
||||
|
||||
static void
|
||||
prepend_item (XklConfigRegistry *registry,
|
||||
const XklConfigItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GSList **list = data;
|
||||
XklConfigItem *_item = xkl_config_item_copy (item);
|
||||
*list = g_slist_prepend (*list, _item);
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_item_by_name (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const XklConfigItem *ia = a, *ib = b;
|
||||
return g_strcmp0 (ia->name, ib->name);
|
||||
}
|
||||
|
||||
GSList *
|
||||
eekboard_xkl_list_models (XklConfigRegistry *registry)
|
||||
{
|
||||
GSList *list = NULL;
|
||||
xkl_config_registry_foreach_model (registry, prepend_item, &list);
|
||||
return g_slist_sort (list, compare_item_by_name);
|
||||
}
|
||||
|
||||
GSList *
|
||||
eekboard_xkl_list_layouts (XklConfigRegistry *registry)
|
||||
{
|
||||
GSList *list = NULL;
|
||||
xkl_config_registry_foreach_layout (registry, prepend_item, &list);
|
||||
return g_slist_sort (list, compare_item_by_name);
|
||||
}
|
||||
|
||||
GSList *
|
||||
eekboard_xkl_list_option_groups (XklConfigRegistry *registry)
|
||||
{
|
||||
GSList *list = NULL;
|
||||
xkl_config_registry_foreach_option_group (registry, prepend_item, &list);
|
||||
return g_slist_sort (list, compare_item_by_name);
|
||||
}
|
||||
|
||||
GSList *
|
||||
eekboard_xkl_list_layout_variants (XklConfigRegistry *registry,
|
||||
const gchar *layout)
|
||||
{
|
||||
GSList *list = NULL;
|
||||
xkl_config_registry_foreach_layout_variant (registry,
|
||||
layout,
|
||||
prepend_item,
|
||||
&list);
|
||||
return g_slist_sort (list, compare_item_by_name);
|
||||
}
|
||||
|
||||
GSList *
|
||||
eekboard_xkl_list_options (XklConfigRegistry *registry,
|
||||
const gchar *group)
|
||||
{
|
||||
GSList *list = NULL;
|
||||
xkl_config_registry_foreach_option (registry, group, prepend_item, &list);
|
||||
return g_slist_sort (list, compare_item_by_name);
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 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
|
||||
*/
|
||||
#ifndef EEKBOARD_XKLUTIL_H
|
||||
#define EEKBOARD_XKLUTIL_H 1
|
||||
|
||||
#include <libxklavier/xklavier.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
XklConfigRec *eekboard_xkl_config_rec_from_string (const gchar *layouts);
|
||||
gchar *eekboard_xkl_config_rec_to_string (XklConfigRec *rec);
|
||||
|
||||
GSList *eekboard_xkl_list_models (XklConfigRegistry *registry);
|
||||
GSList *eekboard_xkl_list_layouts (XklConfigRegistry *registry);
|
||||
GSList *eekboard_xkl_list_option_groups (XklConfigRegistry *registry);
|
||||
GSList *eekboard_xkl_list_layout_variants (XklConfigRegistry *registry,
|
||||
const gchar *layout);
|
||||
GSList *eekboard_xkl_list_options (XklConfigRegistry *registry,
|
||||
const gchar *group);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEKBOARD_XKLUTIL_H */
|
||||
Reference in New Issue
Block a user