@ -124,9 +124,12 @@ libeek_gtk_la_LIBADD = libeek.la $(GTK_LIBS) $(LIBCANBERRA_LIBS)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
libeek_xkl_public_headers =			\
 | 
					libeek_xkl_public_headers =			\
 | 
				
			||||||
	$(srcdir)/eek-xkl-layout.h		\
 | 
						$(srcdir)/eek-xkl-layout.h		\
 | 
				
			||||||
	$(srcdir)/eek-xkl.h
 | 
						$(srcdir)/eek-xkl.h			\
 | 
				
			||||||
 | 
						$(srcdir)/eek-xkb-layout.h		\
 | 
				
			||||||
 | 
						$(srcdir)/eek-xkb.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libeek_xkl_sources =				\
 | 
					libeek_xkl_sources =				\
 | 
				
			||||||
 | 
						$(srcdir)/eek-xkb-layout.c		\
 | 
				
			||||||
	$(srcdir)/eek-xkl-layout.c
 | 
						$(srcdir)/eek-xkl-layout.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libeek_xkl_la_SOURCES = $(libeek_xkl_sources)
 | 
					libeek_xkl_la_SOURCES = $(libeek_xkl_sources)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										30
									
								
								eek/eek-xkb-0.90.pc.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								eek/eek-xkb-0.90.pc.in
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					# 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@
 | 
				
			||||||
							
								
								
									
										933
									
								
								eek/eek-xkb-layout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										933
									
								
								eek/eek-xkb-layout.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,933 @@
 | 
				
			|||||||
 | 
					/* 
 | 
				
			||||||
 | 
					 * 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 <X11/keysym.h>
 | 
				
			||||||
 | 
					#include <X11/XKBlib.h>
 | 
				
			||||||
 | 
					#include <X11/extensions/XKBgeom.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdarg.h>
 | 
				
			||||||
 | 
					#include <gio/gio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "eek-xkb-layout.h"
 | 
				
			||||||
 | 
					#include "eek-keyboard.h"
 | 
				
			||||||
 | 
					#include "eek-section.h"
 | 
				
			||||||
 | 
					#include "eek-key.h"
 | 
				
			||||||
 | 
					#include "eek-keysym.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define noKBDRAW_DEBUG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void initable_iface_init (GInitableIface *initable_iface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DEFINE_TYPE_WITH_CODE (EekXkbLayout, eek_xkb_layout, EEK_TYPE_LAYOUT,
 | 
				
			||||||
 | 
					                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
 | 
				
			||||||
 | 
					                                                initable_iface_init));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EEK_XKB_LAYOUT_GET_PRIVATE(obj)                                  \
 | 
				
			||||||
 | 
					    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_XKB_LAYOUT, EekXkbLayoutPrivate))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
					    PROP_0,
 | 
				
			||||||
 | 
					    PROP_DISPLAY,
 | 
				
			||||||
 | 
					    PROP_KEYCODES,
 | 
				
			||||||
 | 
					    PROP_GEOMETRY,
 | 
				
			||||||
 | 
					    PROP_SYMBOLS,
 | 
				
			||||||
 | 
					    PROP_LAST
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static guint
 | 
				
			||||||
 | 
					find_keycode (EekXkbLayout *layout, gchar *key_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					get_keyboard (EekXkbLayout *layout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					get_names (EekXkbLayout *layout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					setup_scaling (EekXkbLayout *layout,
 | 
				
			||||||
 | 
					               gdouble       width,
 | 
				
			||||||
 | 
					               gdouble       height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_INLINE_FUNC gint
 | 
				
			||||||
 | 
					xkb_to_pixmap_coord (EekXkbLayout *layout,
 | 
				
			||||||
 | 
					                     gint          n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = layout->priv;
 | 
				
			||||||
 | 
					    return n * priv->scale_numerator / priv->scale_denominator;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_INLINE_FUNC gdouble
 | 
				
			||||||
 | 
					xkb_to_pixmap_double (EekXkbLayout *layout,
 | 
				
			||||||
 | 
					                     gdouble       d)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = layout->priv;
 | 
				
			||||||
 | 
					    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 = layout->priv;
 | 
				
			||||||
 | 
					    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;
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    priv = layout->priv;
 | 
				
			||||||
 | 
					    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 = layout->priv;
 | 
				
			||||||
 | 
					    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 (EekLayout *self,
 | 
				
			||||||
 | 
					                                     gdouble    initial_width,
 | 
				
			||||||
 | 
					                                     gdouble    initial_height)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (self);
 | 
				
			||||||
 | 
					    EekBounds bounds;
 | 
				
			||||||
 | 
					    EekKeyboard *keyboard;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    keyboard = g_object_new (EEK_TYPE_KEYBOARD, "layout", self, NULL);
 | 
				
			||||||
 | 
					    bounds.x = bounds.y = 0.0;
 | 
				
			||||||
 | 
					    bounds.width = initial_width;
 | 
				
			||||||
 | 
					    bounds.height = initial_height;
 | 
				
			||||||
 | 
					    eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* resolve modifiers dynamically assigned at run time */
 | 
				
			||||||
 | 
					    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_PRIVATE (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);
 | 
				
			||||||
 | 
					    const gchar *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (prop_id) {
 | 
				
			||||||
 | 
					    case PROP_DISPLAY:
 | 
				
			||||||
 | 
					        layout->priv->display = g_value_get_pointer (value);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PROP_KEYCODES:
 | 
				
			||||||
 | 
					        name = g_value_get_string (value);
 | 
				
			||||||
 | 
					        eek_xkb_layout_set_keycodes (EEK_XKB_LAYOUT(object), name);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PROP_GEOMETRY:
 | 
				
			||||||
 | 
					        name = g_value_get_string (value);
 | 
				
			||||||
 | 
					        eek_xkb_layout_set_geometry (EEK_XKB_LAYOUT(object), name);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PROP_SYMBOLS:
 | 
				
			||||||
 | 
					        name = g_value_get_string (value);
 | 
				
			||||||
 | 
					        eek_xkb_layout_set_symbols (EEK_XKB_LAYOUT(object), name);
 | 
				
			||||||
 | 
					        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);
 | 
				
			||||||
 | 
					    const gchar *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (prop_id) {
 | 
				
			||||||
 | 
					    case PROP_DISPLAY:
 | 
				
			||||||
 | 
					        g_value_set_pointer (value, layout->priv->display);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PROP_KEYCODES:
 | 
				
			||||||
 | 
					        name = eek_xkb_layout_get_keycodes (EEK_XKB_LAYOUT(object));
 | 
				
			||||||
 | 
					        g_value_set_string (value, name);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PROP_GEOMETRY:
 | 
				
			||||||
 | 
					        name = eek_xkb_layout_get_geometry (EEK_XKB_LAYOUT(object));
 | 
				
			||||||
 | 
					        g_value_set_string (value, name);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case PROP_SYMBOLS:
 | 
				
			||||||
 | 
					        name = eek_xkb_layout_get_symbols (EEK_XKB_LAYOUT(object));
 | 
				
			||||||
 | 
					        g_value_set_string (value, name);
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_type_class_add_private (gobject_class, sizeof (EekXkbLayoutPrivate));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pspec = g_param_spec_string ("keycodes",
 | 
				
			||||||
 | 
									 "Keycodes",
 | 
				
			||||||
 | 
									 "XKB keycodes component name",
 | 
				
			||||||
 | 
									 NULL,
 | 
				
			||||||
 | 
									 G_PARAM_READWRITE);
 | 
				
			||||||
 | 
					    g_object_class_install_property (gobject_class, PROP_KEYCODES, pspec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pspec = g_param_spec_string ("geometry",
 | 
				
			||||||
 | 
					                                 "Geometry",
 | 
				
			||||||
 | 
					                                 "XKB geometry component name",
 | 
				
			||||||
 | 
					                                 NULL,
 | 
				
			||||||
 | 
					                                 G_PARAM_READWRITE);
 | 
				
			||||||
 | 
					    g_object_class_install_property (gobject_class, PROP_GEOMETRY, pspec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pspec = g_param_spec_string ("symbols",
 | 
				
			||||||
 | 
					                                 "Symbols",
 | 
				
			||||||
 | 
					                                 "XKB symbols component name",
 | 
				
			||||||
 | 
					                                 NULL,
 | 
				
			||||||
 | 
					                                 G_PARAM_READWRITE);
 | 
				
			||||||
 | 
					    g_object_class_install_property (gobject_class, PROP_SYMBOLS, pspec);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					eek_xkb_layout_init (EekXkbLayout *self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    self->priv = EEK_XKB_LAYOUT_GET_PRIVATE (self);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					get_names (EekXkbLayout *layout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = layout->priv;
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Set the XKB component names to @layout.
 | 
				
			||||||
 | 
					 * Returns: %TRUE if any of the component names changed, %FALSE otherwise
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					eek_xkb_layout_set_names (EekXkbLayout *layout, XkbComponentNamesRec *names)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 | 
				
			||||||
 | 
					    gboolean retval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_return_val_if_fail (priv, FALSE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (g_strcmp0 (names->keycodes, priv->names.keycodes)) {
 | 
				
			||||||
 | 
					        g_free (priv->names.keycodes);
 | 
				
			||||||
 | 
					        priv->names.keycodes = g_strdup (names->keycodes);
 | 
				
			||||||
 | 
					        retval = TRUE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (g_strcmp0 (names->geometry, priv->names.geometry)) {
 | 
				
			||||||
 | 
					        g_free (priv->names.geometry);
 | 
				
			||||||
 | 
					        priv->names.geometry = g_strdup (names->geometry);
 | 
				
			||||||
 | 
					        retval = TRUE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (g_strcmp0 (names->symbols, priv->names.symbols)) {
 | 
				
			||||||
 | 
					        g_free (priv->names.symbols);
 | 
				
			||||||
 | 
					        priv->names.symbols = g_strdup (names->symbols);
 | 
				
			||||||
 | 
					        retval = TRUE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get_keyboard (layout);
 | 
				
			||||||
 | 
					    g_assert (priv->xkb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return retval;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * eek_xkb_layout_set_names_full:
 | 
				
			||||||
 | 
					 * @layout: an #EekXkbLayout
 | 
				
			||||||
 | 
					 * @Varargs: pairs of component name and value, terminated by NULL.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Set the XKB component names to @layout.  This function is merely a
 | 
				
			||||||
 | 
					 * wrapper around eek_xkb_layout_set_names() to avoid passing a
 | 
				
			||||||
 | 
					 * pointer of XkbComponentNamesRec, which is not currently available
 | 
				
			||||||
 | 
					 * in the gobject-introspection repository.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Available component names are: keymap, keycodes, types, compat,
 | 
				
			||||||
 | 
					 * symbols, geometry.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: %TRUE if the component name is successfully set, %FALSE otherwise
 | 
				
			||||||
 | 
					 * Since: 0.0.2
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					eek_xkb_layout_set_names_full (EekXkbLayout *layout,
 | 
				
			||||||
 | 
					                               ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    va_list var_args;
 | 
				
			||||||
 | 
					    gboolean retval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    va_start (var_args, layout);
 | 
				
			||||||
 | 
					    retval = eek_xkb_layout_set_names_full_valist (layout, var_args);
 | 
				
			||||||
 | 
					    va_end (var_args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return retval;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * eek_xkb_layout_set_names_full_valist:
 | 
				
			||||||
 | 
					 * @layout: an #EekXkbLayout
 | 
				
			||||||
 | 
					 * @var_args: <type>va_list</type> of pairs of component name and value.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See eek_xkb_layout_set_names_full(), this version takes a
 | 
				
			||||||
 | 
					 * <type>va_list</type> for language bindings to use.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Since: 0.0.5
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					eek_xkb_layout_set_names_full_valist (EekXkbLayout *layout,
 | 
				
			||||||
 | 
					                                      va_list       var_args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XkbComponentNamesRec names;
 | 
				
			||||||
 | 
					    gchar *name, *value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset (&names, 0, sizeof names);
 | 
				
			||||||
 | 
					    name = va_arg (var_args, gchar *);
 | 
				
			||||||
 | 
					    while (name) {
 | 
				
			||||||
 | 
					        value = va_arg (var_args, gchar *);
 | 
				
			||||||
 | 
					        if (g_strcmp0 (name, "keymap") == 0)
 | 
				
			||||||
 | 
					            names.keymap = (char *)value;
 | 
				
			||||||
 | 
					        else if (g_strcmp0 (name, "keycodes") == 0)
 | 
				
			||||||
 | 
					            names.keycodes = (char *)value;
 | 
				
			||||||
 | 
					        else if (g_strcmp0 (name, "types") == 0)
 | 
				
			||||||
 | 
					            names.types = (char *)value;
 | 
				
			||||||
 | 
					        else if (g_strcmp0 (name, "compat") == 0)
 | 
				
			||||||
 | 
					            names.compat = (char *)value;
 | 
				
			||||||
 | 
					        else if (g_strcmp0 (name, "symbols") == 0)
 | 
				
			||||||
 | 
					            names.symbols = (char *)value;
 | 
				
			||||||
 | 
					        else if (g_strcmp0 (name, "geometry") == 0)
 | 
				
			||||||
 | 
					            names.geometry = (char *)value;
 | 
				
			||||||
 | 
					        name = va_arg (var_args, gchar *);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return eek_xkb_layout_set_names (layout, &names);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * eek_xkb_layout_set_keycodes:
 | 
				
			||||||
 | 
					 * @layout: an #EekXkbLayout
 | 
				
			||||||
 | 
					 * @keycodes: component name for keycodes
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Set the keycodes component (in the XKB terminology).
 | 
				
			||||||
 | 
					 * Returns: %TRUE if the component name is successfully set, %FALSE otherwise
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					eek_xkb_layout_set_keycodes (EekXkbLayout *layout, const gchar *keycodes)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 | 
				
			||||||
 | 
					    XkbComponentNamesRec names;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_return_val_if_fail (priv, FALSE);
 | 
				
			||||||
 | 
					    memcpy (&names, &priv->names, sizeof names);
 | 
				
			||||||
 | 
					    names.keycodes = (gchar *)keycodes;
 | 
				
			||||||
 | 
					    return eek_xkb_layout_set_names (layout, &names);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * eek_xkb_layout_set_geometry:
 | 
				
			||||||
 | 
					 * @layout: an #EekXkbLayout
 | 
				
			||||||
 | 
					 * @geometry: component name for geometry
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: %TRUE if the component name is successfully set, %FALSE otherwise
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					eek_xkb_layout_set_geometry (EekXkbLayout *layout, const gchar *geometry)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 | 
				
			||||||
 | 
					    XkbComponentNamesRec names;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_return_val_if_fail (priv, FALSE);
 | 
				
			||||||
 | 
					    memcpy (&names, &priv->names, sizeof names);
 | 
				
			||||||
 | 
					    names.geometry = (gchar *)geometry;
 | 
				
			||||||
 | 
					    return eek_xkb_layout_set_names (layout, &names);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * eek_xkb_layout_set_symbols:
 | 
				
			||||||
 | 
					 * @layout: an #EekXkbLayout
 | 
				
			||||||
 | 
					 * @symbols: component name for symbols
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Set the symbols component (in the XKB terminology).
 | 
				
			||||||
 | 
					 * Returns: %TRUE if the component name is successfully set, %FALSE otherwise
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					eek_xkb_layout_set_symbols (EekXkbLayout *layout, const gchar *symbols)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 | 
				
			||||||
 | 
					    XkbComponentNamesRec names;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_return_val_if_fail (priv, FALSE);
 | 
				
			||||||
 | 
					    memcpy (&names, &priv->names, sizeof names);
 | 
				
			||||||
 | 
					    names.symbols = (gchar *)symbols;
 | 
				
			||||||
 | 
					    return eek_xkb_layout_set_names (layout, &names);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * eek_xkb_layout_get_keycodes:
 | 
				
			||||||
 | 
					 * @layout: an #EekXkbLayout
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Get the keycodes component name (in the XKB terminology).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const gchar *
 | 
				
			||||||
 | 
					eek_xkb_layout_get_keycodes (EekXkbLayout *layout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_return_val_if_fail (priv, NULL);
 | 
				
			||||||
 | 
					    return priv->names.keycodes;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * eek_xkb_layout_get_geometry:
 | 
				
			||||||
 | 
					 * @layout: an #EekXkbLayout
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Get the geometry component name (in the XKB terminology).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const gchar *
 | 
				
			||||||
 | 
					eek_xkb_layout_get_geometry (EekXkbLayout *layout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_return_val_if_fail (priv, NULL);
 | 
				
			||||||
 | 
					    return priv->names.geometry;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * eek_xkb_layout_get_symbols:
 | 
				
			||||||
 | 
					 * @layout: an #EekXkbLayout
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Get the symbols component name (in the XKB terminology).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const gchar *
 | 
				
			||||||
 | 
					eek_xkb_layout_get_symbols (EekXkbLayout *layout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_return_val_if_fail (priv, NULL);
 | 
				
			||||||
 | 
					    return priv->names.symbols;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					get_keyboard (EekXkbLayout *layout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = layout->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (priv->xkb)
 | 
				
			||||||
 | 
					        XkbFreeKeyboard (priv->xkb, 0, TRUE);	/* free_all = TRUE */
 | 
				
			||||||
 | 
					    priv->xkb = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (priv->names.keycodes &&
 | 
				
			||||||
 | 
					        priv->names.geometry &&
 | 
				
			||||||
 | 
					        priv->names.symbols) {
 | 
				
			||||||
 | 
					        priv->xkb = XkbGetKeyboardByName (priv->display, XkbUseCoreKbd,
 | 
				
			||||||
 | 
					                                          &priv->names, 0,
 | 
				
			||||||
 | 
					                                          XkbGBN_GeometryMask |
 | 
				
			||||||
 | 
					                                          XkbGBN_KeyNamesMask |
 | 
				
			||||||
 | 
					                                          XkbGBN_OtherNamesMask |
 | 
				
			||||||
 | 
					                                          XkbGBN_ClientSymbolsMask |
 | 
				
			||||||
 | 
					                                          XkbGBN_IndicatorMapMask, FALSE);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        priv->xkb = XkbGetKeyboard (priv->display,
 | 
				
			||||||
 | 
					                                    XkbGBN_GeometryMask |
 | 
				
			||||||
 | 
					                                    XkbGBN_KeyNamesMask |
 | 
				
			||||||
 | 
					                                    XkbGBN_OtherNamesMask |
 | 
				
			||||||
 | 
					                                    XkbGBN_SymbolsMask |
 | 
				
			||||||
 | 
					                                    XkbGBN_IndicatorMapMask,
 | 
				
			||||||
 | 
					                                    XkbUseCoreKbd);
 | 
				
			||||||
 | 
					        get_names (layout);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (priv->xkb == NULL) {
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 = layout->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!priv->xkb)
 | 
				
			||||||
 | 
					        return EEK_INVALID_KEYCODE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef KBDRAW_DEBUG
 | 
				
			||||||
 | 
					    printf ("    looking for keycode for (%c%c%c%c)\n",
 | 
				
			||||||
 | 
					            key_name[0], key_name[1], key_name[2], key_name[3]);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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) {
 | 
				
			||||||
 | 
					#ifdef KBDRAW_DEBUG
 | 
				
			||||||
 | 
					            printf ("      found keycode %u\n", keycode);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					            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);
 | 
				
			||||||
 | 
					#ifdef KBDRAW_DEBUG
 | 
				
			||||||
 | 
					            printf ("found alias keycode %u\n", keycode);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					            return keycode;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        palias++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return EEK_INVALID_KEYCODE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					setup_scaling (EekXkbLayout *layout,
 | 
				
			||||||
 | 
					               gdouble       width,
 | 
				
			||||||
 | 
					               gdouble       height)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv = layout->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* XXX: XkbClientMapMask | XkbIndicatorMapMask | XkbNamesMask |
 | 
				
			||||||
 | 
					       XkbGeometryMask */
 | 
				
			||||||
 | 
					    layout->priv->xkb = XkbGetKeyboard (layout->priv->display,
 | 
				
			||||||
 | 
					                                        XkbGBN_GeometryMask |
 | 
				
			||||||
 | 
					                                        XkbGBN_KeyNamesMask |
 | 
				
			||||||
 | 
					                                        XkbGBN_OtherNamesMask |
 | 
				
			||||||
 | 
					                                        XkbGBN_SymbolsMask |
 | 
				
			||||||
 | 
					                                        XkbGBN_IndicatorMapMask,
 | 
				
			||||||
 | 
					                                        XkbUseCoreKbd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (layout->priv->xkb == NULL) {
 | 
				
			||||||
 | 
					        g_set_error (error,
 | 
				
			||||||
 | 
					                     EEK_ERROR,
 | 
				
			||||||
 | 
					                     EEK_ERROR_LAYOUT_ERROR,
 | 
				
			||||||
 | 
					                     "can't get initial XKB keyboard configuration");
 | 
				
			||||||
 | 
					        return FALSE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get_names (layout);
 | 
				
			||||||
 | 
					    get_keyboard (layout);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (layout->priv->xkb == NULL) {
 | 
				
			||||||
 | 
					        g_set_error (error,
 | 
				
			||||||
 | 
					                     EEK_ERROR,
 | 
				
			||||||
 | 
					                     EEK_ERROR_LAYOUT_ERROR,
 | 
				
			||||||
 | 
					                     "can't get XKB keyboard configuration");
 | 
				
			||||||
 | 
					        return FALSE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					initable_iface_init (GInitableIface *initable_iface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  initable_iface->init = initable_init;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										88
									
								
								eek/eek-xkb-layout.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								eek/eek-xkb-layout.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					/* 
 | 
				
			||||||
 | 
					 * 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/Xlib.h>
 | 
				
			||||||
 | 
					#include <X11/XKBlib.h>
 | 
				
			||||||
 | 
					#include "eek-layout.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EEK_TYPE_XKB_LAYOUT (eek_xkb_layout_get_type())
 | 
				
			||||||
 | 
					#define EEK_XKB_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_XKB_LAYOUT, EekXkbLayout))
 | 
				
			||||||
 | 
					#define EEK_XKB_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_XKB_LAYOUT, EekXkbLayoutClass))
 | 
				
			||||||
 | 
					#define EEK_IS_XKB_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_XKB_LAYOUT))
 | 
				
			||||||
 | 
					#define EEK_IS_XKB_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_XKB_LAYOUT))
 | 
				
			||||||
 | 
					#define EEK_XKB_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_XKB_LAYOUT, EekXkbLayoutClass))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct _EekXkbLayout        EekXkbLayout;
 | 
				
			||||||
 | 
					typedef struct _EekXkbLayoutClass   EekXkbLayoutClass;
 | 
				
			||||||
 | 
					typedef struct _EekXkbLayoutPrivate EekXkbLayoutPrivate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct _EekXkbLayout
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /*< private >*/
 | 
				
			||||||
 | 
					    EekLayout parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    EekXkbLayoutPrivate *priv;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean     eek_xkb_layout_set_names_full (EekXkbLayout         *layout,
 | 
				
			||||||
 | 
					                                            ...);
 | 
				
			||||||
 | 
					gboolean     eek_xkb_layout_set_names_full_valist
 | 
				
			||||||
 | 
					                                           (EekXkbLayout         *layout,
 | 
				
			||||||
 | 
					                                            va_list               var_args);
 | 
				
			||||||
 | 
					                                        
 | 
				
			||||||
 | 
					gboolean     eek_xkb_layout_set_keycodes   (EekXkbLayout         *layout,
 | 
				
			||||||
 | 
					                                            const gchar          *keycodes);
 | 
				
			||||||
 | 
					gboolean     eek_xkb_layout_set_geometry   (EekXkbLayout         *layout,
 | 
				
			||||||
 | 
					                                            const gchar          *geometry);
 | 
				
			||||||
 | 
					gboolean     eek_xkb_layout_set_symbols    (EekXkbLayout         *layout,
 | 
				
			||||||
 | 
					                                            const gchar          *symbols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const gchar *eek_xkb_layout_get_keycodes   (EekXkbLayout         *layout);
 | 
				
			||||||
 | 
					const gchar *eek_xkb_layout_get_geometry   (EekXkbLayout         *layout);
 | 
				
			||||||
 | 
					const gchar *eek_xkb_layout_get_symbols    (EekXkbLayout         *layout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_END_DECLS
 | 
				
			||||||
 | 
					#endif				/* #ifndef EEK_XKB_LAYOUT_H */
 | 
				
			||||||
							
								
								
									
										26
									
								
								eek/eek-xkb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								eek/eek-xkb.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					/* 
 | 
				
			||||||
 | 
					 * 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 */
 | 
				
			||||||
@ -42,7 +42,7 @@ static GInitableIface *parent_initable_iface;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void initable_iface_init (GInitableIface *initable_iface);
 | 
					static void initable_iface_init (GInitableIface *initable_iface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_DEFINE_TYPE_WITH_CODE (EekXklLayout, eek_xkl_layout, EEK_TYPE_LAYOUT,
 | 
					G_DEFINE_TYPE_WITH_CODE (EekXklLayout, eek_xkl_layout, EEK_TYPE_XKB_LAYOUT,
 | 
				
			||||||
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
 | 
					                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
 | 
				
			||||||
                                                initable_iface_init));
 | 
					                                                initable_iface_init));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,6 +64,22 @@ struct _EekXklLayoutPrivate
 | 
				
			|||||||
    XklConfigRec *config;
 | 
					    XklConfigRec *config;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 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
 | 
					static void
 | 
				
			||||||
eek_xkl_layout_dispose (GObject *object)
 | 
					eek_xkl_layout_dispose (GObject *object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -258,7 +274,7 @@ eek_xkl_layout_set_config (EekXklLayout *layout,
 | 
				
			|||||||
    c = xkl_config_rec_new ();
 | 
					    c = xkl_config_rec_new ();
 | 
				
			||||||
    merge_xkl_config_rec (c, priv->config);
 | 
					    merge_xkl_config_rec (c, priv->config);
 | 
				
			||||||
    merge_xkl_config_rec (c, config);
 | 
					    merge_xkl_config_rec (c, config);
 | 
				
			||||||
    retval = xkl_config_rec_activate (c, priv->engine);
 | 
					    retval = set_xkb_component_names (layout, c);
 | 
				
			||||||
    g_object_unref (c);
 | 
					    g_object_unref (c);
 | 
				
			||||||
    merge_xkl_config_rec (priv->config, config);
 | 
					    merge_xkl_config_rec (priv->config, config);
 | 
				
			||||||
    return retval;
 | 
					    return retval;
 | 
				
			||||||
@ -535,6 +551,50 @@ eek_xkl_layout_get_options (EekXklLayout *layout)
 | 
				
			|||||||
    return g_strdupv (priv->config->options);
 | 
					    return g_strdupv (priv->config->options);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static gboolean
 | 
				
			||||||
 | 
					set_xkb_component_names (EekXklLayout *layout, XklConfigRec *config)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekXklLayoutPrivate *priv = layout->priv;
 | 
				
			||||||
 | 
					    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)) {
 | 
				
			||||||
 | 
					        retval = eek_xkb_layout_set_names (EEK_XKB_LAYOUT(layout), &names);
 | 
				
			||||||
 | 
					        xkl_xkb_config_native_cleanup (priv->engine, &names);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return retval;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * eek_xkl_layout_get_option:
 | 
					 * eek_xkl_layout_get_option:
 | 
				
			||||||
 * @layout: an #EekXklLayout
 | 
					 * @layout: an #EekXklLayout
 | 
				
			||||||
@ -585,7 +645,7 @@ initable_init (GInitable    *initable,
 | 
				
			|||||||
        return FALSE;
 | 
					        return FALSE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    xkl_config_rec_activate (layout->priv->config, layout->priv->engine);
 | 
					    set_xkb_component_names (layout, layout->priv->config);
 | 
				
			||||||
    return TRUE;
 | 
					    return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,7 @@
 | 
				
			|||||||
#define EEK_XKL_LAYOUT_H 1
 | 
					#define EEK_XKL_LAYOUT_H 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <libxklavier/xklavier.h>
 | 
					#include <libxklavier/xklavier.h>
 | 
				
			||||||
#include "eek-layout.h"
 | 
					#include "eek-xkb-layout.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_BEGIN_DECLS
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -44,7 +44,7 @@ typedef struct _EekXklLayoutPrivate EekXklLayoutPrivate;
 | 
				
			|||||||
struct _EekXklLayout
 | 
					struct _EekXklLayout
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /*< private >*/
 | 
					    /*< private >*/
 | 
				
			||||||
    EekLayout parent;
 | 
					    EekXkbLayout parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EekXklLayoutPrivate *priv;
 | 
					    EekXklLayoutPrivate *priv;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -52,7 +52,7 @@ struct _EekXklLayout
 | 
				
			|||||||
struct _EekXklLayoutClass
 | 
					struct _EekXklLayoutClass
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /*< private >*/
 | 
					    /*< private >*/
 | 
				
			||||||
    EekLayoutClass parent_class;
 | 
					    EekXkbLayoutClass parent_class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*< private >*/
 | 
					    /*< private >*/
 | 
				
			||||||
    /* padding */
 | 
					    /* padding */
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user