discomfitor pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=945683824b7a7fb8fa63afd37347796267524151

commit 945683824b7a7fb8fa63afd37347796267524151
Author: Seunghun Lee <shiin....@samsung.com>
Date:   Mon Sep 21 12:51:07 2015 -0400

    Add initial module of weekeyboard as a wayland virtual keyboard.
    
    Summary:
    Depends on D2275
    
    this module is a virtual keyboard used in wayland.
    
    Test Plan:
    <prerequisite>
    - Configure with --enable-wl-weekeyboard.
    
    1. run enlightenment as a wayland display server.
    2. run weston-editor which has text entry using wayland protocol.
    
    Reviewers: devilhorns, raster, ManMower, jonc, zmike
    
    Subscribers: bryceharrington, jonc, jihoon, cedric, ManMower
    
    Differential Revision: https://phab.enlightenment.org/D2858
---
 configure.ac                                       |   12 +
 src/modules/Makefile.mk                            |    2 +
 src/modules/Makefile_wl_weekeyboard.mk             |   84 ++
 src/modules/wl_weekeyboard/e_mod_main.c            |  651 ++++++++++++
 .../wl_weekeyboard/input-method-client-protocol.h  |  439 ++++++++
 src/modules/wl_weekeyboard/input-method-protocol.c |  118 +++
 src/modules/wl_weekeyboard/text-client-protocol.h  |  540 ++++++++++
 src/modules/wl_weekeyboard/text-protocol.c         |   92 ++
 .../wl_weekeyboard/themes/default/default.edc      | 1118 ++++++++++++++++++++
 .../wl_weekeyboard/themes/default/default_1080.edc |   26 +
 .../wl_weekeyboard/themes/default/default_600.edc  |   26 +
 .../wl_weekeyboard/themes/default/default_720.edc  |   26 +
 .../themes/default/fonts/LICENSE.txt               |   93 ++
 .../themes/default/fonts/SourceSansPro-Regular.ttf |  Bin 0 -> 293960 bytes
 .../default/fonts/SourceSansPro-Semibold.ttf       |  Bin 0 -> 292456 bytes
 .../wl_weekeyboard/themes/default/ignorekeys.txt   |    4 +
 .../themes/default/images/icon-backspace.png       |  Bin 0 -> 1285 bytes
 .../themes/default/images/icon-enter.png           |  Bin 0 -> 1018 bytes
 .../themes/default/images/icon-language.png        |  Bin 0 -> 2596 bytes
 .../themes/default/images/icon-shift-active.png    |  Bin 0 -> 734 bytes
 .../themes/default/images/icon-shift.png           |  Bin 0 -> 890 bytes
 .../themes/default/images/icon-space.png           |  Bin 0 -> 312 bytes
 .../themes/default/images/key-default-pressed.png  |  Bin 0 -> 1679 bytes
 .../themes/default/images/key-default.png          |  Bin 0 -> 1837 bytes
 .../themes/default/images/key-hint-bg.png          |  Bin 0 -> 1515 bytes
 .../themes/default/images/key-hint.png             |  Bin 0 -> 1716 bytes
 .../themes/default/images/key-special-pressed.png  |  Bin 0 -> 1681 bytes
 .../themes/default/images/key-special.png          |  Bin 0 -> 1819 bytes
 src/modules/wl_weekeyboard/wkb-log.c               |   55 +
 src/modules/wl_weekeyboard/wkb-log.h               |   56 +
 30 files changed, 3342 insertions(+)

diff --git a/configure.ac b/configure.ac
index 0c9411d..9050294 100644
--- a/configure.ac
+++ b/configure.ac
@@ -855,6 +855,17 @@ define([CHECK_MODULE_WL_TEXT_INPUT],
 ])
 AM_CONDITIONAL([HAVE_WL_TEXT_INPUT], [test "x${WL_TEXT_INPUT}" = "xtrue"])
 
+WL_WEEKEYBOARD=false
+define([CHECK_MODULE_WL_WEEKEYBOARD],
+[
+   if test "x${have_wayland}" = "xyes" ; then
+      AC_E_CHECK_PKG(WL_WEEKEYBOARD, [ eina >= 1.8.0 evas >= 1.8.0 ecore >= 
1.8.0 ecore-evas >= 1.8.0 ecore-wayland >= 1.8.0 edje >= 1.8.0 ], 
[WL_WEEKEYBOARD=true], [WL_WEEKEYBOARD=false])
+   else
+      WL_WEEKEYBOARD=false
+   fi
+])
+AM_CONDITIONAL([HAVE_WL_WEEKEYBOARD], [test "x${WL_WEEKEYBOARD}" = "xtrue"])
+
 AC_E_OPTIONAL_MODULE([ibar], true)
 AC_E_OPTIONAL_MODULE([clock], true)
 AC_E_OPTIONAL_MODULE([pager], true)
@@ -910,6 +921,7 @@ AC_E_OPTIONAL_MODULE([wl_wl], $have_wayland, 
[CHECK_MODULE_WL_WL])
 #AC_E_OPTIONAL_MODULE([wl_fb], $have_wayland, [CHECK_MODULE_WL_FB])
 AC_E_OPTIONAL_MODULE([wl_drm], $have_wayland, [CHECK_MODULE_WL_DRM])
 AC_E_OPTIONAL_MODULE([wl_text_input], $have_wayland, 
[CHECK_MODULE_WL_TEXT_INPUT])
+AC_E_OPTIONAL_MODULE([wl_weekeyboard], $have_wayland, 
[CHECK_MODULE_WL_WEEKEYBOARD])
 AC_E_OPTIONAL_MODULE([policy_mobile], true)
 AC_E_OPTIONAL_MODULE([geolocation], true)
 AC_E_OPTIONAL_MODULE([xwayland], $have_wayland, [CHECK_MODULE_XWAYLAND])
diff --git a/src/modules/Makefile.mk b/src/modules/Makefile.mk
index ed334b2..0ddee49 100644
--- a/src/modules/Makefile.mk
+++ b/src/modules/Makefile.mk
@@ -123,6 +123,8 @@ include src/modules/Makefile_xwayland.mk
 
 include src/modules/Makefile_wl_text_input.mk
 
+include src/modules/Makefile_wl_weekeyboard.mk
+
 include src/modules/Makefile_policy_mobile.mk
 
 include src/modules/Makefile_geolocation.mk
diff --git a/src/modules/Makefile_wl_weekeyboard.mk 
b/src/modules/Makefile_wl_weekeyboard.mk
new file mode 100644
index 0000000..ca6adfc
--- /dev/null
+++ b/src/modules/Makefile_wl_weekeyboard.mk
@@ -0,0 +1,84 @@
+DEFAULT_FILES = \
+   src/modules/wl_weekeyboard/themes/default/default.edc \
+   src/modules/wl_weekeyboard/themes/default/ignorekeys.txt \
+   src/modules/wl_weekeyboard/themes/default/fonts/SourceSansPro-Regular.ttf \
+   src/modules/wl_weekeyboard/themes/default/fonts/SourceSansPro-Semibold.ttf \
+   src/modules/wl_weekeyboard/themes/default/images/key-hint-bg.png \
+   src/modules/wl_weekeyboard/themes/default/images/icon-language.png \
+   src/modules/wl_weekeyboard/themes/default/images/icon-backspace.png \
+   src/modules/wl_weekeyboard/themes/default/images/key-special.png \
+   src/modules/wl_weekeyboard/themes/default/images/icon-space.png \
+   src/modules/wl_weekeyboard/themes/default/images/key-hint.png \
+   src/modules/wl_weekeyboard/themes/default/images/icon-shift.png \
+   src/modules/wl_weekeyboard/themes/default/images/icon-shift-active.png \
+   src/modules/wl_weekeyboard/themes/default/images/icon-enter.png \
+   src/modules/wl_weekeyboard/themes/default/images/key-special-pressed.png \
+   src/modules/wl_weekeyboard/themes/default/images/key-default.png \
+   src/modules/wl_weekeyboard/themes/default/images/key-default-pressed.png
+
+EXTRA_DIST += \
+   $(DEFAULT_FILES) \
+   src/modules/wl_weekeyboard/themes/default/default_600.edc \
+   src/modules/wl_weekeyboard/themes/default/default_720.edj \
+   src/modules/wl_weekeyboard/themes/default/default_1080.edj
+
+if USE_MODULE_WL_WEEKEYBOARD
+wl_weekeyboarddir = $(MDIR)/wl_weekeyboard
+wl_weekeyboard_DATA = \
+   src/modules/wl_weekeyboard/themes/default/default_600.edj \
+   src/modules/wl_weekeyboard/themes/default/default_720.edj \
+   src/modules/wl_weekeyboard/themes/default/default_1080.edj
+
+CLEANFILES += \
+   src/modules/wl_weekeyboard/themes/default/default_600.edj \
+   src/modules/wl_weekeyboard/themes/default/default_720.edj \
+   src/modules/wl_weekeyboard/themes/default/default_1080.edj
+
+src/modules/wl_weekeyboard/themes/default/default_600.edj: 
src/modules/wl_weekeyboard/themes/default/default_600.edc $(DEFAULT_FILES) 
Makefile
+       $(EDJE_CC) $(EDJE_FLAGS) \
+           -dd $(top_srcdir)/src/modules/wl_weekeyboard/themes/default \
+           -id $(top_srcdir)/src/modules/wl_weekeyboard/themes/default/images \
+           -fd $(top_srcdir)/src/modules/wl_weekeyboard/themes/default/fonts \
+           
$(top_srcdir)/src/modules/wl_weekeyboard/themes/default/default_600.edc \
+           
$(top_builddir)/src/modules/wl_weekeyboard/themes/default/default_600.edj
+
+src/modules/wl_weekeyboard/themes/default/default_720.edj: 
src/modules/wl_weekeyboard/themes/default/default_720.edc $(DEFAULT_FILES) 
Makefile
+       $(EDJE_CC) $(EDJE_FLAGS) \
+           -dd $(top_srcdir)/src/modules/wl_weekeyboard/themes/default \
+           -id $(top_srcdir)/src/modules/wl_weekeyboard/themes/default/images \
+           -fd $(top_srcdir)/src/modules/wl_weekeyboard/themes/default/fonts \
+           
$(top_srcdir)/src/modules/wl_weekeyboard/themes/default/default_720.edc \
+           
$(top_builddir)/src/modules/wl_weekeyboard/themes/default/default_720.edj
+
+src/modules/wl_weekeyboard/themes/default/default_1080.edj: 
src/modules/wl_weekeyboard/themes/default/default_1080.edc $(DEFAULT_FILES) 
Makefile
+       $(EDJE_CC) $(EDJE_FLAGS) \
+           -dd $(top_srcdir)/src/modules/wl_weekeyboard/themes/default \
+           -id $(top_srcdir)/src/modules/wl_weekeyboard/themes/default/images \
+           -fd $(top_srcdir)/src/modules/wl_weekeyboard/themes/default/fonts \
+           
$(top_srcdir)/src/modules/wl_weekeyboard/themes/default/default_1080.edc \
+           
$(top_builddir)/src/modules/wl_weekeyboard/themes/default/default_1080.edj
+
+wl_weekeyboardpkgdir = $(MDIR)/wl_weekeyboard/$(MODULE_ARCH)
+wl_weekeyboardpkg_LTLIBRARIES = src/modules/wl_weekeyboard/module.la
+
+src_modules_wl_weekeyboard_module_la_DEPENDENCIES = $(MDEPENDENCIES)
+src_modules_wl_weekeyboard_module_la_CPPFLAGS  = \
+   $(MOD_CPPFLAGS)               \
+   @WL_WEEKEYBOARD_CFLAGS@       \
+   @WAYLAND_CFLAGS@              \
+   -DPKGDATADIR='"$pkgdatadir)"'
+src_modules_wl_weekeyboard_module_la_LIBADD   = $(LIBS) @WL_WEEKEYBOARD_LIBS@ 
@WAYLAND_LIBS@
+src_modules_wl_weekeyboard_module_la_LDFLAGS = $(MOD_LDFLAGS)
+src_modules_wl_weekeyboard_module_la_SOURCES =                 \
+   src/modules/wl_weekeyboard/e_mod_main.c                     \
+   src/modules/wl_weekeyboard/wkb-log.h                        \
+   src/modules/wl_weekeyboard/wkb-log.c                        \
+   src/modules/wl_weekeyboard/input-method-protocol.c          \
+   src/modules/wl_weekeyboard/input-method-client-protocol.h   \
+   src/modules/wl_weekeyboard/text-protocol.c                  \
+   src/modules/wl_weekeyboard/text-client-protocol.h
+
+PHONIES += wl_weekeyboard install-wl_weekeyboard
+wl_weekeyboard: $(wl_weekeyboardpkg_LTLIBRARIES) $(wl_weekeyboard_DATA)
+install-wl_weekeyboard: install-wl_weekeyboardpkgLTLIBRARIES
+endif
diff --git a/src/modules/wl_weekeyboard/e_mod_main.c 
b/src/modules/wl_weekeyboard/e_mod_main.c
new file mode 100644
index 0000000..bb5cbe7
--- /dev/null
+++ b/src/modules/wl_weekeyboard/e_mod_main.c
@@ -0,0 +1,651 @@
+#include "e.h"
+
+#include "wkb-log.h"
+
+#include "input-method-client-protocol.h"
+#include "text-client-protocol.h"
+
+struct weekeyboard
+{
+   E_Module *module;
+   Ecore_Evas *ee;
+   Ecore_Wl_Window *win;
+   Evas_Object *edje_obj;
+   const char *ee_engine;
+   char **ignore_keys;
+
+   struct wl_surface *surface;
+   struct wl_input_panel *ip;
+   struct wl_input_method *im;
+   struct wl_output *output;
+   struct wl_input_method_context *im_ctx;
+
+   char *surrounding_text;
+   char *preedit_str;
+   char *language;
+   char *theme;
+
+   uint32_t text_direction;
+   uint32_t preedit_style;
+   uint32_t content_hint;
+   uint32_t content_purpose;
+   uint32_t serial;
+   uint32_t surrounding_cursor;
+
+   Eina_Bool context_changed;
+};
+
+static char *
+_wkb_insert_text(const char *text, uint32_t offset, const char *insert)
+{
+   char *new_text = malloc(strlen(text) + strlen(insert) + 1);
+   uint32_t text_len = 0;
+
+   if ((!text) || (!insert))
+     return NULL;
+
+   text_len = strlen(text);
+   if (offset > text_len)
+     offset = text_len;
+
+   new_text = malloc(text_len + strlen(insert) + 1);
+   if (!new_text)
+     {
+        ERR("out of memory");
+        return NULL;
+     }
+
+   strncpy(new_text, text, offset);
+   new_text[offset] = '\0';
+   strcat(new_text, insert);
+   strcat(new_text, text + offset);
+
+   return new_text;
+}
+
+static void
+_wkb_commit_preedit_str(struct weekeyboard *wkb)
+{
+   char *surrounding_text;
+
+   if ((!wkb->preedit_str) || (strlen(wkb->preedit_str) == 0))
+     return;
+
+   wl_input_method_context_cursor_position(wkb->im_ctx, 0, 0);
+   wl_input_method_context_commit_string(wkb->im_ctx, wkb->serial, 
wkb->preedit_str);
+
+   if (wkb->surrounding_text)
+     {
+        surrounding_text = _wkb_insert_text(wkb->surrounding_text, 
wkb->surrounding_cursor, wkb->preedit_str);
+        free(wkb->surrounding_text);
+        wkb->surrounding_text = surrounding_text;
+        wkb->surrounding_cursor += strlen(wkb->preedit_str);
+     }
+   else
+     {
+        wkb->surrounding_text = strdup(wkb->preedit_str);
+        wkb->surrounding_cursor = strlen(wkb->preedit_str);
+     }
+
+   free(wkb->preedit_str);
+   wkb->preedit_str = strdup("");
+}
+
+static void
+_wkb_send_preedit_str(struct weekeyboard *wkb, int cursor)
+{
+   unsigned int index = strlen(wkb->preedit_str);
+
+   if (wkb->preedit_style)
+     wl_input_method_context_preedit_styling(wkb->im_ctx, 0, 
strlen(wkb->preedit_str), wkb->preedit_style);
+
+   if (cursor > 0)
+     index = cursor;
+
+   wl_input_method_context_preedit_cursor(wkb->im_ctx, index);
+   wl_input_method_context_preedit_string(wkb->im_ctx, wkb->serial, 
wkb->preedit_str, wkb->preedit_str);
+}
+
+static void
+_wkb_update_preedit_str(struct weekeyboard *wkb, const char *key)
+{
+   char *tmp;
+
+   if (!wkb->preedit_str)
+     wkb->preedit_str = strdup("");
+
+   tmp = _wkb_insert_text(wkb->preedit_str, strlen(wkb->preedit_str), key);
+   free(wkb->preedit_str);
+   wkb->preedit_str = tmp;
+
+   if (eina_streq(key, " "))
+     _wkb_commit_preedit_str(wkb);
+   else
+     _wkb_send_preedit_str(wkb, -1);
+}
+
+static Eina_Bool
+_wkb_ignore_key(struct weekeyboard *wkb, const char *key)
+{
+   int i;
+
+   if (!wkb->ignore_keys)
+     return EINA_FALSE;
+
+   for (i = 0; wkb->ignore_keys[i] != NULL; i++)
+     if (eina_streq(key, wkb->ignore_keys[i]))
+       return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+static void
+_cb_wkb_on_key_down(void *data, Evas_Object *obj EINA_UNUSED, const char 
*emission EINA_UNUSED, const char *source)
+{
+   struct weekeyboard *wkb = data;
+   char *src;
+   const char *key;
+
+   EINA_SAFETY_ON_FALSE_RETURN(wkb);
+   EINA_SAFETY_ON_FALSE_RETURN(source);
+
+   src = strdup(source);
+   if (!src)
+     {
+        ERR("out of memory");
+        return;
+     }
+
+   key = strtok(src, ":");
+   key = strtok(NULL, ":");
+   if (key == NULL)
+     key = ":";
+
+   if (_wkb_ignore_key(wkb, key))
+     {
+        DBG("Ignoring key: '%s'", key);
+        goto end;
+     }
+   else if (eina_streq(key, "backspace"))
+     {
+        if (strlen(wkb->preedit_str) == 0)
+          {
+             wl_input_method_context_delete_surrounding_text(wkb->im_ctx, -1, 
1);
+             wl_input_method_context_commit_string(wkb->im_ctx, wkb->serial, 
"");
+          }
+        else
+          {
+             wkb->preedit_str[strlen(wkb->preedit_str) -1] = '\0';
+             _wkb_send_preedit_str(wkb, -1);
+          }
+
+        goto end;
+     }
+   else if (eina_streq(key, "enter"))
+     {
+        _wkb_commit_preedit_str(wkb);
+        wl_input_method_context_keysym(wkb->im_ctx, wkb->serial, 0,
+                                       XKB_KEY_Return, 
WL_KEYBOARD_KEY_STATE_PRESSED, 0);
+        goto end;
+     }
+   else if (eina_streq(key, "space"))
+     {
+        key = " ";
+     }
+
+   DBG("Key pressed: '%s'", key);
+
+   _wkb_update_preedit_str(wkb, key);
+
+end:
+   free(src);
+}
+
+static Eina_Bool
+_wkb_ui_setup(struct weekeyboard *wkb)
+{
+   char path[PATH_MAX];
+   int w = 1080, h;
+   char *ignore_keys;
+   const char *theme;
+
+   /* First run */
+   if (!wkb->edje_obj)
+     {
+        Evas *evas;
+        ecore_evas_alpha_set(wkb->ee, EINA_TRUE);
+        ecore_evas_title_set(wkb->ee, "Weekeyboard");
+
+        evas = ecore_evas_get(wkb->ee);
+        wkb->edje_obj = edje_object_add(evas);
+        edje_object_signal_callback_add(wkb->edje_obj, "key_down", "*", 
_cb_wkb_on_key_down, wkb);
+     }
+
+   // hard coded
+   theme = "default";
+
+   if ((wkb->theme) && (eina_streq(theme, wkb->theme)))
+     return EINA_TRUE;
+
+   free(wkb->theme);
+   wkb->theme = strdup(theme);
+
+   if (eina_streq(wkb->theme, "default"))
+     {
+        ecore_wl_screen_size_get(&w, &h);
+        DBG("Screen size: w=%d, h=%d", w, h);
+        if (w >= 1080)
+          w = 1080;
+        else if (w >= 720)
+          w = 720;
+        else
+          w = 600;
+
+        DBG("Using default_%d theme", w);
+     }
+
+   snprintf(path, PATH_MAX, "%s/%s_%d.edj", e_module_dir_get(wkb->module), 
wkb->theme, w);
+   INF("Loading edje file: '%s'", path);
+
+   if (!edje_object_file_set(wkb->edje_obj, path, "main"))
+     {
+        int err = edje_object_load_error_get(wkb->edje_obj);
+        ERR("Unable to load the edje file: '%s'", edje_load_error_str(err));
+        return EINA_FALSE;
+     }
+
+   edje_object_size_min_get(wkb->edje_obj, &w, &h);
+   DBG("edje_object_size_min_get - w: %d h: %d", w, h);
+   if ((w == 0) || (h == 0))
+     {
+        edje_object_size_min_restricted_calc(wkb->edje_obj, &w, &h, w, h);
+        DBG("edje_object_size_min_restricted_calc - w: %d h: %d", w, h);
+        if ((w == 0) || (h == 0))
+          {
+             edje_object_parts_extends_calc(wkb->edje_obj, NULL, NULL, &w, &h);
+             DBG("edje_object_parts_extends_calc - w: %d h: %d", w, h);
+          }
+     }
+
+   ecore_evas_move_resize(wkb->ee, 0, 0, w, h);
+   evas_object_move(wkb->edje_obj, 0, 0);
+   evas_object_resize(wkb->edje_obj, w, h);
+   evas_object_size_hint_min_set(wkb->edje_obj, w, h);
+   evas_object_size_hint_max_set(wkb->edje_obj, w, h);
+
+   if (wkb->win)
+     {
+        int rx, ry, rw, rh;
+
+        edje_object_part_geometry_get(wkb->edje_obj, "background", &rx, &ry, 
&rw, &rh);
+        ecore_wl_window_input_region_set(wkb->win, rx, ry, rw, rh);
+     }
+
+   ignore_keys = edje_file_data_get(path, "ignore-keys");
+   if (!ignore_keys)
+     {
+        ERR("Special keys file not found in: '%s'", path);
+        goto end;
+     }
+
+   DBG("Got ignore keys: '%s'", ignore_keys);
+   wkb->ignore_keys = eina_str_split(ignore_keys, "\n", 0);
+   free(ignore_keys);
+
+end:
+   ecore_evas_show(wkb->ee);
+   return EINA_TRUE;
+}
+
+static void
+_wkb_im_ctx_surrounding_text(void *data, struct wl_input_method_context 
*im_ctx, const char *text, uint32_t cursor, uint32_t anchor)
+{
+   struct weekeyboard *wkb = data;
+
+   EINA_SAFETY_ON_NULL_RETURN(text);
+
+   DBG("im_context = %p text = '%s' cursor = %d anchor = %d", im_ctx, text, 
cursor, anchor);
+
+   free(wkb->surrounding_text);
+
+   wkb->surrounding_text = strdup(text);
+   if (!wkb->surrounding_text)
+     {
+        ERR("out of memory");
+        return;
+     }
+
+   wkb->surrounding_cursor = cursor;
+}
+
+static void
+_wkb_im_ctx_reset(void *data, struct wl_input_method_context *im_ctx)
+{
+   struct weekeyboard *wkb = data;
+
+   DBG("im_context = %p", im_ctx);
+
+   if (strlen(wkb->preedit_str))
+     {
+        free(wkb->preedit_str);
+        wkb->preedit_str = strdup("");
+     }
+}
+
+static void
+_wkb_im_ctx_content_type(void *data, struct wl_input_method_context *im_ctx, 
uint32_t hint, uint32_t purpose)
+{
+   struct weekeyboard *wkb = data;
+
+   DBG("im_context = %p hint = %d purpose = %d", im_ctx, hint, purpose);
+
+   if (!wkb->context_changed)
+     return;
+
+   switch (purpose)
+     {
+      case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
+      case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
+           {
+              if (wkb->edje_obj)
+                 edje_object_signal_emit(wkb->edje_obj, "show,numeric", "");
+              break;
+           }
+      default:
+           {
+              if (wkb->edje_obj)
+                 edje_object_signal_emit(wkb->edje_obj, "show,alphanumeric", 
"");
+              break;
+           }
+     }
+
+   wkb->content_hint = hint;
+   wkb->content_purpose = purpose;
+   wkb->context_changed = EINA_FALSE;
+}
+
+static void
+_wkb_im_ctx_invoke_action(void *data, struct wl_input_method_context *im_ctx, 
uint32_t button, uint32_t index)
+{
+   struct weekeyboard *wkb = data;
+
+   DBG("im_context = %p button = %d, index = %d", im_ctx, button, index);
+
+   if (button != BTN_LEFT)
+     return;
+
+   _wkb_send_preedit_str(wkb, index);
+}
+
+static void
+_wkb_im_ctx_commit_state(void *data, struct wl_input_method_context *im_ctx, 
uint32_t serial)
+{
+   struct weekeyboard *wkb = data;
+
+   DBG("im_context = %p serial = %d", im_ctx, serial);
+
+   if (wkb->surrounding_text)
+     INF("Surrounding text updated: %s", wkb->surrounding_text);
+
+   wkb->serial = serial;
+
+   wl_input_method_context_language(im_ctx, wkb->serial, "en");
+   wl_input_method_context_text_direction(im_ctx, wkb->serial, 
WL_TEXT_INPUT_TEXT_DIRECTION_LTR);
+}
+
+static void
+_wkb_im_ctx_preferred_language(void *data, struct wl_input_method_context 
*im_ctx, const char *language)
+{
+   struct weekeyboard *wkb = data;
+
+   DBG("im_context = %p language = %s", im_ctx, language ? language : "null");
+
+   if ((language) && (wkb->language) && (eina_streq(language, wkb->language)))
+     return;
+
+   E_FREE_FUNC(wkb->language, free);
+
+   if (language)
+     {
+        wkb->language = strdup(language);
+        INF("Language changed, new: '%s'", language);
+     }
+}
+
+static const struct wl_input_method_context_listener wkb_im_context_listener = 
{
+   _wkb_im_ctx_surrounding_text,
+   _wkb_im_ctx_reset,
+   _wkb_im_ctx_content_type,
+   _wkb_im_ctx_invoke_action,
+   _wkb_im_ctx_commit_state,
+   _wkb_im_ctx_preferred_language,
+};
+
+static void
+_wkb_im_activate(void *data, struct wl_input_method *input_method EINA_UNUSED, 
struct wl_input_method_context *im_ctx)
+{
+   struct weekeyboard *wkb = data;
+
+   DBG("Activate");
+
+   // check if the UI is valid and draw it if not
+   _wkb_ui_setup(wkb);
+
+   E_FREE_FUNC(wkb->im_ctx, wl_input_method_context_destroy);
+
+   free(wkb->preedit_str);
+   wkb->preedit_str = strdup("");
+   wkb->content_hint = WL_TEXT_INPUT_CONTENT_HINT_NONE;
+   wkb->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
+
+   free(wkb->language);
+   wkb->language = NULL;
+
+   free(wkb->surrounding_text);
+   wkb->surrounding_text = NULL;
+
+   wkb->serial = 0;
+
+   wkb->im_ctx = im_ctx;
+   wl_input_method_context_add_listener(im_ctx, &wkb_im_context_listener, wkb);
+
+   /* hard coded */
+   wl_input_method_context_language(im_ctx, wkb->serial, "en");
+   wl_input_method_context_text_direction(im_ctx, wkb->serial, 
WL_TEXT_INPUT_TEXT_DIRECTION_LTR);
+
+   wkb->context_changed = EINA_TRUE;
+   evas_object_show(wkb->edje_obj);
+}
+
+static void
+_wkb_im_deactivate(void *data, struct wl_input_method *input_method 
EINA_UNUSED, struct wl_input_method_context *im_ctx EINA_UNUSED)
+{
+   struct weekeyboard *wkb = data;
+
+   DBG("Deactivate");
+
+   E_FREE_FUNC(wkb->im_ctx, wl_input_method_context_destroy);
+
+   if (wkb->edje_obj)
+     evas_object_hide(wkb->edje_obj);
+}
+
+static const struct wl_input_method_listener wkb_im_listener = {
+   _wkb_im_activate,
+   _wkb_im_deactivate
+};
+
+static Eina_Bool
+_wkb_setup(struct weekeyboard *wkb)
+{
+   Eina_Inlist *globals;
+   struct wl_registry *registry;
+   Ecore_Wl_Global *global;
+   struct wl_input_panel_surface *ips;
+
+   globals = ecore_wl_globals_get();
+   registry = ecore_wl_registry_get();
+   EINA_INLIST_FOREACH(globals, global)
+     {
+        DBG("interface: <%s>", global->interface);
+        if (eina_streq(global->interface, "wl_input_panel"))
+          {
+             wkb->ip = wl_registry_bind(registry, global->id, 
&wl_input_panel_interface, 1);
+             DBG("binding wl_input_panel");
+          }
+        else if (eina_streq(global->interface, "wl_input_method"))
+          {
+             wkb->im = wl_registry_bind(registry, global->id, 
&wl_input_method_interface, 1);
+             DBG("binding wl_input_method, id = %d", global->id);
+          }
+        else if (eina_streq(global->interface, "wl_output"))
+          {
+             wkb->output = wl_registry_bind(registry, global->id, 
&wl_output_interface, 1);
+             DBG("binding wl_output");
+          }
+     }
+
+   if ((!wkb->ip) || (!wkb->im) || (!wkb->output))
+     return EINA_FALSE;
+
+   /* invalidate the UI so it is drawn when invoked */
+   wkb->theme = NULL;
+
+   /* Set input panel surface */
+   DBG("Setting up input panel");
+   wkb->win = ecore_evas_wayland_window_get(wkb->ee);
+   ecore_wl_window_type_set(wkb->win, ECORE_WL_WINDOW_TYPE_NONE);
+   wkb->surface = ecore_wl_window_surface_create(wkb->win);
+   ips = wl_input_panel_get_input_panel_surface(wkb->ip, wkb->surface);
+   wl_input_panel_surface_set_toplevel(ips, wkb->output, 
WL_INPUT_PANEL_SURFACE_POSITION_CENTER_BOTTOM);
+
+   /* Input method listener */
+   DBG("Adding wl_input_method listener");
+   wl_input_method_add_listener(wkb->im, &wkb_im_listener, wkb);
+
+   wkb->edje_obj = NULL;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_wkb_check_evas_engine(struct weekeyboard *wkb)
+{
+   const char *env = getenv("ECORE_EVAS_ENGINE");
+
+   if (!env)
+     {
+        if 
(ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_WAYLAND_SHM))
+          env = "wayland_shm";
+        else if 
(ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_WAYLAND_EGL))
+          env = "wayland_egl";
+        else
+          {
+             ERR("Ecore_Evas must be compiled with support for Wayland 
engines");
+             return EINA_FALSE;
+          }
+     }
+   else if ((!eina_streq(env, "wayland_shm")) &&
+            (!eina_streq(env, "wayland_egl")))
+     {
+        ERR("ECORE_EVAS_ENGINE must be set to either 'wayland_shm' or 
'wayland_egl'");
+        return EINA_FALSE;
+     }
+
+   wkb->ee_engine = env;
+
+   return EINA_TRUE;
+}
+
+static void
+_wkb_free(struct weekeyboard *wkb)
+{
+   E_FREE_FUNC(wkb->im_ctx, wl_input_method_context_destroy);
+   E_FREE_FUNC(wkb->edje_obj, evas_object_del);
+
+   if (wkb->ignore_keys)
+     {
+        free(*wkb->ignore_keys);
+        free(wkb->ignore_keys);
+     }
+
+   free(wkb->preedit_str);
+   free(wkb->surrounding_text);
+   free(wkb->theme);
+   free(wkb);
+}
+
+E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Weekeyboard" };
+
+E_API void *
+e_modapi_init(E_Module *m)
+{
+   struct weekeyboard *wkb;
+
+   EINA_LOG_DBG("LOAD 'weekeyboard' module\n");
+
+   wkb = E_NEW(struct weekeyboard, 1);
+   if (!wkb)
+     {
+        EINA_LOG_ERR("out of memory");
+        goto err;
+     }
+
+   if (!wkb_log_init("weekeyboard"))
+     {
+        EINA_LOG_ERR("failed to init log");
+        goto log_err;
+     }
+
+   if (!_wkb_check_evas_engine(wkb))
+     {
+        ERR("Unable to find available ee engine");
+        goto engine_err;
+     }
+
+   DBG("Selected engine: '%s'", wkb->ee_engine);
+   wkb->ee = ecore_evas_new(wkb->ee_engine, 0, 0, 1, 1, "frame=0");
+   if (!wkb->ee)
+     {
+        ERR("Unable to create Ecore_Evas object");
+        goto engine_err;
+     }
+
+   if (!_wkb_setup(wkb))
+     {
+        ERR("Unable to setup weekeyboard");
+        goto setup_err;
+     }
+
+   wkb->module = m;
+
+   m->data = wkb;
+
+   return m;
+
+setup_err:
+   ecore_evas_free(wkb->ee);
+
+engine_err:
+   wkb_log_shutdown();
+
+log_err:
+   free(wkb);
+
+err:
+   return NULL;
+}
+
+E_API int
+e_modapi_shutdown(E_Module *m)
+{
+   struct weekeyboard *wkb = m->data;
+
+   wkb_log_shutdown();
+
+   _wkb_free(wkb);
+
+   m->data = NULL;
+
+   return 1;
+}
diff --git a/src/modules/wl_weekeyboard/input-method-client-protocol.h 
b/src/modules/wl_weekeyboard/input-method-client-protocol.h
new file mode 100644
index 0000000..64773b5
--- /dev/null
+++ b/src/modules/wl_weekeyboard/input-method-client-protocol.h
@@ -0,0 +1,439 @@
+/* 
+ * Copyright © 2012, 2013 Intel Corporation
+ * 
+ * Permission to use, copy, modify, distribute, and sell this
+ * software and its documentation for any purpose is hereby granted
+ * without fee, provided that the above copyright notice appear in
+ * all copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * the copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ * 
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+
+#ifndef INPUT_METHOD_CLIENT_PROTOCOL_H
+#define INPUT_METHOD_CLIENT_PROTOCOL_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+struct wl_client;
+struct wl_resource;
+
+struct wl_input_method;
+struct wl_input_method_context;
+struct wl_input_panel;
+struct wl_input_panel_surface;
+struct wl_keyboard;
+struct wl_output;
+struct wl_surface;
+
+extern const struct wl_interface wl_input_method_context_interface;
+extern const struct wl_interface wl_input_method_interface;
+extern const struct wl_interface wl_input_panel_interface;
+extern const struct wl_interface wl_input_panel_surface_interface;
+
+/**
+ * wl_input_method_context - input method context
+ * @surrounding_text: surrounding text event
+ * @reset: (none)
+ * @content_type: (none)
+ * @invoke_action: (none)
+ * @commit_state: (none)
+ * @preferred_language: (none)
+ *
+ * Corresponds to a text model on input method side. An input method
+ * context is created on text mode activation on the input method side. It
+ * allows to receive information about the text model from the application
+ * via events. Input method contexts do not keep state after deactivation
+ * and should be destroyed after deactivation is handled.
+ *
+ * Text is generally UTF-8 encoded, indices and lengths are in bytes.
+ *
+ * Serials are used to synchronize the state between the text input and an
+ * input method. New serials are sent by the text input in the commit_state
+ * request and are used by the input method to indicate the known text
+ * input state in events like preedit_string, commit_string, and keysym.
+ * The text input can then ignore events from the input method which are
+ * based on an outdated state (for example after a reset).
+ */
+struct wl_input_method_context_listener {
+       /**
+        * surrounding_text - surrounding text event
+        * @text: (none)
+        * @cursor: (none)
+        * @anchor: (none)
+        *
+        * The plain surrounding text around the input position. Cursor
+        * is the position in bytes within the surrounding text relative to
+        * the beginning of the text. Anchor is the position in bytes of
+        * the selection anchor within the surrounding text relative to the
+        * beginning of the text. If there is no selected text anchor is
+        * the same as cursor.
+        */
+       void (*surrounding_text)(void *data,
+                                struct wl_input_method_context 
*wl_input_method_context,
+                                const char *text,
+                                uint32_t cursor,
+                                uint32_t anchor);
+       /**
+        * reset - (none)
+        */
+       void (*reset)(void *data,
+                     struct wl_input_method_context *wl_input_method_context);
+       /**
+        * content_type - (none)
+        * @hint: (none)
+        * @purpose: (none)
+        */
+       void (*content_type)(void *data,
+                            struct wl_input_method_context 
*wl_input_method_context,
+                            uint32_t hint,
+                            uint32_t purpose);
+       /**
+        * invoke_action - (none)
+        * @button: (none)
+        * @index: (none)
+        */
+       void (*invoke_action)(void *data,
+                             struct wl_input_method_context 
*wl_input_method_context,
+                             uint32_t button,
+                             uint32_t index);
+       /**
+        * commit_state - (none)
+        * @serial: serial of text input state
+        */
+       void (*commit_state)(void *data,
+                            struct wl_input_method_context 
*wl_input_method_context,
+                            uint32_t serial);
+       /**
+        * preferred_language - (none)
+        * @language: (none)
+        */
+       void (*preferred_language)(void *data,
+                                  struct wl_input_method_context 
*wl_input_method_context,
+                                  const char *language);
+};
+
+static inline int
+wl_input_method_context_add_listener(struct wl_input_method_context 
*wl_input_method_context,
+                                    const struct 
wl_input_method_context_listener *listener, void *data)
+{
+       return wl_proxy_add_listener((struct wl_proxy *) 
wl_input_method_context,
+                                    (void (**)(void)) listener, data);
+}
+
+#define WL_INPUT_METHOD_CONTEXT_DESTROY        0
+#define WL_INPUT_METHOD_CONTEXT_COMMIT_STRING  1
+#define WL_INPUT_METHOD_CONTEXT_PREEDIT_STRING 2
+#define WL_INPUT_METHOD_CONTEXT_PREEDIT_STYLING        3
+#define WL_INPUT_METHOD_CONTEXT_PREEDIT_CURSOR 4
+#define WL_INPUT_METHOD_CONTEXT_DELETE_SURROUNDING_TEXT        5
+#define WL_INPUT_METHOD_CONTEXT_CURSOR_POSITION        6
+#define WL_INPUT_METHOD_CONTEXT_MODIFIERS_MAP  7
+#define WL_INPUT_METHOD_CONTEXT_KEYSYM 8
+#define WL_INPUT_METHOD_CONTEXT_GRAB_KEYBOARD  9
+#define WL_INPUT_METHOD_CONTEXT_KEY    10
+#define WL_INPUT_METHOD_CONTEXT_MODIFIERS      11
+#define WL_INPUT_METHOD_CONTEXT_LANGUAGE       12
+#define WL_INPUT_METHOD_CONTEXT_TEXT_DIRECTION 13
+
+static inline void
+wl_input_method_context_set_user_data(struct wl_input_method_context 
*wl_input_method_context, void *user_data)
+{
+       wl_proxy_set_user_data((struct wl_proxy *) wl_input_method_context, 
user_data);
+}
+
+static inline void *
+wl_input_method_context_get_user_data(struct wl_input_method_context 
*wl_input_method_context)
+{
+       return wl_proxy_get_user_data((struct wl_proxy *) 
wl_input_method_context);
+}
+
+static inline void
+wl_input_method_context_destroy(struct wl_input_method_context 
*wl_input_method_context)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_DESTROY);
+
+       wl_proxy_destroy((struct wl_proxy *) wl_input_method_context);
+}
+
+static inline void
+wl_input_method_context_commit_string(struct wl_input_method_context 
*wl_input_method_context, uint32_t serial, const char *text)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_COMMIT_STRING, serial, text);
+}
+
+static inline void
+wl_input_method_context_preedit_string(struct wl_input_method_context 
*wl_input_method_context, uint32_t serial, const char *text, const char *commit)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_PREEDIT_STRING, serial, text, 
commit);
+}
+
+static inline void
+wl_input_method_context_preedit_styling(struct wl_input_method_context 
*wl_input_method_context, uint32_t index, uint32_t length, uint32_t style)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_PREEDIT_STYLING, index, 
length, style);
+}
+
+static inline void
+wl_input_method_context_preedit_cursor(struct wl_input_method_context 
*wl_input_method_context, int32_t index)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_PREEDIT_CURSOR, index);
+}
+
+static inline void
+wl_input_method_context_delete_surrounding_text(struct wl_input_method_context 
*wl_input_method_context, int32_t index, uint32_t length)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_DELETE_SURROUNDING_TEXT, 
index, length);
+}
+
+static inline void
+wl_input_method_context_cursor_position(struct wl_input_method_context 
*wl_input_method_context, int32_t index, int32_t anchor)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_CURSOR_POSITION, index, 
anchor);
+}
+
+static inline void
+wl_input_method_context_modifiers_map(struct wl_input_method_context 
*wl_input_method_context, struct wl_array *map)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_MODIFIERS_MAP, map);
+}
+
+static inline void
+wl_input_method_context_keysym(struct wl_input_method_context 
*wl_input_method_context, uint32_t serial, uint32_t time, uint32_t sym, 
uint32_t state, uint32_t modifiers)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_KEYSYM, serial, time, sym, 
state, modifiers);
+}
+
+static inline struct wl_keyboard *
+wl_input_method_context_grab_keyboard(struct wl_input_method_context 
*wl_input_method_context)
+{
+       struct wl_proxy *keyboard;
+
+       keyboard = wl_proxy_marshal_constructor((struct wl_proxy *) 
wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_GRAB_KEYBOARD, 
&wl_keyboard_interface, NULL);
+
+       return (struct wl_keyboard *) keyboard;
+}
+
+static inline void
+wl_input_method_context_key(struct wl_input_method_context 
*wl_input_method_context, uint32_t serial, uint32_t time, uint32_t key, 
uint32_t state)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_KEY, serial, time, key, state);
+}
+
+static inline void
+wl_input_method_context_modifiers(struct wl_input_method_context 
*wl_input_method_context, uint32_t serial, uint32_t mods_depressed, uint32_t 
mods_latched, uint32_t mods_locked, uint32_t group)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_MODIFIERS, serial, 
mods_depressed, mods_latched, mods_locked, group);
+}
+
+static inline void
+wl_input_method_context_language(struct wl_input_method_context 
*wl_input_method_context, uint32_t serial, const char *language)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_LANGUAGE, serial, language);
+}
+
+static inline void
+wl_input_method_context_text_direction(struct wl_input_method_context 
*wl_input_method_context, uint32_t serial, uint32_t direction)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_method_context,
+                        WL_INPUT_METHOD_CONTEXT_TEXT_DIRECTION, serial, 
direction);
+}
+
+/**
+ * wl_input_method - input method
+ * @activate: activate event
+ * @deactivate: activate event
+ *
+ * An input method object is responsible to compose text in response to
+ * input from hardware or virtual keyboards. There is one input method
+ * object per seat. On activate there is a new input method context object
+ * created which allows the input method to communicate with the text
+ * model.
+ */
+struct wl_input_method_listener {
+       /**
+        * activate - activate event
+        * @id: (none)
+        *
+        * A text model was activated. Creates an input method context
+        * object which allows communication with the text model.
+        */
+       void (*activate)(void *data,
+                        struct wl_input_method *wl_input_method,
+                        struct wl_input_method_context *id);
+       /**
+        * deactivate - activate event
+        * @context: (none)
+        *
+        * The text model corresponding to the context argument was
+        * deactivated. The input method context should be destroyed after
+        * deactivation is handled.
+        */
+       void (*deactivate)(void *data,
+                          struct wl_input_method *wl_input_method,
+                          struct wl_input_method_context *context);
+};
+
+static inline int
+wl_input_method_add_listener(struct wl_input_method *wl_input_method,
+                            const struct wl_input_method_listener *listener, 
void *data)
+{
+       return wl_proxy_add_listener((struct wl_proxy *) wl_input_method,
+                                    (void (**)(void)) listener, data);
+}
+
+static inline void
+wl_input_method_set_user_data(struct wl_input_method *wl_input_method, void 
*user_data)
+{
+       wl_proxy_set_user_data((struct wl_proxy *) wl_input_method, user_data);
+}
+
+static inline void *
+wl_input_method_get_user_data(struct wl_input_method *wl_input_method)
+{
+       return wl_proxy_get_user_data((struct wl_proxy *) wl_input_method);
+}
+
+static inline void
+wl_input_method_destroy(struct wl_input_method *wl_input_method)
+{
+       wl_proxy_destroy((struct wl_proxy *) wl_input_method);
+}
+
+#define WL_INPUT_PANEL_GET_INPUT_PANEL_SURFACE 0
+
+static inline void
+wl_input_panel_set_user_data(struct wl_input_panel *wl_input_panel, void 
*user_data)
+{
+       wl_proxy_set_user_data((struct wl_proxy *) wl_input_panel, user_data);
+}
+
+static inline void *
+wl_input_panel_get_user_data(struct wl_input_panel *wl_input_panel)
+{
+       return wl_proxy_get_user_data((struct wl_proxy *) wl_input_panel);
+}
+
+static inline void
+wl_input_panel_destroy(struct wl_input_panel *wl_input_panel)
+{
+       wl_proxy_destroy((struct wl_proxy *) wl_input_panel);
+}
+
+static inline struct wl_input_panel_surface *
+wl_input_panel_get_input_panel_surface(struct wl_input_panel *wl_input_panel, 
struct wl_surface *surface)
+{
+       struct wl_proxy *id;
+
+       id = wl_proxy_marshal_constructor((struct wl_proxy *) wl_input_panel,
+                        WL_INPUT_PANEL_GET_INPUT_PANEL_SURFACE, 
&wl_input_panel_surface_interface, NULL, surface);
+
+       return (struct wl_input_panel_surface *) id;
+}
+
+#ifndef WL_INPUT_PANEL_SURFACE_POSITION_ENUM
+#define WL_INPUT_PANEL_SURFACE_POSITION_ENUM
+enum wl_input_panel_surface_position {
+       WL_INPUT_PANEL_SURFACE_POSITION_CENTER_BOTTOM = 0,
+};
+#endif /* WL_INPUT_PANEL_SURFACE_POSITION_ENUM */
+
+struct wl_input_panel_surface_listener {
+       /**
+        * cursor_rectangle - cursor rectangle
+        * @x: (none)
+        * @y: (none)
+        * @width: (none)
+        * @height: (none)
+        *
+        * Notify when the cursor rectangle relative to the input panel
+        * surface change.
+        */
+       void (*cursor_rectangle)(void *data,
+                                struct wl_input_panel_surface 
*wl_input_panel_surface,
+                                int32_t x,
+                                int32_t y,
+                                int32_t width,
+                                int32_t height);
+};
+
+static inline int
+wl_input_panel_surface_add_listener(struct wl_input_panel_surface 
*wl_input_panel_surface,
+                                   const struct 
wl_input_panel_surface_listener *listener, void *data)
+{
+       return wl_proxy_add_listener((struct wl_proxy *) wl_input_panel_surface,
+                                    (void (**)(void)) listener, data);
+}
+
+#define WL_INPUT_PANEL_SURFACE_SET_TOPLEVEL    0
+#define WL_INPUT_PANEL_SURFACE_SET_OVERLAY_PANEL       1
+
+static inline void
+wl_input_panel_surface_set_user_data(struct wl_input_panel_surface 
*wl_input_panel_surface, void *user_data)
+{
+       wl_proxy_set_user_data((struct wl_proxy *) wl_input_panel_surface, 
user_data);
+}
+
+static inline void *
+wl_input_panel_surface_get_user_data(struct wl_input_panel_surface 
*wl_input_panel_surface)
+{
+       return wl_proxy_get_user_data((struct wl_proxy *) 
wl_input_panel_surface);
+}
+
+static inline void
+wl_input_panel_surface_destroy(struct wl_input_panel_surface 
*wl_input_panel_surface)
+{
+       wl_proxy_destroy((struct wl_proxy *) wl_input_panel_surface);
+}
+
+static inline void
+wl_input_panel_surface_set_toplevel(struct wl_input_panel_surface 
*wl_input_panel_surface, struct wl_output *output, uint32_t position)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_panel_surface,
+                        WL_INPUT_PANEL_SURFACE_SET_TOPLEVEL, output, position);
+}
+
+static inline void
+wl_input_panel_surface_set_overlay_panel(struct wl_input_panel_surface 
*wl_input_panel_surface)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_input_panel_surface,
+                        WL_INPUT_PANEL_SURFACE_SET_OVERLAY_PANEL);
+}
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/modules/wl_weekeyboard/input-method-protocol.c 
b/src/modules/wl_weekeyboard/input-method-protocol.c
new file mode 100644
index 0000000..72d84cf
--- /dev/null
+++ b/src/modules/wl_weekeyboard/input-method-protocol.c
@@ -0,0 +1,118 @@
+/* 
+ * Copyright © 2012, 2013 Intel Corporation
+ * 
+ * Permission to use, copy, modify, distribute, and sell this
+ * software and its documentation for any purpose is hereby granted
+ * without fee, provided that the above copyright notice appear in
+ * all copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * the copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ * 
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+extern const struct wl_interface wl_input_method_context_interface;
+extern const struct wl_interface wl_input_panel_surface_interface;
+extern const struct wl_interface wl_keyboard_interface;
+extern const struct wl_interface wl_output_interface;
+extern const struct wl_interface wl_surface_interface;
+
+static const struct wl_interface *types[] = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       &wl_keyboard_interface,
+       &wl_input_method_context_interface,
+       &wl_input_method_context_interface,
+       &wl_input_panel_surface_interface,
+       &wl_surface_interface,
+       &wl_output_interface,
+       NULL,
+};
+
+static const struct wl_message wl_input_method_context_requests[] = {
+       { "destroy", "", types + 0 },
+       { "commit_string", "us", types + 0 },
+       { "preedit_string", "uss", types + 0 },
+       { "preedit_styling", "uuu", types + 0 },
+       { "preedit_cursor", "i", types + 0 },
+       { "delete_surrounding_text", "iu", types + 0 },
+       { "cursor_position", "ii", types + 0 },
+       { "modifiers_map", "a", types + 0 },
+       { "keysym", "uuuuu", types + 0 },
+       { "grab_keyboard", "n", types + 5 },
+       { "key", "uuuu", types + 0 },
+       { "modifiers", "uuuuu", types + 0 },
+       { "language", "us", types + 0 },
+       { "text_direction", "uu", types + 0 },
+};
+
+static const struct wl_message wl_input_method_context_events[] = {
+       { "surrounding_text", "suu", types + 0 },
+       { "reset", "", types + 0 },
+       { "content_type", "uu", types + 0 },
+       { "invoke_action", "uu", types + 0 },
+       { "commit_state", "u", types + 0 },
+       { "preferred_language", "s", types + 0 },
+};
+
+WL_EXPORT const struct wl_interface wl_input_method_context_interface = {
+       "wl_input_method_context", 1,
+       14, wl_input_method_context_requests,
+       6, wl_input_method_context_events,
+};
+
+static const struct wl_message wl_input_method_events[] = {
+       { "activate", "n", types + 6 },
+       { "deactivate", "o", types + 7 },
+};
+
+WL_EXPORT const struct wl_interface wl_input_method_interface = {
+       "wl_input_method", 1,
+       0, NULL,
+       2, wl_input_method_events,
+};
+
+static const struct wl_message wl_input_panel_requests[] = {
+       { "get_input_panel_surface", "no", types + 8 },
+};
+
+WL_EXPORT const struct wl_interface wl_input_panel_interface = {
+       "wl_input_panel", 1,
+       1, wl_input_panel_requests,
+       0, NULL,
+};
+
+static const struct wl_message wl_input_panel_surface_requests[] = {
+       { "set_toplevel", "ou", types + 10 },
+       { "set_overlay_panel", "", types + 0 },
+};
+
+static const struct wl_message wl_input_panel_surface_events[] = {
+       { "cursor_rectangle", "iiii", types + 0 },
+};
+
+WL_EXPORT const struct wl_interface wl_input_panel_surface_interface = {
+       "wl_input_panel_surface", 1,
+       2, wl_input_panel_surface_requests,
+       1, wl_input_panel_surface_events,
+};
+
diff --git a/src/modules/wl_weekeyboard/text-client-protocol.h 
b/src/modules/wl_weekeyboard/text-client-protocol.h
new file mode 100644
index 0000000..f9288b1
--- /dev/null
+++ b/src/modules/wl_weekeyboard/text-client-protocol.h
@@ -0,0 +1,540 @@
+/* 
+ * Copyright © 2012, 2013 Intel Corporation
+ * 
+ * Permission to use, copy, modify, distribute, and sell this
+ * software and its documentation for any purpose is hereby granted
+ * without fee, provided that the above copyright notice appear in
+ * all copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * the copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ * 
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+
+#ifndef TEXT_CLIENT_PROTOCOL_H
+#define TEXT_CLIENT_PROTOCOL_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+struct wl_client;
+struct wl_resource;
+
+struct wl_seat;
+struct wl_surface;
+struct wl_text_input;
+struct wl_text_input_manager;
+
+extern const struct wl_interface wl_text_input_interface;
+extern const struct wl_interface wl_text_input_manager_interface;
+
+#ifndef WL_TEXT_INPUT_CONTENT_HINT_ENUM
+#define WL_TEXT_INPUT_CONTENT_HINT_ENUM
+/**
+ * wl_text_input_content_hint - content hint
+ * @WL_TEXT_INPUT_CONTENT_HINT_NONE: no special behaviour
+ * @WL_TEXT_INPUT_CONTENT_HINT_DEFAULT: auto completion, correction and
+ *     capitalization
+ * @WL_TEXT_INPUT_CONTENT_HINT_PASSWORD: hidden and sensitive text
+ * @WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION: suggest word completions
+ * @WL_TEXT_INPUT_CONTENT_HINT_AUTO_CORRECTION: suggest word corrections
+ * @WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION: switch to uppercase
+ *     letters at the start of a sentence
+ * @WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE: prefer lowercase letters
+ * @WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE: prefer uppercase letters
+ * @WL_TEXT_INPUT_CONTENT_HINT_TITLECASE: prefer casing for titles and
+ *     headings (can be language dependent)
+ * @WL_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT: characters should be hidden
+ * @WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA: typed text should not be
+ *     stored
+ * @WL_TEXT_INPUT_CONTENT_HINT_LATIN: just latin characters should be
+ *     entered
+ * @WL_TEXT_INPUT_CONTENT_HINT_MULTILINE: the text input is multiline
+ *
+ * Content hint is a bitmask to allow to modify the behavior of the text
+ * input.
+ */
+enum wl_text_input_content_hint {
+       WL_TEXT_INPUT_CONTENT_HINT_NONE = 0x0,
+       WL_TEXT_INPUT_CONTENT_HINT_DEFAULT = 0x7,
+       WL_TEXT_INPUT_CONTENT_HINT_PASSWORD = 0xc0,
+       WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION = 0x1,
+       WL_TEXT_INPUT_CONTENT_HINT_AUTO_CORRECTION = 0x2,
+       WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION = 0x4,
+       WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE = 0x8,
+       WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE = 0x10,
+       WL_TEXT_INPUT_CONTENT_HINT_TITLECASE = 0x20,
+       WL_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT = 0x40,
+       WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA = 0x80,
+       WL_TEXT_INPUT_CONTENT_HINT_LATIN = 0x100,
+       WL_TEXT_INPUT_CONTENT_HINT_MULTILINE = 0x200,
+};
+#endif /* WL_TEXT_INPUT_CONTENT_HINT_ENUM */
+
+#ifndef WL_TEXT_INPUT_CONTENT_PURPOSE_ENUM
+#define WL_TEXT_INPUT_CONTENT_PURPOSE_ENUM
+/**
+ * wl_text_input_content_purpose - content purpose
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL: default input, allowing all
+ *     characters
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_ALPHA: allow only alphabetic characters
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS: allow only digits
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER: input a number (including
+ *     decimal separator and sign)
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE: input a phone number
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_URL: input an URL
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL: input an email address
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_NAME: input a name of a person
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD: input a password (combine
+ *     with password or sensitive_data hint)
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_DATE: input a date
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_TIME: input a time
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME: input a date and time
+ * @WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL: input for a terminal
+ *
+ * The content purpose allows to specify the primary purpose of a text
+ * input.
+ *
+ * This allows an input method to show special purpose input panels with
+ * extra characters or to disallow some characters.
+ */
+enum wl_text_input_content_purpose {
+       WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL = 0,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_ALPHA = 1,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS = 2,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER = 3,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE = 4,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_URL = 5,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL = 6,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_NAME = 7,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD = 8,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_DATE = 9,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_TIME = 10,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME = 11,
+       WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL = 12,
+};
+#endif /* WL_TEXT_INPUT_CONTENT_PURPOSE_ENUM */
+
+#ifndef WL_TEXT_INPUT_PREEDIT_STYLE_ENUM
+#define WL_TEXT_INPUT_PREEDIT_STYLE_ENUM
+enum wl_text_input_preedit_style {
+       WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT = 0,
+       WL_TEXT_INPUT_PREEDIT_STYLE_NONE = 1,
+       WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE = 2,
+       WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE = 3,
+       WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT = 4,
+       WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE = 5,
+       WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION = 6,
+       WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT = 7,
+};
+#endif /* WL_TEXT_INPUT_PREEDIT_STYLE_ENUM */
+
+#ifndef WL_TEXT_INPUT_TEXT_DIRECTION_ENUM
+#define WL_TEXT_INPUT_TEXT_DIRECTION_ENUM
+enum wl_text_input_text_direction {
+       WL_TEXT_INPUT_TEXT_DIRECTION_AUTO = 0,
+       WL_TEXT_INPUT_TEXT_DIRECTION_LTR = 1,
+       WL_TEXT_INPUT_TEXT_DIRECTION_RTL = 2,
+};
+#endif /* WL_TEXT_INPUT_TEXT_DIRECTION_ENUM */
+
+/**
+ * wl_text_input - text input
+ * @enter: enter event
+ * @leave: leave event
+ * @modifiers_map: modifiers map
+ * @input_panel_state: state of the input panel
+ * @preedit_string: pre-edit
+ * @preedit_styling: pre-edit styling
+ * @preedit_cursor: pre-edit cursor
+ * @commit_string: commit
+ * @cursor_position: set cursor to new position
+ * @delete_surrounding_text: delete surrounding text
+ * @keysym: keysym
+ * @language: language
+ * @text_direction: text direction
+ *
+ * An object used for text input. Adds support for text input and input
+ * methods to applications. A text-input object is created from a
+ * wl_text_input_manager and corresponds typically to a text entry in an
+ * application. Requests are used to activate/deactivate the text-input
+ * object and set state information like surrounding and selected text or
+ * the content type. The information about entered text is sent to the
+ * text-input object via the pre-edit and commit events. Using this
+ * interface removes the need for applications to directly process hardware
+ * key events and compose text out of them.
+ *
+ * Text is generally UTF-8 encoded, indices and lengths are in bytes.
+ *
+ * Serials are used to synchronize the state between the text input and an
+ * input method. New serials are sent by the text input in the commit_state
+ * request and are used by the input method to indicate the known text
+ * input state in events like preedit_string, commit_string, and keysym.
+ * The text input can then ignore events from the input method which are
+ * based on an outdated state (for example after a reset).
+ */
+struct wl_text_input_listener {
+       /**
+        * enter - enter event
+        * @surface: (none)
+        *
+        * Notify the text-input object when it received focus. Typically
+        * in response to an activate request.
+        */
+       void (*enter)(void *data,
+                     struct wl_text_input *wl_text_input,
+                     struct wl_surface *surface);
+       /**
+        * leave - leave event
+        *
+        * Notify the text-input object when it lost focus. Either in
+        * response to a deactivate request or when the assigned surface
+        * lost focus or was destroyed.
+        */
+       void (*leave)(void *data,
+                     struct wl_text_input *wl_text_input);
+       /**
+        * modifiers_map - modifiers map
+        * @map: (none)
+        *
+        * Transfer an array of 0-terminated modifiers names. The
+        * position in the array is the index of the modifier as used in
+        * the modifiers bitmask in the keysym event.
+        */
+       void (*modifiers_map)(void *data,
+                             struct wl_text_input *wl_text_input,
+                             struct wl_array *map);
+       /**
+        * input_panel_state - state of the input panel
+        * @state: (none)
+        *
+        * Notify when the visibility state of the input panel changed.
+        */
+       void (*input_panel_state)(void *data,
+                                 struct wl_text_input *wl_text_input,
+                                 uint32_t state);
+       /**
+        * preedit_string - pre-edit
+        * @serial: serial of the latest known text input state
+        * @text: (none)
+        * @commit: (none)
+        *
+        * Notify when a new composing text (pre-edit) should be set
+        * around the current cursor position. Any previously set composing
+        * text should be removed.
+        *
+        * The commit text can be used to replace the preedit text on reset
+        * (for example on unfocus).
+        *
+        * The text input should also handle all preedit_style and
+        * preedit_cursor events occuring directly before preedit_string.
+        */
+       void (*preedit_string)(void *data,
+                              struct wl_text_input *wl_text_input,
+                              uint32_t serial,
+                              const char *text,
+                              const char *commit);
+       /**
+        * preedit_styling - pre-edit styling
+        * @index: (none)
+        * @length: (none)
+        * @style: (none)
+        *
+        * Sets styling information on composing text. The style is
+        * applied for length bytes from index relative to the beginning of
+        * the composing text (as byte offset). Multiple styles can be
+        * applied to a composing text by sending multiple preedit_styling
+        * events.
+        *
+        * This event is handled as part of a following preedit_string
+        * event.
+        */
+       void (*preedit_styling)(void *data,
+                               struct wl_text_input *wl_text_input,
+                               uint32_t index,
+                               uint32_t length,
+                               uint32_t style);
+       /**
+        * preedit_cursor - pre-edit cursor
+        * @index: (none)
+        *
+        * Sets the cursor position inside the composing text (as byte
+        * offset) relative to the start of the composing text. When index
+        * is a negative number no cursor is shown.
+        *
+        * This event is handled as part of a following preedit_string
+        * event.
+        */
+       void (*preedit_cursor)(void *data,
+                              struct wl_text_input *wl_text_input,
+                              int32_t index);
+       /**
+        * commit_string - commit
+        * @serial: serial of the latest known text input state
+        * @text: (none)
+        *
+        * Notify when text should be inserted into the editor widget.
+        * The text to commit could be either just a single character after
+        * a key press or the result of some composing (pre-edit). It could
+        * be also an empty text when some text should be removed (see
+        * delete_surrounding_text) or when the input cursor should be
+        * moved (see cursor_position).
+        *
+        * Any previously set composing text should be removed.
+        */
+       void (*commit_string)(void *data,
+                             struct wl_text_input *wl_text_input,
+                             uint32_t serial,
+                             const char *text);
+       /**
+        * cursor_position - set cursor to new position
+        * @index: (none)
+        * @anchor: (none)
+        *
+        * Notify when the cursor or anchor position should be modified.
+        *
+        * This event should be handled as part of a following
+        * commit_string event.
+        */
+       void (*cursor_position)(void *data,
+                               struct wl_text_input *wl_text_input,
+                               int32_t index,
+                               int32_t anchor);
+       /**
+        * delete_surrounding_text - delete surrounding text
+        * @index: (none)
+        * @length: (none)
+        *
+        * Notify when the text around the current cursor position should
+        * be deleted.
+        *
+        * Index is relative to the current cursor (in bytes). Length is
+        * the length of deleted text (in bytes).
+        *
+        * This event should be handled as part of a following
+        * commit_string event.
+        */
+       void (*delete_surrounding_text)(void *data,
+                                       struct wl_text_input *wl_text_input,
+                                       int32_t index,
+                                       uint32_t length);
+       /**
+        * keysym - keysym
+        * @serial: serial of the latest known text input state
+        * @time: (none)
+        * @sym: (none)
+        * @state: (none)
+        * @modifiers: (none)
+        *
+        * Notify when a key event was sent. Key events should not be
+        * used for normal text input operations, which should be done with
+        * commit_string, delete_surrounding_text, etc. The key event
+        * follows the wl_keyboard key event convention. Sym is a XKB
+        * keysym, state a wl_keyboard key_state. Modifiers are a mask for
+        * effective modifiers (where the modifier indices are set by the
+        * modifiers_map event)
+        */
+       void (*keysym)(void *data,
+                      struct wl_text_input *wl_text_input,
+                      uint32_t serial,
+                      uint32_t time,
+                      uint32_t sym,
+                      uint32_t state,
+                      uint32_t modifiers);
+       /**
+        * language - language
+        * @serial: serial of the latest known text input state
+        * @language: (none)
+        *
+        * Sets the language of the input text. The "language" argument
+        * is a RFC-3066 format language tag.
+        */
+       void (*language)(void *data,
+                        struct wl_text_input *wl_text_input,
+                        uint32_t serial,
+                        const char *language);
+       /**
+        * text_direction - text direction
+        * @serial: serial of the latest known text input state
+        * @direction: (none)
+        *
+        * Sets the text direction of input text.
+        *
+        * It is mainly needed for showing input cursor on correct side of
+        * the editor when there is no input yet done and making sure
+        * neutral direction text is laid out properly.
+        */
+       void (*text_direction)(void *data,
+                              struct wl_text_input *wl_text_input,
+                              uint32_t serial,
+                              uint32_t direction);
+};
+
+static inline int
+wl_text_input_add_listener(struct wl_text_input *wl_text_input,
+                          const struct wl_text_input_listener *listener, void 
*data)
+{
+       return wl_proxy_add_listener((struct wl_proxy *) wl_text_input,
+                                    (void (**)(void)) listener, data);
+}
+
+#define WL_TEXT_INPUT_ACTIVATE 0
+#define WL_TEXT_INPUT_DEACTIVATE       1
+#define WL_TEXT_INPUT_SHOW_INPUT_PANEL 2
+#define WL_TEXT_INPUT_HIDE_INPUT_PANEL 3
+#define WL_TEXT_INPUT_RESET    4
+#define WL_TEXT_INPUT_SET_SURROUNDING_TEXT     5
+#define WL_TEXT_INPUT_SET_CONTENT_TYPE 6
+#define WL_TEXT_INPUT_SET_CURSOR_RECTANGLE     7
+#define WL_TEXT_INPUT_SET_PREFERRED_LANGUAGE   8
+#define WL_TEXT_INPUT_COMMIT_STATE     9
+#define WL_TEXT_INPUT_INVOKE_ACTION    10
+
+static inline void
+wl_text_input_set_user_data(struct wl_text_input *wl_text_input, void 
*user_data)
+{
+       wl_proxy_set_user_data((struct wl_proxy *) wl_text_input, user_data);
+}
+
+static inline void *
+wl_text_input_get_user_data(struct wl_text_input *wl_text_input)
+{
+       return wl_proxy_get_user_data((struct wl_proxy *) wl_text_input);
+}
+
+static inline void
+wl_text_input_destroy(struct wl_text_input *wl_text_input)
+{
+       wl_proxy_destroy((struct wl_proxy *) wl_text_input);
+}
+
+static inline void
+wl_text_input_activate(struct wl_text_input *wl_text_input, struct wl_seat 
*seat, struct wl_surface *surface)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_ACTIVATE, seat, surface);
+}
+
+static inline void
+wl_text_input_deactivate(struct wl_text_input *wl_text_input, struct wl_seat 
*seat)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_DEACTIVATE, seat);
+}
+
+static inline void
+wl_text_input_show_input_panel(struct wl_text_input *wl_text_input)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_SHOW_INPUT_PANEL);
+}
+
+static inline void
+wl_text_input_hide_input_panel(struct wl_text_input *wl_text_input)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_HIDE_INPUT_PANEL);
+}
+
+static inline void
+wl_text_input_reset(struct wl_text_input *wl_text_input)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_RESET);
+}
+
+static inline void
+wl_text_input_set_surrounding_text(struct wl_text_input *wl_text_input, const 
char *text, uint32_t cursor, uint32_t anchor)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_SET_SURROUNDING_TEXT, text, cursor, 
anchor);
+}
+
+static inline void
+wl_text_input_set_content_type(struct wl_text_input *wl_text_input, uint32_t 
hint, uint32_t purpose)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_SET_CONTENT_TYPE, hint, purpose);
+}
+
+static inline void
+wl_text_input_set_cursor_rectangle(struct wl_text_input *wl_text_input, 
int32_t x, int32_t y, int32_t width, int32_t height)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_SET_CURSOR_RECTANGLE, x, y, width, 
height);
+}
+
+static inline void
+wl_text_input_set_preferred_language(struct wl_text_input *wl_text_input, 
const char *language)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_SET_PREFERRED_LANGUAGE, language);
+}
+
+static inline void
+wl_text_input_commit_state(struct wl_text_input *wl_text_input, uint32_t 
serial)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_COMMIT_STATE, serial);
+}
+
+static inline void
+wl_text_input_invoke_action(struct wl_text_input *wl_text_input, uint32_t 
button, uint32_t index)
+{
+       wl_proxy_marshal((struct wl_proxy *) wl_text_input,
+                        WL_TEXT_INPUT_INVOKE_ACTION, button, index);
+}
+
+#define WL_TEXT_INPUT_MANAGER_CREATE_TEXT_INPUT        0
+
+static inline void
+wl_text_input_manager_set_user_data(struct wl_text_input_manager 
*wl_text_input_manager, void *user_data)
+{
+       wl_proxy_set_user_data((struct wl_proxy *) wl_text_input_manager, 
user_data);
+}
+
+static inline void *
+wl_text_input_manager_get_user_data(struct wl_text_input_manager 
*wl_text_input_manager)
+{
+       return wl_proxy_get_user_data((struct wl_proxy *) 
wl_text_input_manager);
+}
+
+static inline void
+wl_text_input_manager_destroy(struct wl_text_input_manager 
*wl_text_input_manager)
+{
+       wl_proxy_destroy((struct wl_proxy *) wl_text_input_manager);
+}
+
+static inline struct wl_text_input *
+wl_text_input_manager_create_text_input(struct wl_text_input_manager 
*wl_text_input_manager)
+{
+       struct wl_proxy *id;
+
+       id = wl_proxy_marshal_constructor((struct wl_proxy *) 
wl_text_input_manager,
+                        WL_TEXT_INPUT_MANAGER_CREATE_TEXT_INPUT, 
&wl_text_input_interface, NULL);
+
+       return (struct wl_text_input *) id;
+}
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/modules/wl_weekeyboard/text-protocol.c 
b/src/modules/wl_weekeyboard/text-protocol.c
new file mode 100644
index 0000000..c5b3f07
--- /dev/null
+++ b/src/modules/wl_weekeyboard/text-protocol.c
@@ -0,0 +1,92 @@
+/* 
+ * Copyright © 2012, 2013 Intel Corporation
+ * 
+ * Permission to use, copy, modify, distribute, and sell this
+ * software and its documentation for any purpose is hereby granted
+ * without fee, provided that the above copyright notice appear in
+ * all copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * the copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ * 
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+extern const struct wl_interface wl_seat_interface;
+extern const struct wl_interface wl_surface_interface;
+extern const struct wl_interface wl_text_input_interface;
+
+static const struct wl_interface *types[] = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       &wl_seat_interface,
+       &wl_surface_interface,
+       &wl_seat_interface,
+       &wl_surface_interface,
+       &wl_text_input_interface,
+};
+
+static const struct wl_message wl_text_input_requests[] = {
+       { "activate", "oo", types + 5 },
+       { "deactivate", "o", types + 7 },
+       { "show_input_panel", "", types + 0 },
+       { "hide_input_panel", "", types + 0 },
+       { "reset", "", types + 0 },
+       { "set_surrounding_text", "suu", types + 0 },
+       { "set_content_type", "uu", types + 0 },
+       { "set_cursor_rectangle", "iiii", types + 0 },
+       { "set_preferred_language", "s", types + 0 },
+       { "commit_state", "u", types + 0 },
+       { "invoke_action", "uu", types + 0 },
+};
+
+static const struct wl_message wl_text_input_events[] = {
+       { "enter", "o", types + 8 },
+       { "leave", "", types + 0 },
+       { "modifiers_map", "a", types + 0 },
+       { "input_panel_state", "u", types + 0 },
+       { "preedit_string", "uss", types + 0 },
+       { "preedit_styling", "uuu", types + 0 },
+       { "preedit_cursor", "i", types + 0 },
+       { "commit_string", "us", types + 0 },
+       { "cursor_position", "ii", types + 0 },
+       { "delete_surrounding_text", "iu", types + 0 },
+       { "keysym", "uuuuu", types + 0 },
+       { "language", "us", types + 0 },
+       { "text_direction", "uu", types + 0 },
+};
+
+WL_EXPORT const struct wl_interface wl_text_input_interface = {
+       "wl_text_input", 1,
+       11, wl_text_input_requests,
+       13, wl_text_input_events,
+};
+
+static const struct wl_message wl_text_input_manager_requests[] = {
+       { "create_text_input", "n", types + 9 },
+};
+
+WL_EXPORT const struct wl_interface wl_text_input_manager_interface = {
+       "wl_text_input_manager", 1,
+       1, wl_text_input_manager_requests,
+       0, NULL,
+};
+
diff --git a/src/modules/wl_weekeyboard/themes/default/default.edc 
b/src/modules/wl_weekeyboard/themes/default/default.edc
new file mode 100644
index 0000000..8b976e9
--- /dev/null
+++ b/src/modules/wl_weekeyboard/themes/default/default.edc
@@ -0,0 +1,1118 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ * Copyright © 2014 Jaguar Landrover
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+images {
+   image: "icon-backspace.png" COMP;
+   image: "icon-enter.png" COMP;
+   image: "icon-language.png" COMP;
+   image: "icon-shift-active.png" COMP;
+   image: "icon-shift.png" COMP;
+   image: "icon-space.png" COMP;
+
+   image: "key-default.png" COMP;
+   image: "key-default-pressed.png" COMP;
+   image: "key-hint.png" COMP;
+   image: "key-hint-bg.png" COMP;
+   image: "key-special.png" COMP;
+   image: "key-special-pressed.png" COMP;
+}
+
+fonts {
+   font: "SourceSansPro-Regular.ttf" "Regular";
+   font: "SourceSansPro-Semibold.ttf" "Semibold";
+}
+
+data {
+   file: "ignore-keys" "ignorekeys.txt";
+}
+
+collections {
+   group {
+      name: "main";
+
+      min: MIN_WIDTH MIN_HEIGHT;
+      max: MAX_WIDTH MAX_HEIGHT;
+
+      parts {
+         part {
+            name: "rect_bg";
+            mouse_events: 0;
+            type: RECT;
+            description {
+               state: "default" 0.0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: -1 -1;
+               }
+            }
+         }
+
+         part {
+            name: "background";
+            mouse_events: 1;
+            pointer_mode: NOGRAB;
+            type: RECT;
+            description {
+               state: "default" 0.0;
+               color: 214 215 218 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 0 (150*SCALE);
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: -1 -1;
+               }
+            }
+         }
+      }
+
+#define KEY_GROUP(_name)                                               \
+      parts {                                                          \
+         part {                                                        \
+            name: _name"_clip";                                        \
+            type: RECT;                                                \
+            description {                                              \
+               state: "default" 0.0;                                   \
+               rel1 {                                                  \
+                  relative: 0.0 0.0;                                   \
+                  offset: 0 0;                                         \
+               }                                                       \
+               rel2 {                                                  \
+                  relative: 1.0 1.0;                                   \
+                  offset: -1 -1;                                       \
+               }                                                       \
+            }                                                          \
+            description {                                              \
+               state: "hidden" 0.0;                                    \
+               inherit: "default" 0.0;                                 \
+               visible: 0;                                             \
+            }                                                          \
+         }                                                             \
+         part {                                                        \
+            name: _name;                                               \
+            type: GROUP;                                               \
+            source: _name;                                             \
+            clip_to: _name"_clip";                                     \
+            description {                                              \
+               state: "default" 0.0;                                   \
+               rel1 {                                                  \
+                  to: "background";                                    \
+                  relative: 0.0 0.0;                                   \
+                  offset: (5*SCALE) (10*SCALE);                        \
+               }                                                       \
+               rel2 {                                                  \
+                  to: "background";                                    \
+                  relative: 1.0 1.0;                                   \
+                  offset: -1 -1;                                       \
+               }                                                       \
+            }                                                          \
+         }                                                             \
+      }                                                                \
+      programs {                                                       \
+         program {                                                     \
+            name: "show-"_name;                                        \
+            action: STATE_SET "default" 0.0;                           \
+            target: _name"_clip";                                      \
+         }                                                             \
+         program {                                                     \
+            name: "hide-"_name;                                        \
+            action: STATE_SET "hidden" 0.0;                            \
+            target: _name"_clip";                                      \
+         }                                                             \
+      }
+
+      KEY_GROUP("alphanum")
+      KEY_GROUP("numeric")
+      KEY_GROUP("special-1")
+      KEY_GROUP("special-2")
+      KEY_GROUP("fixed")
+
+      programs {
+         program {
+            name: "alphanum_show";
+            signal: "show,alphanumeric";
+            after: "show-alphanum";
+            after: "hide-numeric";
+            after: "hide-special-1";
+            after: "hide-special-2";
+            after: "show-fixed";
+         }
+
+         program {
+            name: "numeric_show";
+            signal: "show,numeric";
+            after: "show-numeric";
+            after: "hide-alphanum";
+            after: "hide-special-1";
+            after: "hide-special-2";
+            after: "hide-fixed";
+         }
+
+         program {
+            name: "special-1_show";
+            signal: "show,special,1";
+            after: "show-special-1";
+            after: "hide-numeric";
+            after: "hide-alphanum";
+            after: "hide-special-2";
+            after: "show-fixed";
+         }
+
+         program {
+            name: "special-2_show";
+            signal: "show,special,2";
+            after: "show-special-2";
+            after: "hide-numeric";
+            after: "hide-alphanum";
+            after: "hide-special-1";
+            after: "show-fixed";
+         }
+
+         program {
+            name: "?123_clicked";
+            signal: "key_down";
+            source: "alphanum:?123";
+            after: "special-1_show";
+         }
+         program {
+            name: "special-1_abc_clicked";
+            signal: "key_down";
+            source: "special-1:abc";
+            after: "alphanum_show";
+         }
+         program {
+            name: "special-2_abc_clicked";
+            signal: "key_down";
+            source: "special-2:abc";
+            after: "alphanum_show";
+         }
+         program {
+            name: "1/2_clicked";
+            signal: "key_down";
+            source: "special-1:1/2";
+            after: "special-2_show";
+         }
+         program {
+            name: "2/2_clicked";
+            signal: "key_down";
+            source: "special-2:2/2";
+            after: "special-1_show";
+         }
+         program {
+            name: "init";
+            signal: "show";
+            after: "alphanum_show";
+         }
+      }
+   }
+
+   group {
+      name: "alphanum";
+
+#define MOUSE_DOWN_UP_SCRIPTS                                          \
+          public shift_pressed = 0;                                    \
+          public mouse_down = 0;                                       \
+          public long_press_timer = 0;                                 \
+          public long_press = 0;                                       \
+          public pressed_key;                                          \
+                                                                       \
+          public _set_long_press(val) {                                \
+             new _cur[20];                                             \
+             new _timer;                                               \
+             _timer = get_int(long_press_timer);                       \
+             if (_timer) {                                             \
+                cancel_timer(_timer);                                  \
+                set_int(long_press_timer, 0);                          \
+             }                                                         \
+             set_int(long_press, val);                                 \
+             if (!val)                                                 \
+                return;                                                \
+             get_str(pressed_key, _cur, 20);                           \
+             if (strlen(_cur) > 0) {                                   \
+                emit("long_press", _cur);                              \
+             }                                                         \
+          }                                                            \
+                                                                       \
+          _set_key_pressed(_key[]) {                                   \
+             new _cur[20];                                             \
+             new _prg[30];                                             \
+             new _timer;                                               \
+             get_str(pressed_key, _cur, 20);                           \
+             if (strlen(_cur) > 0) {                                   \
+                _set_key_released(_cur);                               \
+             }                                                         \
+             set_str(pressed_key, _key);                               \
+             _timer = timer(0.5, "_set_long_press", 1);                \
+             set_int(long_press_timer, _timer);                        \
+             snprintf(_prg, 30, "key-press-%s", _key);                 \
+             run_program(get_program_id(_prg));                        \
+          }                                                            \
+                                                                       \
+          _set_key_released(_key[]) {                                  \
+             new _prg[30];                                             \
+             _set_long_press(0);                                       \
+             set_str(pressed_key, "");                                 \
+             snprintf(_prg, 30, "key-release-%s", _key);               \
+             run_program(get_program_id(_prg));                        \
+          }                                                            \
+
+#define MOUSE_DOWN_UP_PROGRAMS                                         \
+         program {                                                     \
+            name: "mouse-down";                                        \
+            signal: "mouse,down,1";                                    \
+            source: "*";                                               \
+            script {                                                   \
+               set_int(mouse_down, 1);                                 \
+            }                                                          \
+         }                                                             \
+         program {                                                     \
+            name: "mouse-up";                                          \
+            signal: "mouse,up,1";                                      \
+            source: "*";                                               \
+            script {                                                   \
+               set_int(mouse_down, 0);                                 \
+            }                                                          \
+         }
+
+      script {
+         MOUSE_DOWN_UP_SCRIPTS
+      }
+      programs {
+         MOUSE_DOWN_UP_PROGRAMS
+      }
+      parts {
+#undef INIT_HSPACE
+#define INIT_HSPACE 5
+#define KEY_WIDTH (65*SCALE)
+#define KEY_HEIGHT (90*SCALE)
+#define COL_SPACE 5
+#define KEY_OFFSET(index) ((COL_SPACE+KEY_WIDTH)*index)+INIT_HSPACE
+
+#define FIRST_ROW 0
+#define ROW_SPACE (20*SCALE)
+
+#define SKEY_FULL(key_low, key_up, key_name, key_alt, x, y)            \
+         part {                                                        \
+            name: "key-img-"key_name;                                  \
+            type: IMAGE;                                               \
+            mouse_events: 0;                                           \
+            description {                                              \
+               state: "default" 0.0;                                   \
+               min: KEY_WIDTH KEY_HEIGHT;                              \
+               max: KEY_WIDTH KEY_HEIGHT;                              \
+               fixed: 1 1;                                             \
+               rel1 {                                                  \
+                  relative: 0.0 0.0;                                   \
+                  offset: (x) (y);                                     \
+               }                                                       \
+               rel2 {                                                  \
+                  relative: 0.0 0.0;                                   \
+                  offset: (x+KEY_WIDTH-1) (y+KEY_HEIGHT-1);            \
+               }                                                       \
+               image {                                                 \
+                  normal: "key-default.png";                           \
+                  border: 8 8 10 10;                                   \
+               }                                                       \
+            }                                                          \
+            description {                                              \
+               state: "down" 0.0;                                      \
+               inherit: "default" 0.0;                                 \
+               rel1.offset: (x+1) (y+1);                               \
+               rel2.offset: (x+1+KEY_WIDTH-1) (y+1+KEY_HEIGHT-1);      \
+               image.normal: "key-default-pressed.png";                \
+            }                                                          \
+         }                                                             \
+         part {                                                        \
+            name: "key-bg-"key_name;                                   \
+            type: RECT;                                                \
+            pointer_mode: NOGRAB;                                      \
+            description {                                              \
+               state: "default" 0.0;                                   \
+               color: 0 0 0 0;                                         \
+               rel1 {                                                  \
+                  to: "key-img-"key_name;                              \
+                  relative: 0.0 0.0;                                   \
+                  offset: 3 2;                                         \
+               }                                                       \
+               rel2 {                                                  \
+                  to: "key-img-"key_name;                              \
+                  relative: 1.0 1.0;                                   \
+                  offset: -4 -6;                                       \
+               }                                                       \
+            }                                                          \
+         }                                                             \
+         part {                                                        \
+           name: "key-lbl-"key_name;                                   \
+           type: TEXT;                                                 \
+           mouse_events: 0;                                            \
+           effect: SHADOW BOTTOM;                                      \
+           description {                                               \
+              state: "default" 0.0;                                    \
+              color: 63 67 72 255;                                     \
+              color2: 240 240 240 255;                                 \
+              color3: 240 240 240 255;                                 \
+              rel1 {                                                   \
+                 to: "key-bg-"key_name;                                \
+                 relative: 0.0 0.4;                                    \
+              }                                                        \
+              rel2 {                                                   \
+                 to: "key-bg-"key_name;                                \
+                 relative: 1.0 0.9;                                    \
+              }                                                        \
+              text {                                                   \
+                 font: "Regular";                                      \
+                 size: (44*SCALE);                                     \
+                 text: key_low;                                        \
+              }                                                        \
+            }                                                          \
+         }                                                             \
+         part {                                                        \
+           name: "key-lbl-alt-"key_name;                               \
+           type: TEXT;                                                 \
+           mouse_events: 0;                                            \
+           effect: SHADOW BOTTOM;                                      \
+           description {                                               \
+              state: "default" 0.0;                                    \
+              color: 63 67 72 255;                                     \
+              color2: 240 240 240 255;                                 \
+              color3: 240 240 240 255;                                 \
+              rel1 {                                                   \
+                 to: "key-bg-"key_name;                                \
+                 relative: 0.0 0.1;                                    \
+              }                                                        \
+              rel2 {                                                   \
+                 to: "key-bg-"key_name;                                \
+                 relative: 1.0 0.4;                                    \
+              }                                                        \
+              text {                                                   \
+                 font: "Regular";                                      \
+                 size: (22*SCALE);                                     \
+                 align: 0.8 0.0;                                       \
+                 text: key_alt;                                        \
+              }                                                        \
+            }                                                          \
+         }                                                             \
+         part {                                                        \
+            name: "key-img-hint-"key_name;                             \
+            type: IMAGE;                                               \
+            mouse_events: 0;                                           \
+            description {                                              \
+               state: "default" 0.0;                                   \
+               min: KEY_WIDTH KEY_HEIGHT;                              \
+               max: KEY_WIDTH KEY_HEIGHT;                              \
+               fixed: 1 1;                                             \
+               rel1 {                                                  \
+                  to: "key-img-"key_name;                              \
+                  relative: 0.0 0.0;                                   \
+                  offset: 0 ((-20*SCALE)-KEY_HEIGHT);                  \
+               }                                                       \
+               rel2 {                                                  \
+                  to: "key-img-"key_name;                              \
+                  relative: 1.0 0.0;                                   \
+                  offset: 0 (-20*SCALE);                               \
+               }                                                       \
+               image {                                                 \
+                  normal: "key-hint.png";                              \
+                  border: 8 8 10 10;                                   \
+               }                                                       \
+               visible: 0;                                             \
+            }                                                          \
+            description {                                              \
+               state: "down" 0.0;                                      \
+               inherit: "default" 0.0;                                 \
+               visible: 1;                                             \
+            }                                                          \
+         }                                                             \
+         part {                                                        \
+            name: "key-lbl-hint-"key_name;                             \
+            type: TEXT;                                                \
+            mouse_events: 0;                                           \
+            effect: SHADOW BOTTOM;                                     \
+            description {                                              \
+               state: "default" 0.0;                                   \
+               color: 63 67 72 255;                                    \
+               color2: 240 240 240 255;                                \
+               color3: 240 240 240 255;                                \
+               rel1 {                                                  \
+                  to: "key-img-hint-"key_name;                         \
+                  relative: 0.0 0.0;                                   \
+               }                                                       \
+               rel2 {                                                  \
+                  to: "key-img-hint-"key_name;                         \
+                  relative: 1.0 1.0;                                   \
+               }                                                       \
+               text {                                                  \
+                  font: "Regular";                                     \
+                  size: (48*SCALE);                                    \
+                  text: key_low;                                       \
+               }                                                       \
+               visible: 0;                                             \
+            }                                                          \
+            description {                                              \
+               state: "down" 0.0;                                      \
+               inherit: "default" 0.0;                                 \
+               visible: 1;                                             \
+            }                                                          \
+         }                                                             \
+         programs {                                                    \
+            program {                                                  \
+               name: "key-mouse-in-"key_name;                          \
+               signal: "mouse,in";                                     \
+               source: "key-bg-"key_name;                              \
+               script {                                                \
+                  if (get_int(mouse_down) == 0)                        \
+                     return;                                           \
+                  _set_key_pressed(key_name);                          \
+               }                                                       \
+            }                                                          \
+            program {                                                  \
+               name: "key-mouse-out-"key_name;                         \
+               signal: "mouse,out";                                    \
+               source: "key-bg-"key_name;                              \
+               script {                                                \
+                  if (get_int(mouse_down) == 0)                        \
+                     return;                                           \
+                  _set_key_released(key_name);                         \
+               }                                                       \
+            }                                                          \
+            program {                                                  \
+               name: "key-mouse-down-"key_name;                        \
+               signal: "mouse,down,1";                                 \
+               source: "key-bg-"key_name;                              \
+               script {                                                \
+                  _set_key_pressed(key_name);                          \
+               }                                                       \
+            }                                                          \
+            program {                                                  \
+               name: "key-mouse-up-"key_name;                          \
+               signal: "mouse,up,1";                                   \
+               source: "key-bg-"key_name;                              \
+               script {                                                \
+                  if (get_int(long_press) == 0) {                      \
+                     if (get_int(shift_pressed) == 0)                  \
+                        emit("key_down", key_low);                     \
+                     else                                              \
+                        emit("key_down", key_up);                      \
+                  } else {                                             \
+                     if (strcmp(key_alt, " "))                         \
+                        emit("key_down", key_alt);                     \
+                     else if (get_int(shift_pressed) == 0)             \
+                        emit("key_down", key_low);                     \
+                     else                                              \
+                        emit("key_down", key_up);                      \
+                  }                                                    \
+                  _set_key_released(key_name);                         \
+               }                                                       \
+            }                                                          \
+            program {                                                  \
+               name: "key-press-"key_name;                             \
+               action: STATE_SET "down" 0.0;                           \
+               target: "key-img-"key_name;                             \
+               target: "key-img-hint-"key_name;                        \
+               target: "key-lbl-hint-"key_name;                        \
+            }                                                          \
+            program {                                                  \
+               name: "key-release-"key_name;                           \
+               action: STATE_SET "default" 0.0;                        \
+               transition: LINEAR 0.2;                                 \
+               target: "key-img-"key_name;                             \
+               target: "key-img-hint-"key_name;                        \
+               target: "key-lbl-hint-"key_name;                        \
+               after: "shift-pressed-"key_name;                        \
+            }                                                          \
+            program {                                                  \
+               name: "long-press-"key_name;                            \
+               signal: "long_press";                                   \
+               source: key_name;                                       \
+               script {                                                \
+                  if (strcmp(key_alt, " "))                            \
+                     set_text(PART:"key-lbl-hint-"key_name, key_alt);  \
+               }                                                       \
+            }                                                          \
+            program {                                                  \
+               name: "shift-pressed-"key_name;                         \
+               signal: "key_down";                                     \
+               source: "shift";                                        \
+               script {                                                \
+                  if (get_int(shift_pressed) == 0) {                   \
+                     set_text(PART:"key-lbl-"key_name, key_low);       \
+                     set_text(PART:"key-lbl-hint-"key_name, key_low);  \
+                  } else {                                             \
+                     set_text(PART:"key-lbl-"key_name, key_up);        \
+                     set_text(PART:"key-lbl-hint-"key_name, key_up);   \
+                  }                                                    \
+               }                                                       \
+            }                                                          \
+         }
+#define KEY_FULL(low, up, alt, x, y) SKEY_FULL(low, up, low, alt, x, y)
+#define SKEY(name, text, alt, x, y) SKEY_FULL(name, name, text, alt, x, y)
+#define KEY(v, alt, x, y) SKEY(v, v, alt, x, y)
+
+         KEY_FULL("q", "Q", "1", KEY_OFFSET(0), FIRST_ROW)
+         KEY_FULL("w", "W", "2", KEY_OFFSET(1), FIRST_ROW)
+         KEY_FULL("e", "E", "3", KEY_OFFSET(2), FIRST_ROW)
+         KEY_FULL("r", "R", "4", KEY_OFFSET(3), FIRST_ROW)
+         KEY_FULL("t", "T", "5", KEY_OFFSET(4), FIRST_ROW)
+         KEY_FULL("y", "Y", "6", KEY_OFFSET(5), FIRST_ROW)
+         KEY_FULL("u", "U", "7", KEY_OFFSET(6), FIRST_ROW)
+         KEY_FULL("i", "I", "8", KEY_OFFSET(7), FIRST_ROW)
+         KEY_FULL("o", "O", "9", KEY_OFFSET(8), FIRST_ROW)
+         KEY_FULL("p", "P", "0", KEY_OFFSET(9), FIRST_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (45*SCALE)
+#define SECOND_ROW FIRST_ROW+KEY_HEIGHT+ROW_SPACE
+
+         KEY_FULL("a", "A", "-", KEY_OFFSET(0), SECOND_ROW)
+         KEY_FULL("s", "S", "@", KEY_OFFSET(1), SECOND_ROW)
+         KEY_FULL("d", "D", "*", KEY_OFFSET(2), SECOND_ROW)
+         KEY_FULL("f", "F", "^", KEY_OFFSET(3), SECOND_ROW)
+         KEY_FULL("g", "G", ":", KEY_OFFSET(4), SECOND_ROW)
+         KEY_FULL("h", "H", ";", KEY_OFFSET(5), SECOND_ROW)
+         KEY_FULL("j", "J", "(", KEY_OFFSET(6), SECOND_ROW)
+         KEY_FULL("k", "K", ")", KEY_OFFSET(7), SECOND_ROW)
+         KEY_FULL("l", "L", "~", KEY_OFFSET(8), SECOND_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (110*SCALE)
+#define THIRD_ROW SECOND_ROW+KEY_HEIGHT+ROW_SPACE
+
+         KEY_FULL("z", "Z", "/",  KEY_OFFSET(0), THIRD_ROW)
+         KEY_FULL("x", "X", "'",  KEY_OFFSET(1), THIRD_ROW)
+         KEY_FULL("c", "C", "\"", KEY_OFFSET(2), THIRD_ROW)
+         KEY_FULL("v", "V", ".",  KEY_OFFSET(3), THIRD_ROW)
+         KEY_FULL("b", "B", ",",  KEY_OFFSET(4), THIRD_ROW)
+         KEY_FULL("n", "N", "?",  KEY_OFFSET(5), THIRD_ROW)
+         KEY_FULL("m", "M", "!",  KEY_OFFSET(6), THIRD_ROW)
+
+#define KEY_SPECIAL(val, x, y, w)                                      \
+         part {                                                        \
+            name: "key-img-"val;                                       \
+            type: IMAGE;                                               \
+            mouse_events: 0;                                           \
+            description {                                              \
+               state: "default" 0.0;                                   \
+               min: w KEY_HEIGHT;                                      \
+               max: w KEY_HEIGHT;                                      \
+               fixed: 1 1;                                             \
+               rel1 {                                                  \
+                  relative: 0.0 0.0;                                   \
+                  offset: (x) (y);                                     \
+               }                                                       \
+               rel2 {                                                  \
+                  relative: 0.0 0.0;                                   \
+                  offset: (x+w-1) (y+KEY_HEIGHT-1);                    \
+               }                                                       \
+               image {                                                 \
+                  normal: "key-special.png";                           \
+                  border: 8 8 10 10;                                   \
+               }                                                       \
+            }                                                          \
+            description {                                              \
+               state: "down" 0.0;                                      \
+               inherit: "default" 0.0;                                 \
+               rel1.offset: (x+1) (y+1);                               \
+               rel2.offset: (x+1+w-1) (y+1+KEY_HEIGHT-1);              \
+               image.normal: "key-special-pressed.png";                \
+            }                                                          \
+         }                                                             \
+         part {                                                        \
+            name: "key-bg-"val;                                        \
+            type: RECT;                                                \
+            pointer_mode: NOGRAB;                                      \
+            description {                                              \
+               state: "default" 0.0;                                   \
+               rel1 {                                                  \
+                  to: "key-img-"val;                                   \
+                  relative: 0.0 0.0;                                   \
+                  offset: 3 2;                                         \
+               }                                                       \
+               rel2 {                                                  \
+                  to: "key-img-"val;                                   \
+                  relative: 1.0 1.0;                                   \
+                  offset: -4 -6;                                       \
+               }                                                       \
+               color: 0 0 0 0;                                         \
+            }                                                          \
+         }                                                             \
+         programs {                                                    \
+            program {                                                  \
+               name: "key-mouse-up-"val;                               \
+               signal: "mouse,up,1";                                   \
+               source: "key-bg-"val;                                   \
+               script {                                                \
+                  emit("key_down", val);                               \
+                  _set_key_released(val);                              \
+                  emit("key_up", val);                                 \
+               }                                                       \
+            }                                                          \
+            program {                                                  \
+               name: "key-mouse-in-"val;                               \
+               signal: "mouse,in";                                     \
+               source: "key-bg-"val;                                   \
+               script {                                                \
+                  if (get_int(mouse_down) == 0)                        \
+                     return;                                           \
+                  _set_key_pressed(val);                               \
+               }                                                       \
+            }                                                          \
+            program {                                                  \
+               name: "key-mouse-out-"val;                              \
+               signal: "mouse,out";                                    \
+               source: "key-bg-"val;                                   \
+               script {                                                \
+                  if (get_int(mouse_down) == 0)                        \
+                     return;                                           \
+                  _set_key_released(val);                              \
+                  emit("key_up", val);                                 \
+               }                                                       \
+            }                                                          \
+            program {                                                  \
+               name: "key-mouse-down-"val;                             \
+               signal: "mouse,down,1";                                 \
+               source: "key-bg-"val;                                   \
+               script {                                                \
+                  _set_key_pressed(val);                               \
+               }                                                       \
+            }                                                          \
+            program {                                                  \
+               name: "key-press-"val;                                  \
+               action: STATE_SET "down" 0.0;                           \
+               target: "key-img-"val;                                  \
+               target: "key-lbl-"val;                                  \
+            }                                                          \
+            program {                                                  \
+               name: "key-release-"val;                                \
+               action: STATE_SET "default" 0.0;                        \
+               transition: LINEAR 0.2;                                 \
+               target: "key-img-"val;                                  \
+               target: "key-lbl-"val;                                  \
+            }                                                          \
+         }
+
+#define KEY_SPECIAL_TEXT(val, x, y, w)                                 \
+         KEY_SPECIAL(val, x, y, w)                                     \
+         part {                                                        \
+            name: "key-lbl-"val;                                       \
+            type: TEXT;                                                \
+            mouse_events: 0;                                           \
+            effect: SHADOW BOTTOM;                                     \
+            description {                                              \
+               state: "default" 0.0;                                   \
+               color: 63 67 72 255;                                    \
+               color2: 240 240 240 255;                                \
+               color3: 240 240 240 255;                                \
+               rel1 {                                                  \
+                  to: "key-bg-"val;                                    \
+                  relative: 0.0 0.4;                                   \
+               }                                                       \
+               rel2 {                                                  \
+                  to: "key-bg-"val;                                    \
+                  relative: 1.0 1.0;                                   \
+               }                                                       \
+               text {                                                  \
+                  font: "Semibold";                                    \
+                  size: (34*SCALE);                                    \
+                  text: val;                                           \
+               }                                                       \
+            }                                                          \
+         }
+
+#define KEY_SPECIAL_ICON(val, x, y, w, icon_size)                      \
+         KEY_SPECIAL(val, x, y, w)                                     \
+         part {                                                        \
+           name: "key-lbl-"val;                                        \
+           type: IMAGE;                                                \
+           mouse_events: 0;                                            \
+           description {                                               \
+              state: "default" 0.0;                                    \
+              min: icon_size icon_size;                                \
+              max: icon_size icon_size;                                \
+              fixed: 1 1;                                              \
+              rel1 {                                                   \
+                 to: "key-bg-"val;                                     \
+                 relative: 0.5 0.4;                                    \
+              }                                                        \
+              rel2 {                                                   \
+                 to: "key-bg-"val;                                     \
+                 relative: 0.5 0.8;                                    \
+              }                                                        \
+              image.normal: "icon-"val".png";                          \
+            }                                                          \
+         }                                                             \
+
+#define FOURTH_ROW THIRD_ROW+KEY_HEIGHT+ROW_SPACE
+         KEY_SPECIAL_TEXT("?123", (5*SCALE), FOURTH_ROW, (95*SCALE))
+
+         part {
+            name: "key-img-shift";
+            type: IMAGE;
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               min: (85*SCALE) KEY_HEIGHT;
+               max: (85*SCALE) KEY_HEIGHT;
+               fixed: 1 1;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: (5*SCALE) (THIRD_ROW);
+               }
+               rel2 {
+                  relative: 0.0 0.0;
+                  offset: (((5+85)*SCALE)-1) (THIRD_ROW+KEY_HEIGHT-1);
+               }
+               image {
+                  normal: "key-special.png";
+                  border: 8 8 10 10;
+               }
+            }
+            description {
+               state: "down" 0.0;
+               inherit: "default" 0.0;
+               rel1.offset: ((5*SCALE)+2) (THIRD_ROW+2);
+               rel2.offset: ((((5+85)*SCALE)+2)-1) (THIRD_ROW+2+KEY_HEIGHT-1);
+               image.normal: "key-special-pressed.png";
+            }
+         }
+         part {
+            name: "key-bg-shift";
+            type: RECT;
+            pointer_mode: NOGRAB;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  to: "key-img-shift";
+                  relative: 0.0 0.0;
+                  offset: 3 2;
+               }
+               rel2 {
+                  to: "key-img-shift";
+                  relative: 1.0 1.0;
+                  offset: -4 -6;
+               }
+               color: 0 0 0 0;
+            }
+         }
+         part {
+           name: "key-lbl-shift";
+           type: IMAGE;
+           mouse_events: 0;
+           description {
+              state: "default" 0.0;
+              max: (50*SCALE) (50*SCALE);
+              min: (50*SCALE) (50*SCALE);
+              fixed: 1 1;
+              rel1 {
+                 to: "key-bg-shift";
+                 relative: 0.5 0.4;
+              }
+              rel2 {
+                 to: "key-bg-shift";
+                 relative: 0.5 0.8;
+              }
+              image.normal: "icon-shift.png";
+            }
+            description {
+               state: "down" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon-shift-active.png";
+            }
+         }
+         programs {
+            program {
+               name: "key-press-shift";
+               signal: "mouse,down,1";
+               source: "key-bg-shift";
+               action: STATE_SET "down" 0.0;
+               target: "key-img-shift";
+               target: "key-lbl-shift";
+            }
+            program {
+               name: "key-release-shift";
+               action: STATE_SET "default" 0.0;
+               transition: LINEAR 0.2;
+               target: "key-img-shift";
+               target: "key-lbl-shift";
+            }
+            program {
+               name: "key-mouse-in-shift";
+               signal: "mouse,in";
+               source: "key-bg-shift";
+               script {
+                  if (get_int(mouse_down) == 0)
+                     return;
+                  run_program(PROGRAM:"key-press-shift");
+               }
+            }
+            program {
+               name: "key-mouse-out-shift";
+               signal: "mouse,out";
+               source: "key-bg-shift";
+               script {
+                  if (get_int(mouse_down) == 0)
+                     return;
+                  run_program(PROGRAM:"key-release-shift");
+               }
+            }
+            program {
+               name: "key-down-shift";
+               signal: "mouse,up,1";
+               source: "key-bg-shift";
+               script {
+                  emit("key_down", "shift");
+                  if (get_int(shift_pressed) == 0) {
+                     run_program(PROGRAM:"key-press-shift");
+                     set_int(shift_pressed, 1);
+                  } else {
+                     run_program(PROGRAM:"key-release-shift");
+                     set_int(shift_pressed, 0);
+                  }
+               }
+            }
+         }
+      }
+   }
+
+   group {
+      name: "special-1";
+
+      script {
+         MOUSE_DOWN_UP_SCRIPTS
+      }
+      programs {
+         MOUSE_DOWN_UP_PROGRAMS
+      }
+      parts {
+#undef INIT_HSPACE
+#define INIT_HSPACE 5
+
+         KEY("1", "#",  KEY_OFFSET(0), FIRST_ROW)
+         KEY("2", "&",  KEY_OFFSET(1), FIRST_ROW)
+         KEY("3", "%",  KEY_OFFSET(2), FIRST_ROW)
+         KEY("4", "+",  KEY_OFFSET(3), FIRST_ROW)
+         KEY("5", "=",  KEY_OFFSET(4), FIRST_ROW)
+         KEY("6", "_",  KEY_OFFSET(5), FIRST_ROW)
+         KEY("7", "\\", KEY_OFFSET(6), FIRST_ROW)
+         KEY("8", "|",  KEY_OFFSET(7), FIRST_ROW)
+         KEY("9", "<",  KEY_OFFSET(8), FIRST_ROW)
+         KEY("0", ">",  KEY_OFFSET(9), FIRST_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (45*SCALE)
+
+         SKEY("-", "dash",       "{", KEY_OFFSET(0), SECOND_ROW)
+         SKEY("@", "at",         "}", KEY_OFFSET(1), SECOND_ROW)
+         SKEY("*", "star",       "[", KEY_OFFSET(2), SECOND_ROW)
+         SKEY("^", "circumflex", "]", KEY_OFFSET(3), SECOND_ROW)
+         SKEY(":", "colon",      "$", KEY_OFFSET(4), SECOND_ROW)
+         SKEY(";", "semi_colon", "£", KEY_OFFSET(5), SECOND_ROW)
+         SKEY("(", "open_par",   "¥", KEY_OFFSET(6), SECOND_ROW)
+         SKEY(")", "close_par",  "€", KEY_OFFSET(7), SECOND_ROW)
+         SKEY("~", "tilde",      "₩", KEY_OFFSET(8), SECOND_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (110*SCALE)
+
+         SKEY("/",  "slash",        "¢", KEY_OFFSET(0), THIRD_ROW)
+         SKEY("'",  "single_quote", "`", KEY_OFFSET(1), THIRD_ROW)
+         SKEY("\"", "double_quote", "°", KEY_OFFSET(2), THIRD_ROW)
+         SKEY(".",  "dot",          "˙", KEY_OFFSET(3), THIRD_ROW)
+         SKEY(",",  "comma",        "®", KEY_OFFSET(4), THIRD_ROW)
+         SKEY("?",  "question",     "©", KEY_OFFSET(5), THIRD_ROW)
+         SKEY("!",  "exclamation",  "¿", KEY_OFFSET(6), THIRD_ROW)
+
+         KEY_SPECIAL_TEXT("1/2", (5*SCALE), THIRD_ROW, (85*SCALE))
+         KEY_SPECIAL_TEXT("abc", (5*SCALE), FOURTH_ROW, (95*SCALE))
+      }
+   }
+
+   group {
+      name: "special-2";
+
+      script {
+         MOUSE_DOWN_UP_SCRIPTS
+      }
+      programs {
+         MOUSE_DOWN_UP_PROGRAMS
+      }
+      parts {
+#undef INIT_HSPACE
+#define INIT_HSPACE 5
+
+         SKEY("#",  "hash",      "1", KEY_OFFSET(0), FIRST_ROW)
+         SKEY("&",  "amp",       "2", KEY_OFFSET(1), FIRST_ROW)
+         SKEY("%",  "percent",   "3", KEY_OFFSET(2), FIRST_ROW)
+         SKEY("+",  "plus",      "4", KEY_OFFSET(3), FIRST_ROW)
+         SKEY("=",  "equal",     "5", KEY_OFFSET(4), FIRST_ROW)
+         SKEY("_",  "underline", "6", KEY_OFFSET(5), FIRST_ROW)
+         SKEY("\\", "backslash", "7", KEY_OFFSET(6), FIRST_ROW)
+         SKEY("|",  "vert_bar",  "8", KEY_OFFSET(7), FIRST_ROW)
+         SKEY("<",  "less",      "9", KEY_OFFSET(8), FIRST_ROW)
+         SKEY(">",  "greater",   "0", KEY_OFFSET(9), FIRST_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (45*SCALE)
+
+         SKEY("{", "open_brace",    "-", KEY_OFFSET(0), SECOND_ROW)
+         SKEY("}", "close_brace",   "@", KEY_OFFSET(1), SECOND_ROW)
+         SKEY("[", "open_bracket",  "*", KEY_OFFSET(2), SECOND_ROW)
+         SKEY("]", "close_bracket", "^", KEY_OFFSET(3), SECOND_ROW)
+         SKEY("$", "dollar",        ":", KEY_OFFSET(4), SECOND_ROW)
+         SKEY("£", "sterling",      ";", KEY_OFFSET(5), SECOND_ROW)
+         SKEY("¥", "yen",           "(", KEY_OFFSET(6), SECOND_ROW)
+         SKEY("€", "euro",          ")", KEY_OFFSET(7), SECOND_ROW)
+         SKEY("₩", "won",           "~", KEY_OFFSET(8), SECOND_ROW)
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (110*SCALE)
+
+         SKEY("¢", "cent" ,        "/",  KEY_OFFSET(0), THIRD_ROW)
+         SKEY("`", "back_quote",   "'",  KEY_OFFSET(1), THIRD_ROW)
+         SKEY("°", "ring",         "\"", KEY_OFFSET(2), THIRD_ROW)
+         SKEY("˙", "dot",          ".",  KEY_OFFSET(3), THIRD_ROW)
+         SKEY("®", "registered",   ",",  KEY_OFFSET(4), THIRD_ROW)
+         SKEY("©", "copyright",    "?",  KEY_OFFSET(5), THIRD_ROW)
+         SKEY("¿", "inv_question", "!",  KEY_OFFSET(6), THIRD_ROW)
+
+         KEY_SPECIAL_TEXT("2/2", (5*SCALE), THIRD_ROW, (85*SCALE))
+         KEY_SPECIAL_TEXT("abc", (5*SCALE), FOURTH_ROW, (95*SCALE))
+      }
+   }
+
+   group {
+      name: "fixed";
+
+#define REPEAT_KEY_SCRIPTS                                             \
+         public repeat_timer;                                          \
+         public repeat_key;                                            \
+                                                                       \
+         public _repeat_key(val) {                                     \
+            new _cur[20];                                              \
+            new _timer;                                                \
+            get_str(repeat_key, _cur, 20);                             \
+            emit("key_down", _cur);                                    \
+            _timer = get_int(repeat_timer);                            \
+            if (_timer) {                                              \
+               cancel_timer(_timer);                                   \
+            }                                                          \
+            _timer = timer(0.1, "_repeat_key", 1);                     \
+            set_int(repeat_timer, _timer);                             \
+         }                                                             \
+                                                                       \
+         public _repeat_key_pressed(_key[]) {                          \
+            new _cur[20];                                              \
+            get_str(repeat_key, _cur, 20);                             \
+            if (strlen(_cur) > 0) {                                    \
+               _repeat_key_released(_cur);                             \
+            }                                                          \
+            set_str(repeat_key, _key);                                 \
+            _repeat_key(1);                                            \
+         }                                                             \
+                                                                       \
+         public _repeat_key_released(_key[]) {                         \
+            new _timer;                                                \
+            set_str(repeat_key, "");                                   \
+            _timer = get_int(repeat_timer);                            \
+            if (_timer) {                                              \
+               cancel_timer(_timer);                                   \
+               set_int(repeat_timer, 0);                               \
+            }                                                          \
+         }
+
+      script {
+         MOUSE_DOWN_UP_SCRIPTS
+         REPEAT_KEY_SCRIPTS
+      }
+      programs {
+         MOUSE_DOWN_UP_PROGRAMS
+      }
+
+#define KEY_SPECIAL_ICON_REPEAT(val, x, y, w, icon_size)               \
+         KEY_SPECIAL_ICON(val, x, y, w, icon_size)                     \
+         programs {                                                    \
+            program {                                                  \
+               name: "long-press-"val;                                 \
+               signal: "long_press";                                   \
+               source: val;                                            \
+               script {                                                \
+                  _repeat_key_pressed(val);                            \
+               }                                                       \
+            }                                                          \
+            program {                                                  \
+               name: "key-up-"val;                                     \
+               signal: "key_up";                                       \
+               source: val;                                            \
+               script {                                                \
+                  _repeat_key_released(val);                           \
+               }                                                       \
+            }                                                          \
+         }
+
+      parts {
+         KEY_SPECIAL_ICON_REPEAT("backspace", (620*SCALE), THIRD_ROW, 
(85*SCALE), (60*SCALE))
+         KEY_SPECIAL_ICON("enter", (610*SCALE), FOURTH_ROW, (95*SCALE), 
(60*SCALE))
+
+#undef INIT_HSPACE
+#define INIT_HSPACE (120*SCALE)
+         KEY_SPECIAL_ICON_REPEAT("space", KEY_OFFSET(0), FOURTH_ROW, 
KEY_OFFSET(5), (64*SCALE));
+      }
+   }
+
+   group {
+      name: "numeric";
+      script {
+         MOUSE_DOWN_UP_SCRIPTS
+         REPEAT_KEY_SCRIPTS
+      }
+      programs {
+         MOUSE_DOWN_UP_PROGRAMS
+      }
+      parts {
+#undef KEY_WIDTH
+#define KEY_WIDTH (200*SCALE)
+#undef KEY_HEIGHT
+#define KEY_HEIGHT NUMERIC_KEY_HEIGHT
+#undef INIT_HSPACE
+#define INIT_HSPACE (45*SCALE)
+#undef ROW_SPACE
+#define ROW_SPACE (10*SCALE)
+#undef COL_SPACE
+#define COL_SPACE (10*SCALE)
+         KEY("1", " ", KEY_OFFSET(0), FIRST_ROW)
+         KEY("2", " ", KEY_OFFSET(1), FIRST_ROW)
+         KEY("3", " ", KEY_OFFSET(2), FIRST_ROW)
+
+         KEY("4", " ", KEY_OFFSET(0), SECOND_ROW)
+         KEY("5", " ", KEY_OFFSET(1), SECOND_ROW)
+         KEY("6", " ", KEY_OFFSET(2), SECOND_ROW)
+
+         KEY("7", " ", KEY_OFFSET(0), THIRD_ROW)
+         KEY("8", " ", KEY_OFFSET(1), THIRD_ROW)
+         KEY("9", " ", KEY_OFFSET(2), THIRD_ROW)
+
+         KEY_SPECIAL_ICON_REPEAT("backspace", KEY_OFFSET(0), FOURTH_ROW, 
KEY_WIDTH, (50*SCALE))
+         KEY("0", " ", KEY_OFFSET(1), FOURTH_ROW)
+         KEY_SPECIAL_ICON("enter", KEY_OFFSET(2), FOURTH_ROW, KEY_WIDTH, 
(60*SCALE))
+      }
+   }
+}
diff --git a/src/modules/wl_weekeyboard/themes/default/default_1080.edc 
b/src/modules/wl_weekeyboard/themes/default/default_1080.edc
new file mode 100644
index 0000000..d5f23d6
--- /dev/null
+++ b/src/modules/wl_weekeyboard/themes/default/default_1080.edc
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2014 Jaguar Landrover
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define SCALE 1.5
+
+#define MIN_WIDTH 1080
+#define MAX_WIDTH 1280
+#define MIN_HEIGHT 900
+#define MAX_HEIGHT 900
+
+#define NUMERIC_KEY_HEIGHT 150
+
+#include "default.edc"
diff --git a/src/modules/wl_weekeyboard/themes/default/default_600.edc 
b/src/modules/wl_weekeyboard/themes/default/default_600.edc
new file mode 100644
index 0000000..b5ef5e4
--- /dev/null
+++ b/src/modules/wl_weekeyboard/themes/default/default_600.edc
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define SCALE 0.83
+
+#define MIN_WIDTH 600
+#define MAX_WIDTH 1024
+#define MIN_HEIGHT 480
+#define MAX_HEIGHT 480
+
+#define NUMERIC_KEY_HEIGHT 80
+
+#include "default.edc"
diff --git a/src/modules/wl_weekeyboard/themes/default/default_720.edc 
b/src/modules/wl_weekeyboard/themes/default/default_720.edc
new file mode 100644
index 0000000..476f405
--- /dev/null
+++ b/src/modules/wl_weekeyboard/themes/default/default_720.edc
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define SCALE 1.0
+
+#define MIN_WIDTH 720
+#define MAX_WIDTH 1280
+#define MIN_HEIGHT 600
+#define MAX_HEIGHT 600
+
+#define NUMERIC_KEY_HEIGHT 100
+
+#include "default.edc"
diff --git a/src/modules/wl_weekeyboard/themes/default/fonts/LICENSE.txt 
b/src/modules/wl_weekeyboard/themes/default/fonts/LICENSE.txt
new file mode 100644
index 0000000..df18763
--- /dev/null
+++ b/src/modules/wl_weekeyboard/themes/default/fonts/LICENSE.txt
@@ -0,0 +1,93 @@
+Copyright 2010, 2012, 2014 Adobe Systems Incorporated (http://www.adobe.com/), 
with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of 
Adobe Systems Incorporated in the United States and/or other countries.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: 
http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded, 
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git 
a/src/modules/wl_weekeyboard/themes/default/fonts/SourceSansPro-Regular.ttf 
b/src/modules/wl_weekeyboard/themes/default/fonts/SourceSansPro-Regular.ttf
new file mode 100644
index 0000000..a011dff
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/fonts/SourceSansPro-Regular.ttf 
differ
diff --git 
a/src/modules/wl_weekeyboard/themes/default/fonts/SourceSansPro-Semibold.ttf 
b/src/modules/wl_weekeyboard/themes/default/fonts/SourceSansPro-Semibold.ttf
new file mode 100644
index 0000000..dbf946a
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/fonts/SourceSansPro-Semibold.ttf 
differ
diff --git a/src/modules/wl_weekeyboard/themes/default/ignorekeys.txt 
b/src/modules/wl_weekeyboard/themes/default/ignorekeys.txt
new file mode 100644
index 0000000..de27cff
--- /dev/null
+++ b/src/modules/wl_weekeyboard/themes/default/ignorekeys.txt
@@ -0,0 +1,4 @@
+abc
+?123
+1/2
+2/2
diff --git 
a/src/modules/wl_weekeyboard/themes/default/images/icon-backspace.png 
b/src/modules/wl_weekeyboard/themes/default/images/icon-backspace.png
new file mode 100644
index 0000000..32a1c3f
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/icon-backspace.png differ
diff --git a/src/modules/wl_weekeyboard/themes/default/images/icon-enter.png 
b/src/modules/wl_weekeyboard/themes/default/images/icon-enter.png
new file mode 100644
index 0000000..66b2d4d
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/icon-enter.png differ
diff --git a/src/modules/wl_weekeyboard/themes/default/images/icon-language.png 
b/src/modules/wl_weekeyboard/themes/default/images/icon-language.png
new file mode 100644
index 0000000..d3d754b
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/icon-language.png differ
diff --git 
a/src/modules/wl_weekeyboard/themes/default/images/icon-shift-active.png 
b/src/modules/wl_weekeyboard/themes/default/images/icon-shift-active.png
new file mode 100644
index 0000000..17a91c4
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/icon-shift-active.png differ
diff --git a/src/modules/wl_weekeyboard/themes/default/images/icon-shift.png 
b/src/modules/wl_weekeyboard/themes/default/images/icon-shift.png
new file mode 100644
index 0000000..b59d6a2
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/icon-shift.png differ
diff --git a/src/modules/wl_weekeyboard/themes/default/images/icon-space.png 
b/src/modules/wl_weekeyboard/themes/default/images/icon-space.png
new file mode 100644
index 0000000..b1b5bd3
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/icon-space.png differ
diff --git 
a/src/modules/wl_weekeyboard/themes/default/images/key-default-pressed.png 
b/src/modules/wl_weekeyboard/themes/default/images/key-default-pressed.png
new file mode 100644
index 0000000..bcc0f7d
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/key-default-pressed.png 
differ
diff --git a/src/modules/wl_weekeyboard/themes/default/images/key-default.png 
b/src/modules/wl_weekeyboard/themes/default/images/key-default.png
new file mode 100644
index 0000000..a4f5ba2
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/key-default.png differ
diff --git a/src/modules/wl_weekeyboard/themes/default/images/key-hint-bg.png 
b/src/modules/wl_weekeyboard/themes/default/images/key-hint-bg.png
new file mode 100644
index 0000000..b72b876
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/key-hint-bg.png differ
diff --git a/src/modules/wl_weekeyboard/themes/default/images/key-hint.png 
b/src/modules/wl_weekeyboard/themes/default/images/key-hint.png
new file mode 100644
index 0000000..d051c98
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/key-hint.png differ
diff --git 
a/src/modules/wl_weekeyboard/themes/default/images/key-special-pressed.png 
b/src/modules/wl_weekeyboard/themes/default/images/key-special-pressed.png
new file mode 100644
index 0000000..ae0a76c
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/key-special-pressed.png 
differ
diff --git a/src/modules/wl_weekeyboard/themes/default/images/key-special.png 
b/src/modules/wl_weekeyboard/themes/default/images/key-special.png
new file mode 100644
index 0000000..1cf53fe
Binary files /dev/null and 
b/src/modules/wl_weekeyboard/themes/default/images/key-special.png differ
diff --git a/src/modules/wl_weekeyboard/wkb-log.c 
b/src/modules/wl_weekeyboard/wkb-log.c
new file mode 100644
index 0000000..543bb53
--- /dev/null
+++ b/src/modules/wl_weekeyboard/wkb-log.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wkb-log.h"
+
+int _wkb_log_domain = -1;
+static int _init_count = 0;
+
+int
+wkb_log_init(const char *domain)
+{
+   if (_init_count)
+      goto end;
+
+   if (!eina_init())
+     {
+        fprintf(stderr, "%s:%d - %s() Error initializing Eina\n", __FILE__, 
__LINE__, __FUNCTION__);
+        return 0;
+     }
+
+   _wkb_log_domain = eina_log_domain_register(domain, EINA_COLOR_LIGHTCYAN);
+
+   if (_wkb_log_domain < 0)
+      {
+         EINA_LOG_ERR("Unable to register '%s' log domain", domain);
+         eina_shutdown();
+         return 0;
+      }
+
+end:
+   return ++_init_count;
+}
+
+void
+wkb_log_shutdown(void)
+{
+   if (_init_count <= 0 || --_init_count > 0)
+      return;
+
+   eina_log_domain_unregister(_wkb_log_domain);
+   eina_shutdown();
+}
diff --git a/src/modules/wl_weekeyboard/wkb-log.h 
b/src/modules/wl_weekeyboard/wkb-log.h
new file mode 100644
index 0000000..810b365
--- /dev/null
+++ b/src/modules/wl_weekeyboard/wkb-log.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WKB_LOG_H_
+#define _WKB_LOG_H_
+
+#include <Eina.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef DBG
+#undef DBG
+#endif
+#ifdef INF
+#undef INF
+#endif
+#ifdef WRN
+#undef WRN
+#endif
+#ifdef ERR
+#undef ERR
+#endif
+#ifdef CRITICAL
+#undef CRITICAL
+#endif
+
+extern int _wkb_log_domain;
+#define DBG(...)      EINA_LOG_DOM_DBG(_wkb_log_domain, __VA_ARGS__)
+#define INF(...)      EINA_LOG_DOM_INFO(_wkb_log_domain, __VA_ARGS__)
+#define WRN(...)      EINA_LOG_DOM_WARN(_wkb_log_domain, __VA_ARGS__)
+#define ERR(...)      EINA_LOG_DOM_ERR(_wkb_log_domain, __VA_ARGS__)
+#define CRITICAL(...) EINA_LOG_DOM_CRIT(_wkb_log_domain, __VA_ARGS__)
+
+int wkb_log_init(const char *domain);
+void wkb_log_shutdown(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WKB_LOG_H_ */

-- 


Reply via email to