diff --git a/configure.ac b/configure.ac
index 333d89b2..eb6910d3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -35,9 +35,11 @@ PKG_CHECK_MODULES([PANGO], [pango], ,
 PKG_CHECK_MODULES([CLUTTER], [clutter-1.0], ,
   [AC_MSG_ERROR([Clutter not found])])
 PKG_CHECK_MODULES([GTK2], [gtk+-2.0 gdk-2.0], ,
-  [AC_MSG_ERROR([GTK2 support not found])])
+  [AC_MSG_ERROR([GTK2 not found])])
 PKG_CHECK_MODULES([XKB], [x11], ,
   [AC_MSG_ERROR([XKB support not found])])
+PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier x11], ,
+  [AC_MSG_ERROR([Libxklavier not found])])
 
 GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
 
@@ -56,5 +58,6 @@ docs/reference/Makefile
 docs/reference/eek/Makefile
 eek/eek.pc
 eek/eek-clutter.pc
-eek/eek-xkb.pc])
+eek/eek-xkb.pc
+eek/eek-xkl.pc])
 AC_OUTPUT
diff --git a/docs/reference/eek/eek-docs.sgml b/docs/reference/eek/eek-docs.sgml
index de2970a1..1faf9a3e 100644
--- a/docs/reference/eek/eek-docs.sgml
+++ b/docs/reference/eek/eek-docs.sgml
@@ -32,6 +32,10 @@
     
XKB layout engine
     
   
+  
+    Libxklavier layout engine
+    
+  
   
     Object Hierarchy
      
diff --git a/eek/Makefile.am b/eek/Makefile.am
index eaa8db9b..7192cf9c 100644
--- a/eek/Makefile.am
+++ b/eek/Makefile.am
@@ -16,7 +16,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301 USA
 
-lib_LTLIBRARIES = libeek.la libeek-clutter.la libeek-xkb.la
+lib_LTLIBRARIES = libeek.la libeek-clutter.la libeek-xkb.la libeek-xkl.la
 
 libeek_la_SOURCES = \
 	eek-layout.c \
@@ -66,6 +66,14 @@ libeek_xkb_la_SOURCES = \
 libeek_xkb_la_CFLAGS = $(GTK2_CFLAGS) $(XKB_CFLAGS)
 libeek_xkb_la_LIBADD = libeek.la $(GTK2_LIBS) $(XKB_LIBS)
 
+libeek_xkl_la_SOURCES = \
+	eek-xkl-layout.h \
+	eek-xkl-layout.c \
+	$(NULL)
+
+libeek_xkl_la_CFLAGS = $(GTK2_CFLAGS) $(LIBXKLAVIER_CFLAGS)
+libeek_xkl_la_LIBADD = libeek-xkb.la $(GTK2_LIBS) $(LIBXKLAVIER_LIBS)
+
 eekdir = $(includedir)/eek-$(EEK_API_VERSION)/eek
 eek_HEADERS = \
 	$(top_srcdir)/eek/eek-element.h \
@@ -80,9 +88,11 @@ eek_HEADERS = \
 	$(top_srcdir)/eek/eek-clutter-section.h \
 	$(top_srcdir)/eek/eek-clutter-key.h \
 	$(top_srcdir)/eek/eek-xkb-layout.h \
+	$(top_srcdir)/eek/eek-xkl-layout.h \
 	$(top_srcdir)/eek/eek.h \
 	$(top_srcdir)/eek/eek-clutter.h \
-	$(top_srcdir)/eek/eek-xkb.h
+	$(top_srcdir)/eek/eek-xkb.h \
+	$(top_srcdir)/eek/eek-xkl.h
 
 eek-keysym.c: eek-special-keysym-labels.h eek-unicode-keysym-labels.h eek-keyname-keysym-labels.h
 
@@ -94,7 +104,7 @@ eek-keyname-keysym-labels.h: keyname-keysym-labels.txt
 	$(PYTHON) ./gen-keysym-labels.py keyname_keysym_labels < $< > $@
 
 pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = eek.pc eek-clutter.pc eek-xkb.pc
+pkgconfig_DATA = eek.pc eek-clutter.pc eek-xkb.pc eek-xkl.pc
 
 DISTCLEANFILES = \
 	eek-special-keysym-labels.h \
diff --git a/eek/eek-clutter-key-actor.c b/eek/eek-clutter-key-actor.c
index 080e5fd8..db3975fc 100644
--- a/eek/eek-clutter-key-actor.c
+++ b/eek/eek-clutter-key-actor.c
@@ -35,6 +35,14 @@
 
 #define noKBDRAW_DEBUG
 
+enum {
+    PRESSED,
+    RELEASED,
+    LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
 G_DEFINE_TYPE (EekClutterKeyActor, eek_clutter_key_actor,
                CLUTTER_TYPE_GROUP);
 
@@ -47,12 +55,20 @@ struct _EekClutterKeyActorPrivate
     ClutterActor *texture;
 };
 
+static struct {
+    /* outline pointer -> ClutterTexture */
+    GHashTable *outline_textures;
+    gint outline_textures_ref_count;
+} texture_cache;
+
 static gboolean      on_event           (ClutterActor       *actor,
                                          ClutterEvent       *event,
                                          gpointer            user_data);
 static ClutterActor *get_texture        (EekClutterKeyActor *actor);
 static void          draw_key_on_layout (EekKey             *key,
                                          PangoLayout        *layout);
+static void          key_enlarge        (ClutterActor       *actor);
+static void          key_shrink         (ClutterActor       *actor);
 
 static void
 eek_clutter_key_actor_real_paint (ClutterActor *self)
@@ -119,11 +135,46 @@ eek_clutter_key_actor_real_get_preferred_width (ClutterActor *self,
         get_preferred_width (self, for_height, min_width_p, natural_width_p);
 }
 
+static void
+eek_clutter_key_actor_real_pressed (EekClutterKeyActor *self)
+{
+    ClutterActor *actor, *section;
+
+    actor = CLUTTER_ACTOR(self);
+
+    /* Make sure the enlarged key show up on the keys which belong
+       to other sections. */
+    section = clutter_actor_get_parent (actor);
+    clutter_actor_raise_top (section);
+    clutter_actor_raise_top (actor);
+    key_enlarge (actor);
+}
+
+static void
+eek_clutter_key_actor_real_released (EekClutterKeyActor *self)
+{
+    ClutterActor *actor, *section;
+
+    actor = CLUTTER_ACTOR(self);
+
+    /* Make sure the enlarged key show up on the keys which belong
+       to other sections. */
+    section = clutter_actor_get_parent (actor);
+    clutter_actor_raise_top (section);
+    clutter_actor_raise_top (actor);
+    key_shrink (actor);
+}
+
 static void
 eek_clutter_key_actor_finalize (GObject *object)
 {
     EekClutterKeyActorPrivate *priv = EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(object);
+
     g_object_unref (priv->key);
+    if (priv->texture && --texture_cache.outline_textures_ref_count <= 0) {
+        g_hash_table_unref (texture_cache.outline_textures);
+        texture_cache.outline_textures = NULL;
+    }
     G_OBJECT_CLASS (eek_clutter_key_actor_parent_class)->finalize (object);
 }
 
@@ -145,6 +196,54 @@ eek_clutter_key_actor_class_init (EekClutterKeyActorClass *klass)
         eek_clutter_key_actor_real_get_preferred_width;
 
     gobject_class->finalize = eek_clutter_key_actor_finalize;
+
+    /* signals */
+    klass->pressed = eek_clutter_key_actor_real_pressed;
+    klass->released = eek_clutter_key_actor_real_released;
+
+    signals[PRESSED] =
+        g_signal_new ("pressed",
+                      G_TYPE_FROM_CLASS(gobject_class),
+                      G_SIGNAL_RUN_FIRST,
+                      G_STRUCT_OFFSET(EekClutterKeyActorClass, pressed),
+                      NULL,
+                      NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0);
+
+    signals[RELEASED] =
+        g_signal_new ("released",
+                      G_TYPE_FROM_CLASS(gobject_class),
+                      G_SIGNAL_RUN_FIRST,
+                      G_STRUCT_OFFSET(EekClutterKeyActorClass, released),
+                      NULL,
+                      NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0);
+}
+
+static void
+on_button_press_event (ClutterActor *actor,
+                       ClutterEvent *event,
+                       gpointer user_data)
+{
+    EekClutterKeyActorPrivate *priv =
+        EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(actor);
+
+    /* priv->key will send back PRESSED event of actor. */
+    g_signal_emit_by_name (priv->key, "pressed");
+}
+
+static void
+on_button_release_event (ClutterActor *actor,
+                         ClutterEvent *event,
+                         gpointer      user_data)
+{
+    EekClutterKeyActorPrivate *priv =
+        EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(actor);
+
+    /* priv->key will send back RELEASED event of actor. */
+    g_signal_emit_by_name (priv->key, "released");
 }
 
 static void
@@ -156,7 +255,10 @@ eek_clutter_key_actor_init (EekClutterKeyActor *self)
     priv->key = NULL;
     priv->texture = NULL;
     clutter_actor_set_reactive (CLUTTER_ACTOR(self), TRUE);
-    g_signal_connect (self, "event", G_CALLBACK (on_event), NULL);
+    g_signal_connect (self, "button-press-event",
+                      G_CALLBACK (on_button_press_event), NULL);
+    g_signal_connect (self, "button-release-event",
+                      G_CALLBACK (on_button_release_event), NULL);
 }
 
 ClutterActor *
@@ -166,7 +268,7 @@ eek_clutter_key_actor_new (EekKey *key)
 
     actor = g_object_new (EEK_TYPE_CLUTTER_KEY_ACTOR, NULL);
     actor->priv->key = key;
-    g_object_ref (actor->priv->key);
+    g_object_ref_sink (actor->priv->key);
     return CLUTTER_ACTOR(actor);
 }
 
@@ -479,23 +581,22 @@ create_texture_for_key (EekKey *key)
 static ClutterActor *
 get_texture (EekClutterKeyActor *actor)
 {
-    EekClutterKeyActorClass *actor_class =
-        EEK_CLUTTER_KEY_ACTOR_GET_CLASS(actor);
     ClutterActor *texture;
     EekOutline *outline;
 
-    if (!actor_class->outline_textures)
-        actor_class->outline_textures = g_hash_table_new_full (g_direct_hash,
-                                                               g_direct_equal,
-                                                               NULL,
-                                                               g_free);
+    if (!texture_cache.outline_textures)
+        texture_cache.outline_textures = g_hash_table_new_full (g_direct_hash,
+                                                                g_direct_equal,
+                                                                NULL,
+                                                                g_free);
     outline = eek_key_get_outline (actor->priv->key);
-    texture = g_hash_table_lookup (actor_class->outline_textures, outline);
+    texture = g_hash_table_lookup (texture_cache.outline_textures, outline);
     if (texture == NULL) {
         texture = create_texture_for_key (actor->priv->key);
-        g_hash_table_insert (actor_class->outline_textures, outline, texture);
+        g_hash_table_insert (texture_cache.outline_textures, outline, texture);
     } else
         texture = clutter_clone_new (texture);
+    texture_cache.outline_textures_ref_count++;
     return texture;
 }
 
diff --git a/eek/eek-clutter-key-actor.h b/eek/eek-clutter-key-actor.h
index 110f7110..7f1bf77d 100644
--- a/eek/eek-clutter-key-actor.h
+++ b/eek/eek-clutter-key-actor.h
@@ -49,8 +49,9 @@ struct _EekClutterKeyActorClass
     /*< private >*/
     ClutterGroupClass parent_class;
 
-    /* outline pointer -> ClutterTexture */
-    GHashTable *outline_textures;
+    /* signals */
+    void (* pressed) (EekClutterKeyActor *self);
+    void (* released) (EekClutterKeyActor *self);
 };
 
 GType eek_clutter_key_actor_get_type (void) G_GNUC_CONST;
diff --git a/eek/eek-clutter-key.c b/eek/eek-clutter-key.c
index b1048c48..4df65d3f 100644
--- a/eek/eek-clutter-key.c
+++ b/eek/eek-clutter-key.c
@@ -68,13 +68,29 @@ eek_clutter_key_real_set_bounds (EekElement *self,
     clutter_actor_set_size (priv->actor, bounds->width, bounds->height);
 }
 
+static void
+eek_clutter_key_real_pressed (EekKey *key)
+{
+    EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(key);
+
+    if (priv->actor)
+        g_signal_emit_by_name (priv->actor, "pressed");
+}
+
+static void
+eek_clutter_key_real_released (EekKey *key)
+{
+    EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(key);
+
+    if (priv->actor)
+        g_signal_emit_by_name (priv->actor, "released");
+}
+
 static void
 eek_clutter_key_finalize (GObject *object)
 {
     EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(object);
 
-    /* No need for clutter_group_remove_all() since
-       ClutterGroup#dispose() unrefs all the children. */
     if (priv->actor)
         g_object_unref (priv->actor);
     G_OBJECT_CLASS (eek_clutter_key_parent_class)->finalize (object);
@@ -85,6 +101,7 @@ eek_clutter_key_class_init (EekClutterKeyClass *klass)
 {
     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     EekElementClass *element_class = EEK_ELEMENT_CLASS (klass);
+    EekKeyClass *key_class = EEK_KEY_CLASS (klass);
 
     g_type_class_add_private (gobject_class,
                               sizeof (EekClutterKeyPrivate));
@@ -92,6 +109,10 @@ eek_clutter_key_class_init (EekClutterKeyClass *klass)
     element_class->set_name = eek_clutter_key_real_set_name;
     element_class->set_bounds = eek_clutter_key_real_set_bounds;
     gobject_class->finalize = eek_clutter_key_finalize;
+
+    /* signals */
+    key_class->pressed = eek_clutter_key_real_pressed;
+    key_class->released = eek_clutter_key_real_released;
 }
 
 static void
@@ -106,7 +127,9 @@ ClutterActor *
 eek_clutter_key_get_actor (EekClutterKey *key)
 {
     EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(key);
-    if (!priv->actor)
+    if (!priv->actor) {
         priv->actor = eek_clutter_key_actor_new (EEK_KEY(key));
+        g_object_ref_sink (priv->actor);
+    }
     return priv->actor;
 }
diff --git a/eek/eek-clutter-keyboard.c b/eek/eek-clutter-keyboard.c
index 06885a9b..ae789d14 100644
--- a/eek/eek-clutter-keyboard.c
+++ b/eek/eek-clutter-keyboard.c
@@ -40,7 +40,6 @@ G_DEFINE_TYPE (EekClutterKeyboard, eek_clutter_keyboard, EEK_TYPE_KEYBOARD);
 struct _EekClutterKeyboardPrivate
 {
     ClutterActor *actor;
-    EekLayout *layout;
 };
 
 static void
@@ -96,7 +95,6 @@ eek_clutter_keyboard_real_create_section (EekKeyboard *self)
 
     section = g_object_new (EEK_TYPE_CLUTTER_SECTION, NULL);
     g_return_val_if_fail (section, NULL);
-    g_object_ref_sink (section);
 
     g_signal_connect (section, "key-pressed",
                       G_CALLBACK(key_pressed_event), self);
@@ -114,31 +112,13 @@ eek_clutter_keyboard_real_create_section (EekKeyboard *self)
     return section;
 }
 
-static void
-eek_clutter_keyboard_real_set_layout (EekKeyboard *self,
-                                      EekLayout   *layout)
-{
-    EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
-
-    g_return_if_fail (EEK_IS_LAYOUT(layout));
-
-    /* Don't apply the layout to keyboard right now, so to delay
-       drawing until eek_clutter_keyboard_get_actor. */
-    priv->layout = layout;
-    g_object_ref_sink (priv->layout);
-}
-
 static void
 eek_clutter_keyboard_finalize (GObject *object)
 {
     EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(object);
 
-    /* No need for clutter_group_remove_all() since
-       ClutterGroup#dispose() unrefs all the children. */
     if (priv->actor)
         g_object_unref (priv->actor);
-    if (priv->layout)
-        g_object_unref (priv->layout);
     G_OBJECT_CLASS (eek_clutter_keyboard_parent_class)->finalize (object);
 }
 
@@ -165,7 +145,6 @@ eek_clutter_keyboard_init (EekClutterKeyboard *self)
 
     priv = self->priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
     priv->actor = NULL;
-    priv->layout = NULL;
 }
 
 /**
@@ -195,14 +174,67 @@ eek_clutter_keyboard_new (gfloat width,
     return keyboard;
 }
 
+static gboolean
+on_clutter_key_press_event (ClutterActor *actor,
+                            ClutterEvent *event,
+                            gpointer      user_data)
+{
+    guint keycode;
+    EekKey *key;
+
+    keycode = clutter_event_get_key_code (event);
+    key = eek_keyboard_find_key_by_keycode (user_data, keycode);
+    if (key) {
+        g_signal_emit_by_name (key, "pressed", NULL);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static gboolean
+on_clutter_key_release_event (ClutterActor *actor,
+                              ClutterEvent *event,
+                              gpointer      user_data)
+{
+    guint keycode;
+    EekKey *key;
+
+    keycode = clutter_event_get_key_code (event);
+    key = eek_keyboard_find_key_by_keycode (user_data, keycode);
+    if (key) {
+        g_signal_emit_by_name (key, "released", NULL);
+        return TRUE;
+    }
+    return FALSE;    
+}
+
+static void
+on_clutter_realize (ClutterActor *actor, gpointer user_data)
+{
+    EekClutterKeyboard *keyboard = user_data;
+    EekClutterKeyboardPrivate *priv =
+        EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard);
+    ClutterActor *stage;
+
+    stage = clutter_actor_get_stage (priv->actor);
+    g_signal_connect (stage, "key-press-event",
+                      G_CALLBACK (on_clutter_key_press_event), keyboard);
+    g_signal_connect (stage, "key-release-event",
+                      G_CALLBACK (on_clutter_key_release_event), keyboard);
+}
+
 ClutterActor *
 eek_clutter_keyboard_get_actor (EekClutterKeyboard *keyboard)
 {
     EekClutterKeyboardPrivate *priv =
         EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard);
-    if (!priv->actor)
+    if (!priv->actor) {
         priv->actor = clutter_group_new ();
-    if (priv->layout)
-        eek_layout_apply (priv->layout, EEK_KEYBOARD(keyboard));
+        g_object_ref_sink (priv->actor);
+        g_signal_connect (priv->actor, "realize",
+                          G_CALLBACK (on_clutter_realize), keyboard);
+        g_return_val_if_fail (priv->actor, NULL);
+        eek_keyboard_realize (EEK_KEYBOARD(keyboard));
+    }
     return priv->actor;
 }
diff --git a/eek/eek-clutter-section.c b/eek/eek-clutter-section.c
index 4d320c38..031bd81d 100644
--- a/eek/eek-clutter-section.c
+++ b/eek/eek-clutter-section.c
@@ -116,7 +116,6 @@ eek_clutter_section_real_create_key (EekSection  *self,
                         "row", row,
                         NULL);
     g_return_val_if_fail (key, NULL);
-    g_object_ref_sink (key);
     
     g_signal_connect (key, "pressed", G_CALLBACK(pressed_event), self);
     g_signal_connect (key, "released", G_CALLBACK(released_event), self);
@@ -137,8 +136,6 @@ eek_clutter_section_finalize (GObject *object)
 {
     EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(object);
 
-    /* No need for clutter_group_remove_all() since
-       ClutterGroup#dispose() unrefs all the children. */
     if (priv->actor)
         g_object_unref (priv->actor);
     G_OBJECT_CLASS (eek_clutter_section_parent_class)->finalize (object);
@@ -172,7 +169,9 @@ ClutterActor *
 eek_clutter_section_get_actor (EekClutterSection *section)
 {
     EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(section);
-    if (!priv->actor)
+    if (!priv->actor) {
         priv->actor = clutter_group_new ();
+        g_object_ref_sink (priv->actor);
+    }
     return priv->actor;
 }
diff --git a/eek/eek-container.c b/eek/eek-container.c
index e2784bcf..30dd8900 100644
--- a/eek/eek-container.c
+++ b/eek/eek-container.c
@@ -58,7 +58,7 @@ eek_container_real_add_child (EekContainer *self,
     EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
 
     g_return_if_fail (EEK_IS_ELEMENT(child));
-    g_object_ref (child);
+    g_object_ref_sink (child);
     priv->children = g_slist_prepend (priv->children, child);
 }
 
@@ -88,6 +88,20 @@ eek_container_real_foreach_child (EekContainer *self,
         (*callback) (EEK_ELEMENT(head->data), user_data);
 }
 
+static EekElement *
+eek_container_real_find (EekContainer *self,
+                         EekCompareFunc func,
+                         gpointer user_data)
+{
+    EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
+    GSList *head;
+
+    head = g_slist_find_custom (priv->children, user_data, (GCompareFunc)func);
+    if (head)
+        return head->data;
+    return NULL;
+}
+
 static void
 eek_container_finalize (GObject *object)
 {
@@ -111,6 +125,7 @@ eek_container_class_init (EekContainerClass *klass)
     klass->add_child = eek_container_real_add_child;
     klass->remove_child = eek_container_real_remove_child;
     klass->foreach_child = eek_container_real_foreach_child;
+    klass->find = eek_container_real_find;
 
     gobject_class->finalize = eek_container_finalize;
 
@@ -155,3 +170,14 @@ eek_container_foreach_child (EekContainer *container,
                                                        callback,
                                                        user_data);
 }
+
+EekElement *
+eek_container_find (EekContainer  *container,
+                    EekCompareFunc func,
+                    gpointer       user_data)
+{
+    g_return_val_if_fail (EEK_IS_CONTAINER(container), NULL);
+    return EEK_CONTAINER_GET_CLASS(container)->find (container,
+                                                     func,
+                                                     user_data);
+}
diff --git a/eek/eek-container.h b/eek/eek-container.h
index 8a099af8..418efd74 100644
--- a/eek/eek-container.h
+++ b/eek/eek-container.h
@@ -36,6 +36,7 @@ typedef struct _EekContainerClass EekContainerClass;
 typedef struct _EekContainerPrivate EekContainerPrivate;
 
 typedef void (*EekCallback) (EekElement *element, gpointer user_data);
+typedef gint (*EekCompareFunc) (EekElement *element, gpointer user_data);
 
 struct _EekContainer
 {
@@ -51,29 +52,35 @@ struct _EekContainerClass
     /*< private >*/
     EekElementClass parent_class;
 
-    void (* add_child)     (EekContainer *self,
-                            EekElement   *element);
+    void        (* add_child)     (EekContainer  *self,
+                                   EekElement    *element);
 
-    void (* remove_child)  (EekContainer *self,
-                            EekElement   *element);
+    void        (* remove_child)  (EekContainer  *self,
+                                   EekElement    *element);
 
     /*< public >*/
-    void (* foreach_child) (EekContainer *self,
-                            EekCallback   callback,
-                            gpointer      user_data);
+    void        (* foreach_child) (EekContainer  *self,
+                                   EekCallback    callback,
+                                   gpointer       user_data);
+    EekElement *(* find)          (EekContainer  *self,
+                                   EekCompareFunc func,
+                                   gpointer       user_data);
 
     /* signals */
-    void (* child_added)   (EekContainer *self,
-                            EekElement   *element);
-    void (* child_removed) (EekContainer *self,
-                            EekElement   *element);
+    void        (* child_added)   (EekContainer  *self,
+                                   EekElement    *element);
+    void        (* child_removed) (EekContainer  *self,
+                                   EekElement    *element);
 };
 
-GType eek_container_get_type      (void) G_GNUC_CONST;
+GType       eek_container_get_type      (void) G_GNUC_CONST;
 
-void  eek_container_foreach_child (EekContainer *self,
-                                   EekCallback   callback,
-                                   gpointer      user_data);
+void        eek_container_foreach_child (EekContainer  *self,
+                                         EekCallback    callback,
+                                         gpointer       user_data);
+EekElement *eek_container_find          (EekContainer  *container,
+                                         EekCompareFunc func,
+                                         gpointer       user_data);
 
 G_END_DECLS
 #endif  /* EEK_CONTAINER_H */
diff --git a/eek/eek-key.c b/eek/eek-key.c
index d7d9a25e..21e174f2 100644
--- a/eek/eek-key.c
+++ b/eek/eek-key.c
@@ -221,6 +221,18 @@ eek_key_real_get_keysym_index (EekKey *self,
         *level = priv->level;
 }
 
+static void
+eek_key_real_pressed (EekKey *key)
+{
+    g_debug ("pressed %X", eek_key_get_keycode (key));
+}
+
+static void
+eek_key_real_released (EekKey *key)
+{
+    g_debug ("released %X", eek_key_get_keycode (key));
+}
+
 static void
 eek_key_finalize (GObject *object)
 {
@@ -354,6 +366,10 @@ eek_key_class_init (EekKeyClass *klass)
     gobject_class->get_property = eek_key_get_property;
     gobject_class->finalize     = eek_key_finalize;
 
+    /* signals */
+    klass->pressed = eek_key_real_pressed;
+    klass->released = eek_key_real_released;
+
     /**
      * EekKey:keycode:
      *
@@ -444,7 +460,7 @@ eek_key_class_init (EekKeyClass *klass)
         g_signal_new ("pressed",
                       G_TYPE_FROM_CLASS(gobject_class),
                       G_SIGNAL_RUN_FIRST,
-                      0,
+                      G_STRUCT_OFFSET(EekKeyClass, pressed),
                       NULL,
                       NULL,
                       g_cclosure_marshal_VOID__VOID,
@@ -454,7 +470,7 @@ eek_key_class_init (EekKeyClass *klass)
         g_signal_new ("released",
                       G_TYPE_FROM_CLASS(gobject_class),
                       G_SIGNAL_RUN_FIRST,
-                      0,
+                      G_STRUCT_OFFSET(EekKeyClass, released),
                       NULL,
                       NULL,
                       g_cclosure_marshal_VOID__VOID,
diff --git a/eek/eek-key.h b/eek/eek-key.h
index fac2412d..b3995b97 100644
--- a/eek/eek-key.h
+++ b/eek/eek-key.h
@@ -80,6 +80,10 @@ struct _EekKeyClass
     void        (* get_keysym_index) (EekKey     *self,
                                       gint       *group,
                                       gint       *level);
+
+    /* signals */
+    void        (* pressed)          (EekKey     *key);
+    void        (* released)         (EekKey     *key);
 };
 
 GType       eek_key_get_type         (void) G_GNUC_CONST;
diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c
index e6f88f28..7f5a3d32 100644
--- a/eek/eek-keyboard.c
+++ b/eek/eek-keyboard.c
@@ -60,6 +60,8 @@ struct _EekKeyboardPrivate
 {
     gint group;
     gint level;
+    EekLayout *layout;
+    gboolean is_realized;
 };
 
 struct keysym_index {
@@ -141,7 +143,6 @@ eek_keyboard_real_create_section (EekKeyboard *self)
 
     section = g_object_new (EEK_TYPE_SECTION, NULL);
     g_return_val_if_fail (section, NULL);
-    g_object_ref_sink (section);
 
     g_signal_connect (section, "key-pressed",
                       G_CALLBACK(key_pressed_event), self);
@@ -157,12 +158,64 @@ static void
 eek_keyboard_real_set_layout (EekKeyboard *self,
                               EekLayout   *layout)
 {
+    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
+
     g_return_if_fail (EEK_IS_LAYOUT(layout));
+    priv->layout = layout;
+    g_object_ref_sink (priv->layout);
+}
 
-    EEK_LAYOUT_GET_IFACE(layout)->apply (layout, self);
+static void
+eek_keyboard_real_realize (EekKeyboard *self)
+{
+    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
 
-    if (g_object_is_floating (layout))
-        g_object_unref (layout);
+    g_return_if_fail (priv->layout);
+    g_return_if_fail (!priv->is_realized);
+    EEK_LAYOUT_GET_IFACE(priv->layout)->apply (priv->layout, self);
+    priv->is_realized = TRUE;
+}
+
+struct find_key_by_keycode_data {
+    EekKey *key;
+    guint keycode;
+};
+
+static gint
+compare_section_by_keycode (EekElement *element, gpointer user_data)
+{
+    struct find_key_by_keycode_data *data = user_data;
+
+    data->key = eek_section_find_key_by_keycode (EEK_SECTION(element),
+                                                 data->keycode);
+    if (data->key)
+        return 0;
+    return -1;
+}
+
+static EekKey *
+eek_keyboard_real_find_key_by_keycode (EekKeyboard *self,
+                                       guint        keycode)
+{
+    struct find_key_by_keycode_data data;
+
+    data.keycode = keycode;
+    if (eek_container_find (EEK_CONTAINER(self),
+                            compare_section_by_keycode,
+                            &data))
+        return data.key;
+    return NULL;
+}
+
+static void
+eek_keyboard_finalize (GObject *object)
+{
+    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
+
+    if (priv->layout)
+        g_object_unref (priv->layout);
+
+    G_OBJECT_CLASS(eek_keyboard_parent_class)->finalize (object);
 }
 
 static void
@@ -234,9 +287,12 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
     klass->get_keysym_index = eek_keyboard_real_get_keysym_index;
     klass->create_section = eek_keyboard_real_create_section;
     klass->set_layout = eek_keyboard_real_set_layout;
+    klass->realize = eek_keyboard_real_realize;
+    klass->find_key_by_keycode = eek_keyboard_real_find_key_by_keycode;
 
     gobject_class->get_property = eek_keyboard_get_property;
     gobject_class->set_property = eek_keyboard_set_property;
+    gobject_class->finalize = eek_keyboard_finalize;
 
     /**
      * EekKeyboard:group:
@@ -298,6 +354,8 @@ eek_keyboard_init (EekKeyboard *self)
 
     priv = self->priv = EEK_KEYBOARD_GET_PRIVATE(self);
     priv->group = priv->level = 0;
+    priv->layout = NULL;
+    priv->is_realized = FALSE;
 }
 
 /**
@@ -368,3 +426,19 @@ eek_keyboard_set_layout (EekKeyboard *keyboard,
     g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
     EEK_KEYBOARD_GET_CLASS(keyboard)->set_layout (keyboard, layout);
 }
+
+void
+eek_keyboard_realize (EekKeyboard *keyboard)
+{
+    g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
+    EEK_KEYBOARD_GET_CLASS(keyboard)->realize (keyboard);
+}
+
+EekKey *
+eek_keyboard_find_key_by_keycode (EekKeyboard *keyboard,
+                                  guint        keycode)
+{
+    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
+    return EEK_KEYBOARD_GET_CLASS(keyboard)->find_key_by_keycode (keyboard,
+                                                                  keycode);
+}
diff --git a/eek/eek-keyboard.h b/eek/eek-keyboard.h
index b3b63401..feff731a 100644
--- a/eek/eek-keyboard.h
+++ b/eek/eek-keyboard.h
@@ -51,32 +51,38 @@ struct _EekKeyboardClass
     EekContainerClass parent_class;
 
     /*< public >*/
-    void        (* set_keysym_index) (EekKeyboard *self,
-                                      gint         group,
-                                      gint         level);
-    void        (* get_keysym_index) (EekKeyboard *self,
-                                      gint        *group,
-                                      gint        *level);
+    void        (* set_keysym_index)    (EekKeyboard *self,
+                                         gint         group,
+                                         gint         level);
+    void        (* get_keysym_index)    (EekKeyboard *self,
+                                         gint        *group,
+                                         gint        *level);
 
-    EekSection *(* create_section)   (EekKeyboard *self);
+    EekSection *(* create_section)      (EekKeyboard *self);
 
-    void        (* set_layout)       (EekKeyboard *self,
-                                      EekLayout   *layout);
+    void        (* set_layout)          (EekKeyboard *self,
+                                         EekLayout   *layout);
+    EekKey     *(* find_key_by_keycode) (EekKeyboard *self,
+                                         guint        keycode);
+    void        (* realize)             (EekKeyboard *self);
 };
 
-GType       eek_keyboard_get_type         (void) G_GNUC_CONST;
+GType       eek_keyboard_get_type            (void) G_GNUC_CONST;
 
-void        eek_keyboard_set_keysym_index (EekKeyboard *self,
-                                           gint         group,
-                                           gint         level);
-void        eek_keyboard_get_keysym_index (EekKeyboard *self,
-                                           gint        *group,
-                                           gint        *level);
+void        eek_keyboard_set_keysym_index    (EekKeyboard *self,
+                                              gint         group,
+                                              gint         level);
+void        eek_keyboard_get_keysym_index    (EekKeyboard *self,
+                                              gint        *group,
+                                              gint        *level);
 
-EekSection *eek_keyboard_create_section   (EekKeyboard *keyboard);
+EekSection *eek_keyboard_create_section      (EekKeyboard *keyboard);
 
-void        eek_keyboard_set_layout       (EekKeyboard *keyboard,
-                                           EekLayout   *layout);
+void        eek_keyboard_set_layout          (EekKeyboard *keyboard,
+                                              EekLayout   *layout);
+void        eek_keyboard_realize          (EekKeyboard *keyboard);
+EekKey     *eek_keyboard_find_key_by_keycode (EekKeyboard *keyboard,
+                                              guint        keycode);
 
 G_END_DECLS
 #endif  /* EEK_KEYBOARD_H */
diff --git a/eek/eek-section.c b/eek/eek-section.c
index 1396adc0..3a6010c6 100644
--- a/eek/eek-section.c
+++ b/eek/eek-section.c
@@ -158,7 +158,6 @@ eek_section_real_create_key (EekSection  *self,
                         "row", row,
                         NULL);
     g_return_val_if_fail (key, NULL);
-    g_object_ref_sink (key);
 
     g_signal_connect (key, "pressed", G_CALLBACK(pressed_event), self);
     g_signal_connect (key, "released", G_CALLBACK(released_event), self);
@@ -169,6 +168,23 @@ eek_section_real_create_key (EekSection  *self,
     return key;
 }
 
+static gint
+compare_key_by_keycode (EekElement *element, gpointer user_data)
+{
+    if (eek_key_get_keycode (EEK_KEY(element)) == (guint)(long)user_data)
+        return 0;
+    return -1;
+}
+
+static EekKey *
+eek_section_real_find_key_by_keycode (EekSection *self,
+                                      guint       keycode)
+{
+    return (EekKey *)eek_container_find (EEK_CONTAINER(self),
+                                         compare_key_by_keycode,
+                                         (gpointer)(long)keycode);
+}
+
 static void
 eek_section_finalize (GObject *object)
 {
@@ -179,10 +195,6 @@ eek_section_finalize (GObject *object)
         g_slice_free (EekRow, head->data);
     g_slist_free (priv->rows);
 
-    for (head = priv->keys; head; head = g_slist_next (head))
-        g_object_unref (head->data);
-    g_slist_free (priv->keys);
-
     G_OBJECT_CLASS (eek_section_parent_class)->finalize (object);
 }
 
@@ -237,6 +249,7 @@ eek_section_class_init (EekSectionClass *klass)
     klass->add_row = eek_section_real_add_row;
     klass->get_row = eek_section_real_get_row;
     klass->create_key = eek_section_real_create_key;
+    klass->find_key_by_keycode = eek_section_real_find_key_by_keycode;
 
     gobject_class->set_property = eek_section_set_property;
     gobject_class->get_property = eek_section_get_property;
@@ -289,7 +302,6 @@ eek_section_init (EekSection *self)
     priv = self->priv = EEK_SECTION_GET_PRIVATE (self);
     priv->angle = 0;
     priv->rows = NULL;
-    priv->keys = NULL;
 }
 
 void
@@ -346,3 +358,12 @@ eek_section_create_key (EekSection  *section,
     g_return_val_if_fail (EEK_IS_SECTION(section), NULL);
     return EEK_SECTION_GET_CLASS(section)->create_key (section, column, row);
 }
+
+EekKey *
+eek_section_find_key_by_keycode (EekSection *section,
+                                 guint       keycode)
+{
+    g_return_val_if_fail (EEK_IS_SECTION(section), NULL);
+    return EEK_SECTION_GET_CLASS(section)->find_key_by_keycode (section,
+                                                                keycode);
+}
diff --git a/eek/eek-section.h b/eek/eek-section.h
index 85daab13..ac8501a0 100644
--- a/eek/eek-section.h
+++ b/eek/eek-section.h
@@ -50,42 +50,48 @@ struct _EekSectionClass
     EekContainerClass parent_class;
 
     /*< public >*/
-    void    (* set_angle)    (EekSection     *self,
-                              gint            angle);
-    gint    (* get_angle)    (EekSection     *self);
+    void    (* set_angle)           (EekSection     *self,
+                                     gint            angle);
+    gint    (* get_angle)           (EekSection     *self);
 
-    gint    (* get_n_rows)   (EekSection     *self);
-    void    (* add_row)      (EekSection     *self,
-                              gint            num_columns,
-                              EekOrientation  orientation);
-    void    (* get_row)      (EekSection     *self,
-                              gint            index,
-                              gint           *num_columns,
-                              EekOrientation *orientation);
+    gint    (* get_n_rows)          (EekSection     *self);
+    void    (* add_row)             (EekSection     *self,
+                                     gint            num_columns,
+                                     EekOrientation  orientation);
+    void    (* get_row)             (EekSection     *self,
+                                     gint            index,
+                                     gint           *num_columns,
+                                     EekOrientation *orientation);
 
-    EekKey *(* create_key)   (EekSection     *self,
-                              gint            row,
-                              gint            column);
+    EekKey *(* create_key)          (EekSection     *self,
+                                     gint            row,
+                                     gint            column);
+
+    EekKey *(* find_key_by_keycode) (EekSection     *self,
+                                     guint           keycode);
 };
 
-GType   eek_section_get_type   (void) G_GNUC_CONST;
+GType   eek_section_get_type            (void) G_GNUC_CONST;
 
-void    eek_section_set_angle  (EekSection     *section,
-                                gint            angle);
-gint    eek_section_get_angle  (EekSection     *section);
+void    eek_section_set_angle           (EekSection     *section,
+                                         gint            angle);
+gint    eek_section_get_angle           (EekSection     *section);
 
-gint    eek_section_get_n_rows (EekSection     *section);
-void    eek_section_add_row    (EekSection     *section,
-                                gint            num_columns,
-                                EekOrientation  orientation);
-void    eek_section_get_row    (EekSection     *section,
-                                gint            index,
-                                gint           *num_columns,
-                                EekOrientation *orientation);
+gint    eek_section_get_n_rows          (EekSection     *section);
+void    eek_section_add_row             (EekSection     *section,
+                                         gint            num_columns,
+                                         EekOrientation  orientation);
+void    eek_section_get_row             (EekSection     *section,
+                                         gint            index,
+                                         gint           *num_columns,
+                                         EekOrientation *orientation);
 
-EekKey *eek_section_create_key (EekSection     *section,
-                                gint            column,
-                                gint            row);
+EekKey *eek_section_create_key          (EekSection     *section,
+                                         gint            column,
+                                         gint            row);
+
+EekKey *eek_section_find_key_by_keycode (EekSection     *self,
+                                         guint           keycode);
 
 G_END_DECLS
 #endif  /* EEK_SECTION_H */
diff --git a/eek/eek-xkb-layout.c b/eek/eek-xkb-layout.c
index a2b973c6..a2a649e6 100644
--- a/eek/eek-xkb-layout.c
+++ b/eek/eek-xkb-layout.c
@@ -145,7 +145,8 @@ create_key (EekXkbLayout *layout,
             gdouble x1, y1, x2, y2;
 
             outline->num_points = 4;
-            outline->points = g_new0 (EekPoint, outline->num_points);
+            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);
@@ -232,9 +233,10 @@ create_section (EekXkbLayout  *layout,
 
     priv = layout->priv;
     xkbgeometry = priv->xkb->geom;
-    name = XGetAtomName (priv->display, xkbsection->name);
     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 */
@@ -303,11 +305,22 @@ static void
 eek_xkb_layout_real_apply (EekLayout *layout, EekKeyboard *keyboard)
 {
     g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
-
     create_keyboard (EEK_XKB_LAYOUT(layout), keyboard);
+}
 
-    if (g_object_is_floating (keyboard))
-        g_object_unref (keyboard);
+static void
+eek_xkb_layout_real_set_names (EekXkbLayout *self, XkbComponentNamesRec *names)
+{
+    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (self);
+
+    g_return_if_fail (priv);
+    g_free (priv->names.keycodes);
+    priv->names.keycodes = g_strdup (names->keycodes);
+    g_free (priv->names.geometry);
+    priv->names.geometry = g_strdup (names->geometry);
+    g_free (priv->names.symbols);
+    priv->names.symbols = g_strdup (names->symbols);
+    get_keyboard (self);
 }
 
 static void
@@ -318,7 +331,8 @@ eek_xkb_layout_finalize (GObject *object)
     g_free (priv->names.keycodes);
     g_free (priv->names.geometry);
     g_free (priv->names.symbols);
-    g_hash_table_unref (priv->outline_hash);
+    if (priv->outline_hash)
+        g_hash_table_unref (priv->outline_hash);
     XkbFreeKeyboard (priv->xkb, 0, TRUE);	/* free_all = TRUE */
     G_OBJECT_CLASS (eek_xkb_layout_parent_class)->finalize (object);
 }
@@ -392,12 +406,13 @@ eek_layout_iface_init (EekLayoutIface *iface)
 static void
 eek_xkb_layout_class_init (EekXkbLayoutClass *klass)
 {
-    GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
-    GParamSpec        *pspec;
+    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+    GParamSpec *pspec;
 
     g_type_class_add_private (gobject_class, sizeof (EekXkbLayoutPrivate));
 
-    gobject_class->finalize     = eek_xkb_layout_finalize;
+    klass->set_names = eek_xkb_layout_real_set_names;
+    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;
 
@@ -426,7 +441,9 @@ eek_xkb_layout_class_init (EekXkbLayoutClass *klass)
 static void
 outline_free (gpointer data)
 {
-    g_slice_free (EekOutline, data);
+    EekOutline *outline = data;
+    g_slice_free1 (sizeof (EekPoint) * outline->num_points, outline->points);
+    g_boxed_free (EEK_TYPE_OUTLINE, outline);
 }
 
 static void
@@ -435,9 +452,10 @@ eek_xkb_layout_init (EekXkbLayout *self)
     EekXkbLayoutPrivate *priv;
 
     priv = self->priv = EEK_XKB_LAYOUT_GET_PRIVATE (self);
-
     memset (&priv->names, 0, sizeof priv->names);
+
     priv->display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+    g_return_if_fail (priv->display);
 
     /* XXX: XkbClientMapMask | XkbIndicatorMapMask | XkbNamesMask |
        XkbGeometryMask */
@@ -555,8 +573,9 @@ eek_xkb_layout_new (const gchar *keycodes,
 void
 eek_xkb_layout_set_keycodes (EekXkbLayout *layout, const gchar *keycodes)
 {
-    EekXkbLayoutPrivate *priv = layout->priv;
+    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 
+    g_return_if_fail (priv);
     g_free (priv->names.keycodes);
     priv->names.keycodes = g_strdup (keycodes);
     get_keyboard (layout);
@@ -572,8 +591,9 @@ eek_xkb_layout_set_keycodes (EekXkbLayout *layout, const gchar *keycodes)
 void
 eek_xkb_layout_set_geometry (EekXkbLayout *layout, const gchar *geometry)
 {
-    EekXkbLayoutPrivate *priv = layout->priv;
+    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 
+    g_return_if_fail (priv);
     g_free (priv->names.geometry);
     priv->names.geometry = g_strdup (geometry);
     get_keyboard (layout);
@@ -589,8 +609,9 @@ eek_xkb_layout_set_geometry (EekXkbLayout *layout, const gchar *geometry)
 void
 eek_xkb_layout_set_symbols (EekXkbLayout *layout, const gchar *symbols)
 {
-    EekXkbLayoutPrivate *priv = layout->priv;
+    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 
+    g_return_if_fail (priv);
     g_free (priv->names.symbols);
     priv->names.symbols = g_strdup (symbols);
     get_keyboard (layout);
@@ -605,8 +626,9 @@ eek_xkb_layout_set_symbols (EekXkbLayout *layout, const gchar *symbols)
 G_CONST_RETURN gchar *
 eek_xkb_layout_get_keycodes (EekXkbLayout *layout)
 {
-    EekXkbLayoutPrivate *priv = layout->priv;
+    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 
+    g_return_val_if_fail (priv, NULL);
     return priv->names.keycodes;
 }
 
@@ -619,7 +641,9 @@ eek_xkb_layout_get_keycodes (EekXkbLayout *layout)
 G_CONST_RETURN gchar *
 eek_xkb_layout_get_geometry (EekXkbLayout *layout)
 {
-    EekXkbLayoutPrivate *priv = layout->priv;
+    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
+
+    g_return_val_if_fail (priv, NULL);
     return priv->names.geometry;
 }
 
@@ -632,8 +656,9 @@ eek_xkb_layout_get_geometry (EekXkbLayout *layout)
 G_CONST_RETURN gchar *
 eek_xkb_layout_get_symbols (EekXkbLayout *layout)
 {
-    EekXkbLayoutPrivate *priv = layout->priv;
+    EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout);
 
+    g_return_val_if_fail (priv, NULL);
     return priv->names.symbols;
 }
 
diff --git a/eek/eek-xkb-layout.h b/eek/eek-xkb-layout.h
index b39b1cac..52f73510 100644
--- a/eek/eek-xkb-layout.h
+++ b/eek/eek-xkb-layout.h
@@ -50,34 +50,26 @@ struct _EekXkbLayoutClass
     /*< private >*/
     GInitiallyUnownedClass parent_class;
 
-    void                  (* set_keycodes) (EekXkbLayout *self,
-                                            const gchar  *keycodes);
-    void                  (* set_geometry) (EekXkbLayout *self,
-                                            const gchar  *geometry);
-    void                  (* set_symbols)  (EekXkbLayout *self,
-                                            const gchar  *symbols);
-
-    G_CONST_RETURN gchar *(* get_keycodes) (EekXkbLayout *self);
-    G_CONST_RETURN gchar *(* get_geometry) (EekXkbLayout *self);
-    G_CONST_RETURN gchar *(* get_symbols)  (EekXkbLayout *self);
+    void (* set_names) (EekXkbLayout         *self,
+                        XkbComponentNamesRec *names);
 };
 
 GType                 eek_xkb_layout_get_type     (void) G_GNUC_CONST;
 
-EekLayout            *eek_xkb_layout_new          (const gchar   *keycodes,
-                                                   const gchar   *geometry,
-                                                   const gchar   *symbols);
+EekLayout            *eek_xkb_layout_new          (const gchar  *keycodes,
+                                                   const gchar  *geometry,
+                                                   const gchar  *symbols);
 
-void                  eek_xkb_layout_set_keycodes (EekXkbLayout  *layout,
-                                                   const gchar   *keycodes);
-void                  eek_xkb_layout_set_geometry (EekXkbLayout  *layout,
-                                                   const gchar   *geometry);
-void                  eek_xkb_layout_set_symbols  (EekXkbLayout  *layout,
-                                                   const gchar   *symbols);
+void                  eek_xkb_layout_set_keycodes (EekXkbLayout *layout,
+                                                   const gchar  *keycodes);
+void                  eek_xkb_layout_set_geometry (EekXkbLayout *layout,
+                                                   const gchar  *geometry);
+void                  eek_xkb_layout_set_symbols  (EekXkbLayout *layout,
+                                                   const gchar  *symbols);
 
-G_CONST_RETURN gchar *eek_xkb_layout_get_keycodes (EekXkbLayout * layout);
-G_CONST_RETURN gchar *eek_xkb_layout_get_geometry (EekXkbLayout * layout);
-G_CONST_RETURN gchar *eek_xkb_layout_get_symbols  (EekXkbLayout * layout);
+G_CONST_RETURN gchar *eek_xkb_layout_get_keycodes (EekXkbLayout *layout);
+G_CONST_RETURN gchar *eek_xkb_layout_get_geometry (EekXkbLayout *layout);
+G_CONST_RETURN gchar *eek_xkb_layout_get_symbols  (EekXkbLayout *layout);
 
 G_END_DECLS
 #endif				/* #ifndef EEK_XKB_LAYOUT_H */
diff --git a/eek/eek-xkl-layout.c b/eek/eek-xkl-layout.c
new file mode 100644
index 00000000..8099097e
--- /dev/null
+++ b/eek/eek-xkl-layout.c
@@ -0,0 +1,272 @@
+/* 
+ * Copyright (C) 2010 Daiki Ueno 
+ * Copyright (C) 2010 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.
+ */
+
+#include 
+#include 
+#include 
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif  /* HAVE_CONFIG_H */
+
+#include "eek-xkl-layout.h"
+
+#define noKBDRAW_DEBUG
+
+G_DEFINE_TYPE (EekXklLayout, eek_xkl_layout, EEK_TYPE_XKB_LAYOUT);
+
+#define EEK_XKL_LAYOUT_GET_PRIVATE(obj)                                  \
+    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_XKL_LAYOUT, EekXklLayoutPrivate))
+
+enum {
+    PROP_0,
+    PROP_LAYOUTS,
+    PROP_VARIANTS,
+    PROP_OPTIONS,
+    PROP_LAST
+};
+
+struct _EekXklLayoutPrivate
+{
+    XklEngine *engine;
+    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 void update_xkb_layout (EekXklLayout *layout);
+
+static void
+eek_xkl_layout_finalize (GObject *object)
+{
+    EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (object);
+
+    g_free (priv->config.layouts);
+    g_free (priv->config.variants);
+    g_free (priv->config.options);
+    G_OBJECT_CLASS (eek_xkl_layout_parent_class)->finalize (object);
+}
+
+static void 
+eek_xkl_layout_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+    switch (prop_id) 
+        {
+        case PROP_LAYOUTS:
+            eek_xkl_layout_set_layouts (EEK_XKL_LAYOUT(object),
+                                        g_value_get_boxed (value));
+            break;
+        case PROP_VARIANTS:
+            eek_xkl_layout_set_variants (EEK_XKL_LAYOUT(object),
+                                         g_value_get_boxed (value));
+            break;
+        case PROP_OPTIONS:
+            eek_xkl_layout_set_options (EEK_XKL_LAYOUT(object),
+                                        g_value_get_boxed (value));
+            break;
+        default:
+            g_object_set_property (object,
+                                   g_param_spec_get_name (pspec),
+                                   value);
+            break;
+        }
+}
+
+static void 
+eek_xkl_layout_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+    switch (prop_id) 
+        {
+        case PROP_LAYOUTS:
+            g_value_set_boxed (value,
+                               eek_xkl_layout_get_layouts (EEK_XKL_LAYOUT(object)));
+            break;
+        case PROP_VARIANTS:
+            g_value_set_boxed (value,
+                               eek_xkl_layout_get_variants (EEK_XKL_LAYOUT(object)));
+            break;
+        case PROP_OPTIONS:
+            g_value_set_boxed (value,
+                               eek_xkl_layout_get_options (EEK_XKL_LAYOUT(object)));
+            break;
+        default:
+            g_object_get_property (object,
+                                   g_param_spec_get_name (pspec),
+                                   value);
+            break;
+        }
+}
+
+static void
+eek_xkl_layout_class_init (EekXklLayoutClass *klass)
+{
+    GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
+    GParamSpec        *pspec;
+
+    g_type_class_add_private (gobject_class, sizeof (EekXklLayoutPrivate));
+
+    gobject_class->finalize     = eek_xkl_layout_finalize;
+    gobject_class->set_property = eek_xkl_layout_set_property;
+    gobject_class->get_property = eek_xkl_layout_get_property;
+
+    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);
+
+    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);
+
+    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)
+{
+    EekXklLayoutPrivate *priv;
+    Display *display;
+
+    priv = self->priv = EEK_XKL_LAYOUT_GET_PRIVATE (self);
+    memset (&priv->config, 0, sizeof priv->config);
+
+    display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+    g_return_if_fail (display);
+
+    priv->engine = xkl_engine_get_instance (display);
+    xkl_config_rec_get_from_server (&priv->config, priv->engine);
+    update_xkb_layout (self);
+}
+
+EekLayout *
+eek_xkl_layout_new (gchar **layouts,
+                    gchar **variants,
+                    gchar **options)
+{
+    return g_object_new (EEK_TYPE_XKL_LAYOUT, NULL);
+}
+
+void
+eek_xkl_layout_set_layouts (EekXklLayout *layout, gchar **layouts)
+{
+    EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
+
+    g_return_if_fail (priv);
+    g_strfreev (priv->config.layouts);
+    priv->config.layouts = g_strdupv (layouts);
+    update_xkb_layout (layout);
+}
+
+void
+eek_xkl_layout_set_variants (EekXklLayout *layout, gchar **variants)
+{
+    EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
+
+    g_return_if_fail (priv);
+    g_strfreev (priv->config.variants);
+    priv->config.variants = g_strdupv (variants);
+    update_xkb_layout (layout);
+}
+
+void
+eek_xkl_layout_set_options (EekXklLayout *layout, gchar **options)
+{
+    EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
+
+    g_return_if_fail (priv);
+    g_strfreev (priv->config.options);
+    priv->config.options = g_strdupv (options);
+    update_xkb_layout (layout);
+}
+
+gchar **
+eek_xkl_layout_get_layouts (EekXklLayout *layout)
+{
+    EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
+
+    g_return_val_if_fail (priv, NULL);
+    return priv->config.layouts;
+}
+
+gchar **
+eek_xkl_layout_get_variants (EekXklLayout *layout)
+{
+    EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
+
+    g_return_val_if_fail (priv, NULL);
+    return priv->config.variants;
+}
+
+gchar **
+eek_xkl_layout_get_options (EekXklLayout *layout)
+{
+    EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
+
+    g_return_val_if_fail (priv, NULL);
+    return priv->config.options;
+}
+
+static void
+update_xkb_layout (EekXklLayout *layout)
+{
+    EekXklLayoutPrivate *priv = layout->priv;
+    XkbComponentNamesRec names;
+
+    if (xkl_xkb_config_native_prepare (priv->engine, &priv->config, &names)) {
+        EEK_XKB_LAYOUT_GET_CLASS (layout)->
+            set_names (EEK_XKB_LAYOUT(layout), &names);
+        xkl_xkb_config_native_cleanup (priv->engine, &names);
+    }
+}
diff --git a/eek/eek-xkl-layout.h b/eek/eek-xkl-layout.h
new file mode 100644
index 00000000..18fab763
--- /dev/null
+++ b/eek/eek-xkl-layout.h
@@ -0,0 +1,70 @@
+/* 
+ * Copyright (C) 2010 Daiki Ueno 
+ * Copyright (C) 2010 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_LAYOUT_H
+#define EEK_XKL_LAYOUT_H 1
+
+#include "eek-xkb-layout.h"
+
+G_BEGIN_DECLS
+
+#define EEK_TYPE_XKL_LAYOUT (eek_xkl_layout_get_type())
+#define EEK_XKL_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_XKL_LAYOUT, EekXklLayout))
+#define EEK_XKL_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_XKL_LAYOUT, EekXklLayoutClass))
+#define EEK_IS_XKL_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_XKL_LAYOUT))
+#define EEK_IS_XKL_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_XKL_LAYOUT))
+#define EEK_XKL_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_XKL_LAYOUT, EekXklLayoutClass))
+
+typedef struct _EekXklLayout        EekXklLayout;
+typedef struct _EekXklLayoutClass   EekXklLayoutClass;
+typedef struct _EekXklLayoutPrivate EekXklLayoutPrivate;
+
+struct _EekXklLayout
+{
+    /*< private >*/
+    EekXkbLayout parent;
+
+    EekXklLayoutPrivate *priv;
+};
+
+struct _EekXklLayoutClass
+{
+    /*< private >*/
+    EekXkbLayoutClass parent_class;
+};
+
+GType      eek_xkl_layout_get_type     (void) G_GNUC_CONST;
+
+EekLayout *eek_xkl_layout_new          (gchar       **layouts,
+                                        gchar       **variants,
+                                        gchar       **options);
+
+void       eek_xkl_layout_set_layouts  (EekXklLayout *layout,
+                                        gchar       **layouts);
+void       eek_xkl_layout_set_variants (EekXklLayout *layout,
+                                        gchar       **variants);
+void       eek_xkl_layout_set_options  (EekXklLayout *layout,
+                                        gchar       **options);
+
+gchar    **eek_xkl_layout_get_layouts  (EekXklLayout *layout);
+gchar    **eek_xkl_layout_get_variants (EekXklLayout *layout);
+gchar    **eek_xkl_layout_get_options  (EekXklLayout *layout);
+
+G_END_DECLS
+#endif				/* #ifndef EEK_XKL_LAYOUT_H */
diff --git a/eek/eek-xkl.h b/eek/eek-xkl.h
new file mode 100644
index 00000000..cd94b000
--- /dev/null
+++ b/eek/eek-xkl.h
@@ -0,0 +1,26 @@
+/* 
+ * Copyright (C) 2010 Daiki Ueno 
+ * Copyright (C) 2010 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 */
diff --git a/eek/eek-xkl.pc.in b/eek/eek-xkl.pc.in
new file mode 100644
index 00000000..b94e64be
--- /dev/null
+++ b/eek/eek-xkl.pc.in
@@ -0,0 +1,30 @@
+# Copyright (C) 2010 Daiki Ueno 
+# Copyright (C) 2010 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: EEK-XKB
+Description: A Library to Create Keyboard-like UI (XKB Support)
+URL: http://github.com/ueno/eek
+Version: @VERSION@
+Libs: -L${libdir} -leek -leek-xkb
+Libs.private: @GTK2_LIBS@ @XKB_LIBS@
+Cflags: -I${includedir}/eek-@EEK_API_VERSION@
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 48a27d09..4d01c69f 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -17,5 +17,5 @@
 # 02110-1301 USA
 
 noinst_PROGRAMS = eek-clutter-xkb-test
-eek_clutter_xkb_test_CFLAGS = -I$(top_srcdir) $(GOBJECT2_CFLAGS) $(CLUTTER_CFLAGS) $(XKB_CFLAGS)
-eek_clutter_xkb_test_LDFLAGS = $(top_builddir)/eek/libeek.la $(top_builddir)/eek/libeek-xkb.la $(top_builddir)/eek/libeek-clutter.la $(GOBJECT2_LIBS) $(CLUTTER_LIBS) $(XKB_LIBS)
+eek_clutter_xkb_test_CFLAGS = -I$(top_srcdir) $(GOBJECT2_CFLAGS) $(CLUTTER_CFLAGS) $(GTK2_CFLAGS) $(XKB_CFLAGS)
+eek_clutter_xkb_test_LDFLAGS = $(top_builddir)/eek/libeek.la $(top_builddir)/eek/libeek-xkb.la $(top_builddir)/eek/libeek-clutter.la $(GOBJECT2_LIBS) $(CLUTTER_LIBS) $(GTK2_CFLAGS) $(XKB_LIBS)
diff --git a/examples/eek-clutter-xkb-test.c b/examples/eek-clutter-xkb-test.c
index cc95d658..b8f38c63 100644
--- a/examples/eek-clutter-xkb-test.c
+++ b/examples/eek-clutter-xkb-test.c
@@ -1,5 +1,6 @@
 #include "eek/eek-clutter.h"
 #include "eek/eek-xkb.h"
+#include 
 #include 
 #include 
 #include 
@@ -31,31 +32,6 @@ static const GOptionEntry options[] = {
 
 gfloat stage_width, stage_height;
 
-static gboolean
-on_event (ClutterStage *stage,
-	  ClutterEvent *event,
-	  gpointer      user_data)
-{
-    if (event->type == CLUTTER_BUTTON_PRESS) {
-        ClutterActor *actor = clutter_event_get_source (event);
-
-        if (EEK_IS_KEY(actor)) {
-            guint keysym;
-            const gchar *label = NULL;
-
-            keysym = eek_key_get_keysym (EEK_KEY(actor));
-            if (keysym != EEK_INVALID_KEYSYM)
-                label = eek_keysym_to_string (keysym);
-            if (label) {
-                printf ("%s", label);
-                fflush (stdout);
-            }
-        }
-        return TRUE;
-    }
-    return FALSE;
-}
-
 static void
 on_resize (GObject *object,
 	   GParamSpec *param_spec,
@@ -107,7 +83,6 @@ main (int argc, char *argv[])
     g_option_context_free (context);
 
     clutter_init (&argc, &argv);
-
     gtk_init (&argc, &argv);
 
     layout = eek_xkb_layout_new (keycodes, geometry, symbols);
@@ -115,7 +90,6 @@ main (int argc, char *argv[])
         fprintf (stderr, "Failed to create layout\n");
         exit(1);
     }
-    g_object_ref_sink (layout);
 
     keyboard = eek_clutter_keyboard_new (CSW, CSH);
     if (keyboard == NULL) {
@@ -123,11 +97,13 @@ main (int argc, char *argv[])
         fprintf (stderr, "Failed to create keyboard\n");
         exit(1);
     }
-    g_object_ref_sink (keyboard);
 
-    g_signal_connect (keyboard, "key-pressed", G_CALLBACK(key_pressed_event), NULL);
+    g_signal_connect (keyboard, "key-pressed",
+                      G_CALLBACK(key_pressed_event), NULL);
+
     eek_keyboard_set_layout (keyboard, layout);
     actor = eek_clutter_keyboard_get_actor (EEK_CLUTTER_KEYBOARD(keyboard));
+
     stage = clutter_stage_get_default ();
 
     clutter_stage_set_color (CLUTTER_STAGE(stage), &stage_color);
diff --git a/examples/eek-gtk-xkb-test.c b/examples/eek-gtk-xkb-test.c
deleted file mode 100644
index b71b1fcc..00000000
--- a/examples/eek-gtk-xkb-test.c
+++ /dev/null
@@ -1,70 +0,0 @@
-#include "eek/eek-gtk.h"
-#include "eek/eek-xkb.h"
-#include 
-#include 
-#include 
-
-static gchar *symbols = NULL;
-static gchar *keycodes = NULL;
-static gchar *geometry = NULL;
-
-static const GOptionEntry options[] = {
-    {"symbols", '\0', 0, G_OPTION_ARG_STRING, &symbols,
-     "Symbols component of the keyboard. If you omit this option, it is "
-     "obtained from the X server; that is, the keyboard that is currently "
-     "configured is drawn. Examples: --symbols=us or "
-     "--symbols=us(pc104)+iso9995-3+group(switch)+ctrl(nocaps)", NULL},
-    {"keycodes", '\0', 0, G_OPTION_ARG_STRING, &keycodes,
-     "Keycodes component of the keyboard. If you omit this option, it is "
-     "obtained from the X server; that is, the keyboard that is currently"
-     " configured is drawn. Examples: --keycodes=xfree86+aliases(qwerty)",
-     NULL},
-    {"geometry", '\0', 0, G_OPTION_ARG_STRING, &geometry,
-     "Geometry xkb component. If you omit this option, it is obtained from the"
-     " X server; that is, the keyboard that is currently configured is drawn. "
-     "Example: --geometry=kinesis", NULL},
-    {NULL},
-};
-
-gfloat window_width, window_height;
-
-int
-main (int argc, char *argv[])
-{
-    EekKeyboard *keyboard;
-    EekLayout *layout;
-    GtkWidget *window;
-    GOptionContext *context;
-
-    context = g_option_context_new ("test-xkb-gtk");
-    g_option_context_add_main_entries (context, options, NULL);
-    g_option_context_parse (context, &argc, &argv, NULL);
-    g_option_context_free (context);
-
-    gtk_init (&argc, &argv);
-
-    layout = eek_xkb_layout_new (keycodes, geometry, symbols);
-    if (layout == NULL) {
-        fprintf (stderr, "Failed to create layout\n");
-        exit(1);
-    }
-    g_object_ref_sink (layout);
-
-    keyboard = eek_gtk_keyboard_new ();
-    if (keyboard == NULL) {
-        g_object_unref (layout);
-        fprintf (stderr, "Failed to create keyboard\n");
-        exit(1);
-    }
-    g_object_ref_sink (keyboard);
-
-    eek_keyboard_set_layout (keyboard, layout);
-
-    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-    gtk_container_add (GTK_CONTAINER(window), GTK_WIDGET(keyboard));
-
-    gtk_widget_show_all (window);
-    gtk_main ();
-
-    return 0;
-}
diff --git a/tests/eek-simple-test.c b/tests/eek-simple-test.c
index 084ca1a4..b22d33ff 100644
--- a/tests/eek-simple-test.c
+++ b/tests/eek-simple-test.c
@@ -37,6 +37,7 @@ test_create (void)
     g_assert (EEK_IS_KEY(key1));
 }
 
+#if 0
 static void
 test_create_clutter (void)
 {
@@ -57,6 +58,7 @@ test_create_clutter (void)
     g_assert (CLUTTER_IS_ACTOR(actor));
     g_object_unref (keyboard);
 }
+#endif
 
 int
 main (int argc, char **argv)
@@ -64,7 +66,9 @@ main (int argc, char **argv)
     g_type_init ();
     g_test_init (&argc, &argv, NULL);
     g_test_add_func ("/eek-simple-test/create", test_create);
+#if 0
     clutter_init (&argc, &argv);
     g_test_add_func ("/eek-simple-test/create-clutter", test_create_clutter);
+#endif
     return g_test_run ();
 }