[wl_keyrouter] Add keyrouter wayland protocol/backend-implementation 80/39480/4 submit/tizen/20150516.064906
authorSung-Jin Park <sj76.park@samsung.com>
Fri, 15 May 2015 11:41:07 +0000 (20:41 +0900)
committerSung-Jin Park <sj76.park@samsung.com>
Sat, 16 May 2015 06:46:56 +0000 (15:46 +0900)
Change-Id: I88bf63212598364fe48cb22264e9671ddc0c95ec

configure.ac
packaging/e-mod-tizen-keyrouter.spec
protocol/keyrouter.xml [new file with mode: 0644]
src/Makefile.am
src/e_mod_main.c [changed mode: 0755->0644]
src/e_mod_main.h [changed mode: 0755->0644]
src/e_mod_main_wl.c [new file with mode: 0644]
src/e_mod_main_wl.h [new file with mode: 0644]

index 81fac40..8585f6a 100644 (file)
@@ -92,6 +92,30 @@ AC_SUBST(ENLIGHTENMENT_LIBS)
 #AC_MSG_CHECKING([Which edje_cc to use])
 #AC_MSG_RESULT(${EDJE_CC})
 
+dnl ========================================================================
+# checks for the existence of wayland_scanner
+dnl ========================================================================
+AC_PATH_PROG([wayland_scanner], [wayland-scanner])
+if test x$wayland_scanner = x; then
+   AC_MSG_ERROR([wayland-scanner is needed to compile])
+fi
+
+PKG_CHECK_MODULES(WAYLAND_SCANNER, [wayland-scanner])
+PKG_CHECK_MODULES(WAYLAND, [wayland-server wayland-client ecore-wayland])
+
+dnl ========================================================================
+# checks for wayland only argument
+dnl ========================================================================
+have_wayland_only=no
+AC_ARG_ENABLE([wayland-only],
+  AS_HELP_STRING([--enable-wayland-only],[enable wayland-only version of enlightenment @<:@default=disabled@:>@]),
+  [have_wayland_only=$enableval],
+  [have_wayland_only=no])
+AC_MSG_CHECKING([whether wayland-only version is enabled])
+AM_CONDITIONAL(WAYLAND_ONLY, test x$have_wayland_only = xyes)
+if test "x${have_wayland_only}" != "xno"; then
+  AC_DEFINE_UNQUOTED([HAVE_WAYLAND_ONLY],[1],[enable wayland-only version of enlightenment])
+fi
 
 dnl =======================================================================
 
index 6b2ddf1..72e12d2 100644 (file)
@@ -1,7 +1,8 @@
 %bcond_with x
+%bcond_with wayland
 
 Name: e-mod-tizen-keyrouter
-Version: 0.0.3
+Version: 0.1.0
 Release: 1
 Summary: The Enlightenment Keyrouter Module for Tizen
 URL: http://www.enlightenment.org
@@ -10,18 +11,21 @@ Source0: %{name}-%{version}.tar.gz
 License: BSD-2-Clause
 BuildRequires: pkgconfig(enlightenment)
 BuildRequires:  gettext
+%if %{with x}
 BuildRequires:  pkgconfig(x11)
 BuildRequires:  pkgconfig(xi)
 BuildRequires:  pkgconfig(xtst)
 BuildRequires:  pkgconfig(xrandr)
 BuildRequires:  pkgconfig(utilX)
+%endif
+%if %{with wayland}
+BuildRequires:  pkgconfig(ecore)
+BuildRequires:  pkgconfig(wayland-server)
+#BuildRequires:  pkgconfig(ecore-wayland)
+%endif
 BuildRequires:  pkgconfig(dlog)
 BuildRequires:  e-tizen-data
 
-%if !%{with x}
-ExclusiveArch:
-%endif
-
 %description
 This package is a the Enlightenment Keyrouter Module for Tizen.
 
@@ -35,8 +39,15 @@ export CFLAGS+=" -Wall -g -fPIC -rdynamic ${GC_SECTIONS_FLAGS}"
 export LDFLAGS+=" -Wl,--hash-style=both -Wl,--as-needed -Wl,--rpath=/usr/lib"
 
 %autogen
+%if %{with wayland}
 %configure --prefix=/usr \
+           --enable-wayland-only \
            --with-tizen-keylayout-file=/usr/share/X11/xkb/tizen_key_layout.txt
+%else
+%configure --prefix=/usr \
+           --with-tizen-keylayout-file=/usr/share/X11/xkb/tizen_key_layout.txt
+%endif
+
 make
 
 %install
diff --git a/protocol/keyrouter.xml b/protocol/keyrouter.xml
new file mode 100644 (file)
index 0000000..38aad84
--- /dev/null
@@ -0,0 +1,89 @@
+<protocol name="keyrouter">
+  <copyright>
+    Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
+    Contact: Sung-Jin Park (sj76.park@samsung.com),
+             Jeonghyun Kang (jhyuni.kang@samsung.com)
+
+    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.
+  </copyright>
+
+  <interface name="wl_keyrouter" version="1">
+    <description summary="an interface to set each focus for each key">
+      In tradition, all the keys in a keyboard and a device on which
+      some keys are attached will be sent to focus surface by default.
+      Currently it's possible to set up each focus for each key in a keyboard and a device.
+      Therefore, by setting a key grab for a surface, the owner of the
+      surface will get the key event when it has the key grab for the key.
+    </description>
+
+    <enum name="error">
+      <entry name="none" value="0" summary="no error"/>
+      <entry name="invalid_surface" value="1" summary="Given surface is invalid."/>
+      <entry name="invalid_key" value="2" summary="Given key is invalid."/>
+      <entry name="invalid_mode" value="3" summary="Given mode is invalid."/>
+      <entry name="grabbed_already" value="4" summary="The key has been grabbed already."/>
+      <entry name="no_permission" value="5" summary="The wl client has no permission to grab the key."/>
+      <entry name="no_system_resources" value="6" summary="System resources are insufficient."/>
+    </enum>
+
+    <enum name="mode">
+      <description summary="mode for a key grab">
+       This value is used to set a mode for a key grab. With this mode and
+       the order of the surface between surfaces' stack, the compositor will determine the destination client
+       surface.
+      </description>
+      <entry name="none" value="0" summary="none"/>
+      <entry name="shared" value="1"
+       summary="mode to get a key grab with the other client surfaces when the focused client surface gets the key"/>
+      <entry name="topmost" value="2"
+       summary="mode to get a key grab when the client surface is the top most surface"/>
+      <entry name="overridable_exclusive" value="3"
+       summary="mode to get a key grab exclusively, overridably regardless of the order in the surface stack"/>
+      <entry name="exclusive" value="4"
+       summary="mode to get a key grab exclusively regardless of the order in surface stack"/>
+    </enum>
+
+    <request name="set_keygrab">
+      <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
+      <arg name="key" type="uint"/>
+      <arg name="mode" type="uint"/>
+    </request>
+
+    <request name="unset_keygrab">
+      <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
+      <arg name="key" type="uint"/>
+    </request>
+
+    <request name="get_keygrab_status">
+       <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
+       <arg name="key" type="uint"/>
+    </request>
+
+    <event name="keygrab_notify">
+      <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
+      <arg name="key" type="uint"/>
+      <arg name="mode" type="uint"/>
+      <arg name="error" type="uint"/>
+    </event>
+  </interface>
+</protocol>
+
index f698443..64996ad 100644 (file)
@@ -5,12 +5,33 @@ LDFLAGS +=
 
 pkgdir                 = $(libdir)/enlightenment/modules/$(MODULE)/$(MODULE_ARCH)
 pkg_LTLIBRARIES        = module.la
+if WAYLAND_ONLY
+module_la_SOURCES      = e_mod_main_wl.c \
+                         e_mod_main_wl.h \
+                         keyrouter-protocol.c
+module_la_CFLAGS       = @ENLIGHTENMENT_CFLAGS@ @WAYLAND_CFLAGS@ -DHAVE_WAYLAND_ONLY
+module_la_LDFLAGS      = -module -avoid-version @WAYLAND_LIBS@ @ENLIGHTENMENT_LIBS@
+else
 module_la_SOURCES      = e_mod_main.c \
                          e_mod_main.h
 module_la_LIBADD       =
 module_la_CFLAGS       = @ENLIGHTENMENT_CFLAGS@
 module_la_LDFLAGS      = -module -avoid-version @ENLIGHTENMENT_LIBS@
+endif
 module_la_DEPENDENCIES = $(top_builddir)/config.h
 
 #uninstall:
 #  rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE)
+
+if WAYLAND_ONLY
+BUILT_SOURCES = keyrouter-protocol.c keyrouter-protocol.h
+
+CLEANFILES = $(BUILT_SOURCES)
+
+%-protocol.c : $(top_srcdir)/protocol/%.xml
+       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) code < $< > $@
+
+%-protocol.h : $(top_srcdir)/protocol/%.xml
+       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) server-header < $< > $@
+
+endif
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/src/e_mod_main_wl.c b/src/e_mod_main_wl.c
new file mode 100644 (file)
index 0000000..eefcb48
--- /dev/null
@@ -0,0 +1,1076 @@
+#define E_COMP_WL
+#include "e.h"
+#include "e_mod_main_wl.h"
+#include "keyrouter-protocol.h"
+#include <string.h>
+
+E_KeyrouterPtr krt;
+EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Keyrouter Module of Window Manager" };
+
+/* wl_keyrouter_set_keygrab request handler */
+static void
+_e_keyrouter_cb_keygrab_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode)
+{
+   (void) client;
+   (void) resource;
+   (void) surface;
+   (void) key;
+   (void) mode;
+   int res=0;
+
+   if (!surface)
+     {
+        /* Regarding exclusive mode, a client can request to grab a key without a surface. */
+        if (mode < WL_KEYROUTER_MODE_EXCLUSIVE)
+          {
+             KLDBG("Invalid surface ! (key=%d, mode=%d)\n", key, mode);
+
+             WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, mode, WL_KEYROUTER_ERROR_INVALID_SURFACE);
+          }
+        else
+          {
+             KLDBG("Null surface will be permitted only for (or)exclusive mode !\n");
+          }
+     }
+
+   /* Check the given key range */
+   if (0 > key || MAX_HWKEYS < key )
+     {
+        KLDBG("Invalid range of key ! (keycode:%d)\n", key);
+        WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, mode, WL_KEYROUTER_ERROR_INVALID_KEY);
+     }
+
+   /* Check whether the key can be grabbed or not !
+    * Only key listed in Tizen key layout file can be grabbed. */
+   if (0 == krt->HardKeys[key].keycode)
+     {
+        KLDBG("Invalid key ! Disabled to grab ! (keycode:%d)\n", key);
+        WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, mode, WL_KEYROUTER_ERROR_INVALID_KEY);
+     }
+
+   /* Check whether the mode is valid or not */
+   if (WL_KEYROUTER_MODE_NONE > mode || WL_KEYROUTER_MODE_EXCLUSIVE < mode)
+     {
+        KLDBG("Invalid range of mode ! (mode:%d)\n", mode);
+        WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, mode, WL_KEYROUTER_ERROR_INVALID_MODE);
+     }
+
+   /* Check whether the request key can be grabbed or not */
+   res = _e_keyrouter_set_keygrab_in_list(surface, client, key, mode);
+
+   KLDBG("Result of grab check for a key (key:%d, mode:%d, res:%d)\n", key, mode, res);
+
+   WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, mode, res);
+}
+
+/* wl_keyrouter unset_keygrab request handler */
+static void
+_e_keyrouter_cb_keygrab_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
+{
+   (void) client;
+   (void) resource;
+   (void) surface;
+   (void) key;
+
+   E_Pixmap *ep = NULL;
+   E_Client *ec = NULL;
+
+   if (!surface)
+     {
+        if ((krt->HardKeys[key].excl_ptr) && (client == krt->HardKeys[key].excl_ptr->wc))
+          {
+             _e_keyrouter_remove_from_keylist(ec, key, WL_KEYROUTER_MODE_EXCLUSIVE, NULL, krt->HardKeys[key].excl_ptr);
+             WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, WL_KEYROUTER_MODE_NONE, WL_KEYROUTER_ERROR_NONE);
+          }
+     }
+
+    if (!surface || !(ep = wl_resource_get_user_data(surface)))
+     {
+        KLDBG("Surface or E_Pixman from the surface is invalid ! Return error !\n");
+        WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, WL_KEYROUTER_MODE_NONE, WL_KEYROUTER_ERROR_INVALID_SURFACE);
+     }
+
+   if (!(ec = e_pixmap_client_get(ep)))
+     {
+        KLDBG("E_Client pointer from E_Pixman from surface is invalid ! Return error !\n");
+        WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, WL_KEYROUTER_MODE_NONE, WL_KEYROUTER_ERROR_INVALID_SURFACE);
+     }
+
+   /* EXCLUSIVE grab */
+   if ((krt->HardKeys[key].excl_ptr) && (ec == krt->HardKeys[key].excl_ptr->ec))
+     {
+        _e_keyrouter_remove_from_keylist(ec, key, WL_KEYROUTER_MODE_EXCLUSIVE, NULL, krt->HardKeys[key].excl_ptr);
+     }
+
+   /* OVERRIDABLE_EXCLUSIVE grab */
+   _e_keyrouter_find_and_remove_client_from_list(ec, key, WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
+
+   /* TOPMOST(TOP_POSITION) grab */
+   _e_keyrouter_find_and_remove_client_from_list(ec, key, WL_KEYROUTER_MODE_TOPMOST);
+
+   /* SHARED grab */
+   _e_keyrouter_find_and_remove_client_from_list(ec, key, WL_KEYROUTER_MODE_SHARED);
+
+   WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, WL_KEYROUTER_MODE_NONE, WL_KEYROUTER_ERROR_NONE);
+}
+
+/* wl_keyrouter get_keygrab_status request handler */
+static void
+_e_keyrouter_cb_get_keygrab_status(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
+{
+   (void) client;
+   (void) resource;
+   (void) surface;
+   (void) key;
+
+   if (!surface)
+     {
+        KLDBG("No surface !\n");
+
+        /* Regarding exclusive mode, a client can request to grab a key without a surface.
+         * TODO : Need to check the (grab) mode */
+#if 0
+        if (mode < WL_KEYROUTER_MODE_EXCLUSIVE)
+          {
+             KLDBG("Invalid surface ! (key=%d, mode=%d)\n", key, mode);
+             WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, WL_KEYROUTER_MODE_NONE, WL_KEYROUTER_ERROR_INVALID_SURFACE);
+             return;
+          }
+        else
+          {
+             KLDBG("Null surface will be permitted only for EXCLUSIVE mode !\n");
+          }
+#endif
+     }
+
+   /* TODO : Need to check key grab status for the requesting wl client */
+
+   WL_KEYGRAB_NOTIFY_WITH_VAL(resource, surface, key, WL_KEYROUTER_MODE_NONE, WL_KEYROUTER_ERROR_NONE);
+}
+
+/* Function for adding a new key grab information into the keyrouting list */
+static int
+_e_keyrouter_set_keygrab_in_list(struct wl_resource *surface, struct wl_client *client, uint32_t key, uint32_t mode)
+{
+   E_Pixmap *ep = NULL;
+   E_Client *ec = NULL;
+
+   int res = WL_KEYROUTER_ERROR_NONE;
+
+   if (!surface && mode == WL_KEYROUTER_MODE_EXCLUSIVE)
+     {
+        struct wl_listener *destroy_listener = NULL;
+        if (krt->HardKeys[key].excl_ptr)
+          {
+             KLDBG("key(%d) is already exclusive grabbed\n", key);
+             return WL_KEYROUTER_ERROR_GRABBED_ALREADY;
+          }
+
+        E_Keyrouter_Key_List_NodePtr new_keyptr = E_NEW(E_Keyrouter_Key_List_Node, 1);
+
+        if (!new_keyptr)
+          {
+             KLDBG("Failled to allocate memory for new_keyptr\n");
+             return WL_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
+          }
+
+        new_keyptr->ec = NULL;
+        new_keyptr->wc = client;
+        new_keyptr->next = NULL;
+        krt->HardKeys[key].excl_ptr = new_keyptr;
+
+        KLDBG("Succeed to set keygrab information (WL_Client:%p, key:%d, mode:EXCLUSIVE(no surface))\n", client, key);
+
+        destroy_listener = E_NEW(struct wl_listener, 1);
+
+        if (!destroy_listener)
+          {
+             KLDBG("Failed to allocate memory for wl_client destroy listener !\n");
+             return WL_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
+          }
+
+        destroy_listener->notify = _e_keyrouter_wl_client_cb_destroy;
+        wl_client_add_destroy_listener(client, destroy_listener);
+
+        KLDBG("Add a wl_client(%p) destroy listener(%p)\n", client, destroy_listener);
+
+        return WL_KEYROUTER_ERROR_NONE;
+     }
+
+   if (!surface || !(ep = wl_resource_get_user_data(surface)))
+     {
+        KLDBG("Surface or E_Pixman from the surface is invalid ! Return error !\n");
+        return WL_KEYROUTER_ERROR_INVALID_SURFACE;
+     }
+
+   if (!(ec = e_pixmap_client_get(ep)))
+     {
+        KLDBG("E_Client pointer from E_Pixman from surface is invalid ! Return error !\n");
+        return WL_KEYROUTER_ERROR_INVALID_SURFACE;
+     }
+
+   KLDBG("E_Client(%p) request to grab a key(%d) with mode(%d)\n", ec, key, mode);
+
+   switch(mode)
+     {
+        case WL_KEYROUTER_MODE_EXCLUSIVE:
+           if (krt->HardKeys[key].excl_ptr)
+             {
+                KLDBG("key(%d) is already exclusive grabbed\n", key);
+                return WL_KEYROUTER_ERROR_GRABBED_ALREADY;
+             }
+
+           E_Keyrouter_Key_List_NodePtr new_keyptr = E_NEW(E_Keyrouter_Key_List_Node, 1);
+
+           if (!new_keyptr)
+             {
+                KLDBG("Failled to allocate memory for new_keyptr\n");
+                return WL_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
+             }
+
+           new_keyptr->ec = ec;
+           new_keyptr->wc = client;
+           new_keyptr->next = NULL;
+           krt->HardKeys[key].excl_ptr = new_keyptr;
+           KLDBG("Succeed to set keygrab information (E_Client:%p, key:%d, mode:EXCLUSIVE)\n", ec, key);
+           break;
+
+        case WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+           res = _e_keyrouter_prepend_to_keylist(ec, client, key, mode);
+           CHECK_ERR_VAL(res);
+           KLDBG("Succeed to set keygrab information (E_Client:%p, key:%d, mode:OR_EXCLUSIVE)\n", ec, key);
+           break;
+
+        case WL_KEYROUTER_MODE_TOPMOST:
+           res = _e_keyrouter_prepend_to_keylist(ec, client, key, mode);
+           CHECK_ERR_VAL(res);
+           KLDBG("Succeed to set keygrab information (E_Client:%p, key:%d, mode:TOPMOST)\n", ec, key);
+           break;
+
+        case WL_KEYROUTER_MODE_SHARED:
+           res = _e_keyrouter_prepend_to_keylist(ec, client, key, mode);
+           CHECK_ERR_VAL(res);
+           KLDBG("Succeed to set keygrab information (E_Client:%p, key:%d, mode:SHARED)\n", ec, key);
+           break;
+
+        default:
+           KLDBG("Unknown key(%d) grab mode(%d)\n", key, mode);
+           return WL_KEYROUTER_ERROR_INVALID_MODE;
+     }
+
+   //KLDBG("krt->HardKeys[%d].keycode: %d\n", key, krt->HardKeys[key].keycode);
+   return WL_KEYROUTER_ERROR_NONE;
+}
+
+
+/* Function for checking whether the key has been grabbed already by the same wl_surface or not */
+static int
+_e_keyrouter_find_duplicated_client(E_Client *ec, uint32_t key, uint32_t mode)
+{
+   E_Keyrouter_Key_List_NodePtr keylist_ptr;
+
+   switch(mode)
+     {
+        case WL_KEYROUTER_MODE_EXCLUSIVE:
+           return WL_KEYROUTER_ERROR_NONE;
+
+        case WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+           keylist_ptr = krt->HardKeys[key].or_excl_ptr;
+           break;
+
+        case WL_KEYROUTER_MODE_TOPMOST:
+           keylist_ptr = krt->HardKeys[key].top_ptr;
+           break;
+
+        case WL_KEYROUTER_MODE_SHARED:
+           keylist_ptr = krt->HardKeys[key].shared_ptr;
+           break;
+
+        case WL_KEYROUTER_MODE_PRESSED:
+           keylist_ptr = krt->HardKeys[key].press_ptr;
+           break;
+
+        default:
+           KLDBG("Unknown key(%d) and grab mode(%d)\n", key, mode);
+           return WL_KEYROUTER_ERROR_INVALID_MODE;
+     }
+
+   while(keylist_ptr)
+     {
+        if (keylist_ptr->ec == ec)
+          {
+             KLDBG("The key(%d) is already grabbed same mode(%d) on the same E_Client(%p)\n", key, mode, ec);
+             return WL_KEYROUTER_ERROR_GRABBED_ALREADY;
+          }
+        keylist_ptr = keylist_ptr->next;
+     }
+
+   //KLDBG("The key(%d) is not grabbed by mode(%d) for the same E_Client(%p)\n", key, mode, ec);
+   return WL_KEYROUTER_ERROR_NONE;
+}
+
+/* Function for prepending a new key grab information in the keyrouting list */
+static int
+_e_keyrouter_prepend_to_keylist(E_Client *ec, struct wl_client *wc, uint32_t key, uint32_t mode)
+{
+   int res = WL_KEYROUTER_ERROR_NONE;
+
+   res = _e_keyrouter_find_duplicated_client(ec, key, mode);
+   CHECK_ERR_VAL(res);
+
+   E_Keyrouter_Key_List_NodePtr new_keyptr = E_NEW(E_Keyrouter_Key_List_Node, 1);
+
+   if (!new_keyptr)
+     {
+        KLDBG("Failled to allocate memory for new_keyptr\n");
+        return WL_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
+     }
+
+   new_keyptr->ec = ec;
+   new_keyptr->wc = wc;
+
+   KLDBG("Now it's going to add a key(%d) mode(%d) for ec(%p)\n", key, mode, ec);
+
+   switch(mode)
+     {
+        case WL_KEYROUTER_MODE_EXCLUSIVE:
+           new_keyptr->next = krt->HardKeys[key].excl_ptr;
+           krt->HardKeys[key].excl_ptr = new_keyptr;
+           KLDBG("WL_KEYROUTER_MODE_EXCLUSIVE, key=%d, E_Client(%p) has been set !\n", key, ec);
+           break;
+
+        case WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+           new_keyptr->next = krt->HardKeys[key].or_excl_ptr;
+           krt->HardKeys[key].or_excl_ptr = new_keyptr;
+           KLDBG("WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, key=%d, E_Client(%p) has been set !\n", key, ec);
+           break;
+
+        case WL_KEYROUTER_MODE_TOPMOST:
+           new_keyptr->next = krt->HardKeys[key].top_ptr;
+           krt->HardKeys[key].top_ptr = new_keyptr;
+           KLDBG("WL_KEYROUTER_MODE_TOPMOST, key=%d, E_Client(%p) has been set !\n", key, ec);
+           break;
+
+        case WL_KEYROUTER_MODE_SHARED:
+           new_keyptr->next = krt->HardKeys[key].shared_ptr;
+           krt->HardKeys[key].shared_ptr = new_keyptr;
+           KLDBG("WL_KEYROUTER_MODE_SHARED, key=%d, E_Client(%p) has been set !\n", key, ec);
+           break;
+
+        case WL_KEYROUTER_MODE_PRESSED:
+           new_keyptr->next = krt->HardKeys[key].press_ptr;
+           krt->HardKeys[key].press_ptr = new_keyptr;
+           KLDBG("WL_KEYROUTER_MODE_PRESSED, key=%d, E_Client(%p) has been set !\n", key, ec);
+           break;
+
+        default:
+           KLDBG("Unknown key(%d) and grab mode(%d)\n", key, mode);
+           return WL_KEYROUTER_ERROR_INVALID_MODE;
+     }
+
+   return WL_KEYROUTER_ERROR_NONE;
+}
+
+/* Function to be called by the other functions regarding the removal of key grab information */
+static void
+_e_keyrouter_remove_from_keylist(E_Client *ec, uint32_t key, uint32_t mode, E_Keyrouter_Key_List_NodePtr prev_node, E_Keyrouter_Key_List_NodePtr key_node)
+{
+   /* TODO: memory free after remove from list */
+
+   KLDBG("Try to remove e_client(%p) key(%d) mode(%d) prev_node: %p, key_node: %p\n", ec, key, mode, prev_node, key_node);
+
+   switch(mode)
+     {
+        case WL_KEYROUTER_MODE_EXCLUSIVE:
+           key_node->ec = NULL;
+           key_node ->wc = NULL;
+           E_FREE(key_node);
+
+           key_node = NULL;
+           krt->HardKeys[key].excl_ptr = key_node;
+           KLDBG("WL_KEYROUTER_MODE_EXCLUSIVE Succeed to remove grab information ! (e_client:%p, key:%d)\n", ec, key);
+           break;
+
+        case WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+        case WL_KEYROUTER_MODE_TOPMOST:
+        case WL_KEYROUTER_MODE_SHARED:
+           if (!prev_node)
+             {
+                /* First Node */
+                switch (mode)
+                  {
+                     case WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+                        krt->HardKeys[key].or_excl_ptr = key_node->next;
+                        break;
+
+                     case WL_KEYROUTER_MODE_TOPMOST:
+                        krt->HardKeys[key].top_ptr = key_node->next;
+                        break;
+
+                     case WL_KEYROUTER_MODE_SHARED:
+                        krt->HardKeys[key].shared_ptr = key_node->next;
+                        break;
+
+                     default:
+                        break;
+                  }
+                key_node->ec = NULL;
+                key_node = NULL;
+             }
+           else
+             {
+                prev_node->next = key_node->next;
+                key_node->ec = NULL;
+                key_node = NULL;
+             }
+
+           if (mode == WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE)
+             {
+                KLDBG("WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE Succeed to remove grab information ! (e_client:%p, key:%d)\n", ec, key);
+             }
+           else if (mode == WL_KEYROUTER_MODE_TOPMOST)
+             {
+                KLDBG("WL_KEYROUTER_MODE_TOPMOST Succeed to remove grab information ! (e_client:%p, key:%d)\n", ec, key);
+             }
+           else if (mode == WL_KEYROUTER_MODE_SHARED)
+             {
+                KLDBG("WL_KEYROUTER_MODE_SHARED Succeed to remove grab information ! (e_client:%p, key:%d)\n", ec, key);
+             }
+           break;
+
+        default:
+           KLDBG("Unknown key(%d) and grab mode(%d)\n", key, mode);
+           return;
+     }
+
+   return;
+}
+
+/* Function for removing the existing key grab information from the list */
+static void
+_e_keyrouter_find_and_remove_client_from_list(E_Client *ec, uint32_t key, uint32_t mode)
+{
+   E_Keyrouter_Key_List_NodePtr prev_node = NULL, cur_node = NULL;
+
+   switch (mode)
+     {
+        case WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+           cur_node = krt->HardKeys[key].or_excl_ptr;
+           break;
+
+        case WL_KEYROUTER_MODE_TOPMOST:
+           cur_node = krt->HardKeys[key].top_ptr;
+           break;
+
+        case WL_KEYROUTER_MODE_SHARED:
+           cur_node = krt->HardKeys[key].shared_ptr;
+           break;
+
+        default:
+           KLDBG("Unknown key(%d) and grab mode(%d)\n", key, mode);
+           return;
+     }
+
+   while (cur_node)
+     {
+        if (ec == cur_node->ec)
+          {
+             _e_keyrouter_remove_from_keylist(ec, key, mode, prev_node, cur_node);
+             break;
+          }
+
+        prev_node = cur_node;
+        cur_node = cur_node->next;
+     }
+}
+
+static void
+_e_keyrouter_remove_client_from_list(E_Client *ec, struct wl_client *wc)
+{
+   int index = 0;
+   if (!ec && !wc)
+     {
+        return;
+     }
+
+   for(index=0; index<MAX_HWKEYS; index++)
+     {
+        if (0 == krt->HardKeys[index].keycode)
+          {
+             continue;
+          }
+
+        /* exclusive grab */
+        if (krt->HardKeys[index].excl_ptr)
+          {
+             if (ec && (ec == krt->HardKeys[index].excl_ptr->ec) )
+               {
+                  KLDBG("Remove exclusive key(%d) by ec(%p)", index, ec);
+                  _e_keyrouter_remove_from_keylist(ec, index, WL_KEYROUTER_MODE_EXCLUSIVE, NULL, krt->HardKeys[index].excl_ptr);
+               }
+             else if (wc && (wc == krt->HardKeys[index].excl_ptr->wc) )
+               {
+                  KLDBG("Remove exclusive key(%d) by wc(%p)", index, wc);
+                  _e_keyrouter_remove_from_keylist(ec, index, WL_KEYROUTER_MODE_EXCLUSIVE, NULL, krt->HardKeys[index].excl_ptr);
+               }
+          }
+
+        /* or exclusive grab */
+        _e_keyrouter_find_and_remove_client_from_list(ec, index, WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
+
+        /* top position grab */
+        _e_keyrouter_find_and_remove_client_from_list(ec, index, WL_KEYROUTER_MODE_TOPMOST);
+
+        /* shared grab */
+        _e_keyrouter_find_and_remove_client_from_list(ec, index, WL_KEYROUTER_MODE_SHARED);
+     }
+}
+
+static Eina_Bool
+_e_keyrouter_is_key_grabbed(int key)
+{
+   if (!krt->HardKeys[key].keycode)
+     {
+        return EINA_FALSE;
+     }
+   if (!krt->HardKeys[key].excl_ptr &&
+        !krt->HardKeys[key].or_excl_ptr &&
+        !krt->HardKeys[key].top_ptr &&
+        !krt->HardKeys[key].shared_ptr)
+     {
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static const struct wl_keyrouter_interface _e_keyrouter_implementation = {
+   _e_keyrouter_cb_keygrab_set,
+   _e_keyrouter_cb_keygrab_unset,
+   _e_keyrouter_cb_get_keygrab_status
+};
+
+/* wl_keyrouter global object destroy function */
+static void
+_e_keyrouter_cb_destory(struct wl_resource *resource)
+{
+   /* TODO : destroy resources if exist */
+}
+
+/* wl_keyrouter global object bind function */
+static void
+_e_keyrouter_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+   E_KeyrouterPtr krt_instance = data;
+   struct wl_resource *resource;
+
+   resource = wl_resource_create(client, &wl_keyrouter_interface, MIN(version, 1), id);
+
+   KLDBG("wl_resource_create(...,&wl_keyrouter_interface,...)\n");
+
+   if (!resource)
+     {
+        KLDBG("Failed to create resource ! (version :%d, id:%d)\n", version, id);
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   wl_resource_set_implementation(resource, &_e_keyrouter_implementation, krt_instance, _e_keyrouter_cb_destory);
+
+   KLDBG("wl_resource_set_implementation(..., _e_keyrouter_implementation, ...)\n");
+}
+
+/* Function for checking the existing grab for a key and sending key event(s) */
+static Eina_Bool
+_e_keyrouter_process_key_event(void *event, int type)
+{
+   Eina_Bool res = EINA_TRUE;
+   Ecore_Event_Key *ev = event;
+
+   if (!ev) return res;
+
+   KLDBG("type=%s\n", (type == ECORE_EVENT_KEY_DOWN) ? "ECORE_EVENT_KEY_DOWN" : "ECORE_EVENT_KEY_UP");
+
+   if (0 > ev->keycode || MAX_HWKEYS < ev->keycode)
+     {
+        KLDBG("The key(%d) is too larger to process keyrouting: Invalid keycode\n", ev->keycode);
+        return res;
+     }
+
+   if ( (ECORE_EVENT_KEY_DOWN == type) && (!_e_keyrouter_is_key_grabbed(ev->keycode)) )
+     {
+        KLDBG("The press key(%d) isn't a grabbable key or has not been grabbed yet !\n", ev->keycode);
+        return res;
+     }
+
+   if ( (ECORE_EVENT_KEY_UP == type) && (!krt->HardKeys[ev->keycode].press_ptr) )
+     {
+        KLDBG("The release key(%d) isn't a grabbable key or has not been grabbed yet !\n", ev->keycode);
+        return res;
+     }
+
+   //KLDBG("The key(%d) is going to be sent to the proper wl client(s) !\n", ev->keycode);
+
+  if (_e_keyrouter_send_key_events(type, ev))
+    {
+       res = EINA_FALSE;
+       KLDBG("Key event(s) has/have been sent to wl client(s) !\n");
+    }
+
+   return res;
+}
+
+/* Function for sending key events to wl_client(s) */
+static Eina_Bool
+_e_keyrouter_send_key_events(int type, Ecore_Event_Key *ev)
+{
+   Eina_Bool res;
+   if (ECORE_EVENT_KEY_DOWN == type)
+     {
+        res = _e_keyrouter_send_key_events_press(type, ev);
+     }
+  else
+     {
+        res = _e_keyrouter_send_key_events_release(type, ev);
+     }
+  return res;
+}
+
+static Eina_Bool
+_e_keyrouter_send_key_events_release(int type, Ecore_Event_Key *ev)
+{
+   E_Keyrouter_Key_List_NodePtr press_key = NULL, next_key = NULL;
+
+   for (press_key = krt->HardKeys[ev->keycode].press_ptr; press_key; press_key = press_key->next)
+     {
+        _e_keyrouter_send_key_event(type, press_key->ec, ev);
+        KLDBG("Press/Release Pair   : Key %s(%d) ===> Client (%p)\n",
+              ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "UP    "), ev->keycode, krt->HardKeys[ev->keycode].press_ptr->ec);
+     }
+
+  for (press_key = krt->HardKeys[ev->keycode].press_ptr; press_key; press_key = next_key)
+    {
+       next_key = press_key->next;
+       E_FREE(press_key);
+    }
+  krt->HardKeys[ev->keycode].press_ptr = NULL;
+
+  return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_keyrouter_send_key_events_press(int type, Ecore_Event_Key *ev)
+{
+   unsigned int keycode = ev->keycode;
+   E_Client *ec_focus;
+
+   if (krt->HardKeys[keycode].excl_ptr)
+     {
+        _e_keyrouter_send_key_event(type, krt->HardKeys[keycode].excl_ptr->ec, ev);
+        KLDBG("EXCLUSIVE Mode : Key %s(%d) ===> Client (%p)\n",
+              ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "UP    "), ev->keycode, krt->HardKeys[keycode].excl_ptr->ec);
+
+        return EINA_TRUE;
+     }
+
+   if (krt->HardKeys[keycode].or_excl_ptr)
+     {
+        _e_keyrouter_send_key_event(type, krt->HardKeys[keycode].or_excl_ptr->ec, ev);
+        KLDBG("OVERRIDABLE_EXCLUSIVE Mode : Key %s (%d) ===> Client (%p)\n",
+              ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "UP"), ev->keycode, krt->HardKeys[keycode].or_excl_ptr->ec);
+
+        return EINA_TRUE;
+     }
+
+   ec_focus = e_client_focused_get();
+
+   if (krt->HardKeys[keycode].top_ptr)
+     {
+        E_Comp *c;
+
+        if ((EINA_FALSE == krt->isWindowStackChanged) && (ec_focus == krt->HardKeys[keycode].top_ptr->ec))
+          {
+             _e_keyrouter_send_key_event(type, krt->HardKeys[keycode].top_ptr->ec, ev);
+             KLDBG("TOPMOST (TOP_POSITION) Mode : Key %s (%d) ===> Client (%p)\n",
+              ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "UP"), ev->keycode, krt->HardKeys[keycode].top_ptr->ec);
+
+             return EINA_TRUE;
+          }
+
+        krt->isWindowStackChanged = EINA_FALSE;
+
+        c = e_comp_find_by_window(ev->window);
+        if (_e_keyrouter_check_top_visible_window(c, ec_focus, keycode))
+          {
+             KLDBG("TOPMOST (TOP_POSITION) Mode : Key %s (%d) ===> Client (%p)\n",
+              ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "UP"), ev->keycode, krt->HardKeys[keycode].top_ptr->ec);
+             _e_keyrouter_send_key_event(type, krt->HardKeys[keycode].top_ptr->ec, ev);
+
+             return EINA_TRUE;
+          }
+     }
+   if (krt->HardKeys[keycode].shared_ptr)
+     {
+        E_Keyrouter_Key_List_NodePtr keylist_deliver = krt->HardKeys[keycode].shared_ptr;
+
+        _e_keyrouter_send_key_event(type, ec_focus, ev);
+        KLDBG("SHARED [Focus client] : Key %s (%d) ===> Client (%p)\n",
+              ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "UP "), ev->keycode, ec_focus);
+
+        while (keylist_deliver)
+          {
+             if (keylist_deliver->ec != ec_focus)
+               {
+                  _e_keyrouter_send_key_event(type, keylist_deliver->ec, ev);
+                  KLDBG("SHARED Mode : Key %s (%d) ===> Client (%p)\n",
+                        ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "UP"), ev->keycode, krt->HardKeys[keycode].shared_ptr->ec);
+               }
+             keylist_deliver = keylist_deliver->next;
+          }
+
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_keyrouter_check_top_visible_window(E_Comp *c, E_Client *ec_focus, int arr_idx)
+{
+   E_Client *ec_top;
+   E_Keyrouter_Key_List_NodePtr keylistPtr;
+
+   ec_top = e_client_top_get(c);
+   KLDBG("Top Client: %p\n", ec_top);
+
+   while (ec_top)
+     {
+        if (!ec_top->visible && ec_top == ec_focus)
+          {
+             KLDBG("Top Client(%p) is invisible(%d) but focus client\n", ec_top, ec_top->visible);
+             return EINA_FALSE;
+          }
+
+        /* TODO: Check this client is located inside a display boundary */
+
+        for (keylistPtr = krt->HardKeys[arr_idx].top_ptr; keylistPtr; keylistPtr=keylistPtr->next)
+          {
+             if (ec_top == keylistPtr->ec)
+               {
+                  _e_keyrouter_rearray_list_item_to_top(WL_KEYROUTER_MODE_TOPMOST, arr_idx, keylistPtr);
+                  KLDBG("Move a client(%p) to first index of list, krt->HardKey[%d].top_ptr->ec: (%p)\n",
+                     ec_top, arr_idx, krt->HardKeys[arr_idx].top_ptr->ec);
+
+                  return EINA_TRUE;
+               }
+          }
+
+        if (ec_top == ec_focus)
+          {
+             KLDBG("The Client(%p) is a focus client\n", ec_top);
+             return EINA_FALSE;
+          }
+
+        ec_top = e_client_below_get(ec_top);
+        KLDBG("Next client: %p\n", ec_top);
+     }
+   return EINA_FALSE;
+}
+
+static void
+_e_keyrouter_rearray_list_item_to_top(int mode, int arr_idx, E_Keyrouter_Key_List_NodePtr keylistPtr)
+{
+   E_Keyrouter_Key_List_NodePtr beforePtr, currentPtr;
+
+   switch (mode)
+     {
+        case WL_KEYROUTER_MODE_EXCLUSIVE:
+        case WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+           break;
+
+        case WL_KEYROUTER_MODE_TOPMOST:
+           beforePtr = currentPtr = krt->HardKeys[arr_idx].top_ptr;
+           for ( ; currentPtr; currentPtr = currentPtr->next)
+             {
+                if (currentPtr->ec == keylistPtr->ec)
+                  {
+                     if (currentPtr->ec == krt->HardKeys[arr_idx].top_ptr->ec)
+                       {
+                          break;
+                       }
+
+                     beforePtr->next = currentPtr->next;
+                     currentPtr->next = krt->HardKeys[arr_idx].top_ptr;
+                     krt->HardKeys[arr_idx].top_ptr = currentPtr;
+                  }
+                beforePtr = currentPtr;
+             }
+           break;
+
+        case WL_KEYROUTER_MODE_SHARED:
+        default:
+           break;
+     }
+}
+
+/* Function for sending key event to wl_client(s) */
+static void
+_e_keyrouter_send_key_event(int type, E_Client *ec, Ecore_Event_Key *ev)
+{
+   struct wl_client *wc;
+   struct wl_resource *res;
+
+   uint evtype;
+   uint serial;
+   Eina_List *l;
+
+   if (ec == NULL)
+     {
+        wc = krt->HardKeys[ev->keycode].excl_ptr->wc;
+     }
+   else
+     {
+        wc = wl_resource_get_client(ec->comp_data->wl_surface);
+     }
+
+   if (ECORE_EVENT_KEY_DOWN == type)
+     {
+        _e_keyrouter_prepend_to_keylist(ec, wc, ev->keycode, WL_KEYROUTER_MODE_PRESSED);
+        evtype = WL_KEYBOARD_KEY_STATE_PRESSED;
+     }
+   else
+     {
+        evtype = WL_KEYBOARD_KEY_STATE_RELEASED;
+     }
+
+   serial = wl_display_next_serial(krt->cdata->wl.disp);
+   EINA_LIST_FOREACH(krt->cdata->kbd.resources, l, res)
+     {
+        if (res)
+          {
+             if (wl_resource_get_client(res) != wc) continue;
+
+             KLDBG("[time: %d] res: %p, serial: %d send a key(%d):%d to wl_client:%p\n", ev->timestamp, res, serial, (ev->keycode)-8, evtype, wc);
+             wl_keyboard_send_key(res, serial, ev->timestamp, ev->keycode-8, evtype);
+          }
+     }
+}
+
+
+static Eina_Bool
+_event_filter(void *data, void *loop_data EINA_UNUSED, int type, void *event)
+{
+   (void) data;
+   (void) type;
+   (void) event;
+
+   /* Filter only for key down/up event */
+   if (ECORE_EVENT_KEY_DOWN == type || ECORE_EVENT_KEY_UP == type)
+     {
+        return _e_keyrouter_process_key_event(event, type);
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_keyrouter_init()
+{
+   krt = E_NEW(E_Keyrouter, 1);
+
+   if (!krt)
+     {
+        KLDBG("Failed to allocate memory for krt !\n");
+        return EINA_FALSE;
+     }
+
+   if (!e_comp)
+     {
+        KLDBG("Failed to initialize keyrouter module ! (e_comp == NULL)\n");
+        goto err;
+     }
+
+   E_Comp_Data *cdata = e_comp->wl_comp_data;
+
+   if (!cdata)
+     {
+        KLDBG("Failed to get wl_comp_data ! (e_comp->wl_comp_data == NULL)\n");
+        goto err;
+     }
+
+   krt->cdata = cdata;
+   krt->global = wl_global_create(cdata->wl.disp, &wl_keyrouter_interface, 1, krt, _e_keyrouter_cb_bind);
+
+   if (!krt->global)
+     {
+        KLDBG("Failed to create global !\n");
+        goto err;
+     }
+
+   /* Get keyname and keycode pair from Tizen Key Layout file */
+   _e_keyrouter_query_tizen_key_table();
+
+#if 0
+   int i = 0;
+   for (i=0 ; i < krt->numTizenHWKeys ; i++)
+     {
+        KLDBG("keycode[%d], keyname[%s] : Enabled to grab\n", krt->TizenHWKeys[i].keycode, krt->TizenHWKeys[i].name);
+     }
+#endif
+
+   /* Add filtering mechanism */
+   krt->ef_handler = ecore_event_filter_add(NULL, _event_filter, NULL, NULL);
+   _e_keyrouter_init_handlers();
+
+   return EINA_TRUE;
+
+err:
+   if (krt && krt->ef_handler) ecore_event_filter_del(krt->ef_handler);
+   if (krt) E_FREE(krt);
+
+   return EINA_FALSE;
+}
+
+EAPI void *
+e_modapi_init(E_Module *m)
+{
+   return (_e_keyrouter_init() ? m : NULL);
+}
+
+EAPI int
+e_modapi_shutdown(E_Module *m EINA_UNUSED)
+{
+   _e_keyrouter_deinit_handlers();
+   /* TODO: free allocated memory */
+
+   return 1;
+}
+
+EAPI int
+e_modapi_save(E_Module *m EINA_UNUSED)
+{
+   /* Save something to be kept */
+   return 1;
+}
+
+/* Function for getting keyname/keycode information from a key layout file */
+static void
+_e_keyrouter_query_tizen_key_table(void)
+{
+   FILE *fp_key_tables = NULL;
+   char keyname[64] = {0, };
+   int key_count = 0;
+   int key_size = 0;
+   int keycode = 0;
+   int i = 0;
+
+   fp_key_tables = fopen(KEYLAYOUT_PATH, "r");
+
+   if (!fp_key_tables)
+     {
+        KLDBG("Failed to read file (%s)\n", KEYLAYOUT_PATH);
+        return;
+     }
+
+   //KLDBG("Support Tizen Keymap\n");
+   while ( 0 < fscanf(fp_key_tables, "%s %d", keyname, &keycode))
+     {
+        key_count++;
+        //KLDBG(" - [%s : %d]\n", keyname, keycode);
+     }
+
+   krt->TizenHWKeys = E_NEW(E_Keyrouter_Tizen_HWKey, key_count);
+   krt->numTizenHWKeys = key_count;
+
+   fseek(fp_key_tables, 0, SEEK_SET);
+
+   for (i=0; i<key_count; i++)
+     {
+        if (fscanf(fp_key_tables, "%s %d", keyname, &keycode) <= 0) continue;
+
+        key_size = sizeof(keyname);
+
+        krt->TizenHWKeys[i].name = (char*)calloc(key_size, sizeof(char));
+
+        if (!krt->TizenHWKeys[i].name)
+          {
+             KLDBG("Failed to allocate memory !\n");
+             continue;
+          }
+
+        strncpy(krt->TizenHWKeys[i].name, keyname, key_size);
+
+        krt->TizenHWKeys[i].keycode = keycode+8;
+        krt->HardKeys[keycode+8].keycode = keycode+8;
+     }
+
+   fclose(fp_key_tables);
+}
+
+static void
+_e_keyrouter_deinit_handlers(void)
+{
+   Ecore_Event_Handler *h = NULL;
+
+   if (!krt ||  !krt->handlers) return;
+
+   EINA_LIST_FREE(krt->handlers, h)
+     ecore_event_handler_del(h);
+}
+
+static void
+_e_keyrouter_init_handlers(void)
+{
+   E_LIST_HANDLER_APPEND(krt->handlers, E_EVENT_CLIENT_STACK, _e_keyrouter_client_cb_stack, NULL);
+   E_LIST_HANDLER_APPEND(krt->handlers, E_EVENT_CLIENT_REMOVE, _e_keyrouter_client_cb_remove, NULL);
+}
+
+static Eina_Bool
+_e_keyrouter_client_cb_stack(void *data, int type, void *event)
+{
+   E_Event_Client *ev = event;
+   E_Client *ec = ev->ec;
+
+   (void) data;
+   (void) type;
+   (void) event;
+   (void) ev;
+   (void) ec;
+
+   //KLDBG("ec: %p, visibile: %d, focused: %d, take_focus: %d, want_focus: %d, bordername: %s, input_only: %d\n",
+   //        ec, ec->visible, ec->focused, ec->take_focus, ec->want_focus, ec->bordername, ec->input_only);
+
+   krt->isWindowStackChanged = EINA_TRUE;
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_keyrouter_client_cb_remove(void *data, int type, void *event)
+{
+   E_Event_Client *ev = event;
+   E_Client *ec = ev->ec;
+
+   (void) data;
+   (void) type;
+   (void) event;
+
+   //KLDBG("ec: %p, visibile: %d, focused: %d, take_focus: %d, want_focus: %d, bordername: %s, input_only: %d\n",
+   //       ec, ec->visible, ec->focused, ec->take_focus, ec->want_focus, ec->bordername, ec->input_only);
+
+   _e_keyrouter_remove_client_from_list(ec, NULL);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
+{
+   struct wl_client *client = data;
+
+   KLDBG("Listener(%p) called: wl_client: %p is died\n", l, client);
+   _e_keyrouter_remove_client_from_list(NULL, client);
+
+   E_FREE(l);
+   l = NULL;
+}
diff --git a/src/e_mod_main_wl.h b/src/e_mod_main_wl.h
new file mode 100644 (file)
index 0000000..ad1f03b
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef E_MOD_MAIN_H
+#define E_MOD_MAIN_H
+
+/* Temporary value of maximum number of HWKeys */
+#define MAX_HWKEYS 512
+
+#define CHECK_ERR(val) if (WL_KEYROUTER_ERROR_NONE != val) return;
+#define CHECK_ERR_VAL(val) if (WL_KEYROUTER_ERROR_NONE != val) return val;
+#define CHECK_NULL(val) if (!val) return;
+#define CHECK_NULL_VAL(val) if (!val) return val;
+
+#define KLDBG(msg, ARG...) DBG("[wl_keyrouter][%s:%d] "msg, __FUNCTION__, __LINE__, ##ARG)
+#define WL_KEYGRAB_NOTIFY_WITH_VAL(resource,surface,key,mode,err) \
+        wl_keyrouter_send_keygrab_notify(resource, surface, key, mode, err); \
+        return
+
+typedef struct _E_Keyrouter E_Keyrouter;
+typedef struct _E_Keyrouter* E_KeyrouterPtr;
+typedef struct _E_Keyrouter_Key_List_Node E_Keyrouter_Key_List_Node;
+typedef struct _E_Keyrouter_Key_List_Node* E_Keyrouter_Key_List_NodePtr;
+typedef struct _E_Keyrouter_Tizen_HWKey E_Keyrouter_Tizen_HWKey;
+typedef struct _E_Keyrouter_Grabbed_Key E_Keyrouter_Grabbed_Key;
+
+#define WL_KEYROUTER_MODE_PRESSED WL_KEYROUTER_MODE_EXCLUSIVE+1
+
+struct _E_Keyrouter_Key_List_Node
+{
+   E_Client *ec;
+   struct wl_client *wc;
+   struct _E_Keyrouter_Key_List_Node* next;
+};
+
+struct _E_Keyrouter_Tizen_HWKey
+{
+   char *name;
+   int keycode;
+};
+
+struct _E_Keyrouter_Grabbed_Key
+{
+   int keycode;
+   char* keyname;
+
+   E_Keyrouter_Key_List_Node* excl_ptr;
+   E_Keyrouter_Key_List_Node* or_excl_ptr;
+   E_Keyrouter_Key_List_Node* top_ptr;
+   E_Keyrouter_Key_List_Node* shared_ptr;
+   E_Keyrouter_Key_List_NodePtr press_ptr;
+};
+
+struct _E_Keyrouter
+{
+   E_Comp_Data *cdata;
+   struct wl_global *global;
+   Ecore_Event_Filter *ef_handler;
+   Eina_List *handlers;
+
+   E_Keyrouter_Grabbed_Key HardKeys[MAX_HWKEYS];
+   E_Keyrouter_Tizen_HWKey *TizenHWKeys;
+
+   Eina_Bool isWindowStackChanged;
+   int numTizenHWKeys;
+};
+
+/* E Module */
+EAPI extern E_Module_Api e_modapi;
+EAPI void *e_modapi_init(E_Module *m);
+EAPI int   e_modapi_shutdown(E_Module *m);
+EAPI int   e_modapi_save(E_Module *m);
+
+static Eina_Bool _e_keyrouter_init();
+static void _e_keyrouter_init_handlers(void);
+static void _e_keyrouter_deinit_handlers(void);
+
+static int _e_keyrouter_set_keygrab_in_list(struct wl_resource *surface, struct wl_client *client, uint32_t key, uint32_t mode);
+static int _e_keyrouter_find_duplicated_client(E_Client *ec, uint32_t key, uint32_t mode);
+static int _e_keyrouter_prepend_to_keylist(E_Client *ec, struct wl_client *wc, uint32_t key, uint32_t mode);
+static void _e_keyrouter_remove_from_keylist(E_Client *ec, uint32_t key, uint32_t mode, E_Keyrouter_Key_List_NodePtr prev_node, E_Keyrouter_Key_List_NodePtr key_node);
+static void _e_keyrouter_find_and_remove_client_from_list(E_Client *ec, uint32_t key, uint32_t mode);
+static void _e_keyrouter_remove_client_from_list(E_Client *ec, struct wl_client *wc);
+static void _e_keyrouter_rearray_list_item_to_top(int mode, int arr_idx, E_Keyrouter_Key_List_NodePtr keylistPtr);
+
+static Eina_Bool _e_keyrouter_process_key_event(void *event, int type);
+static Eina_Bool _e_keyrouter_send_key_events(int type, Ecore_Event_Key *ev);
+static Eina_Bool _e_keyrouter_send_key_events_press(int type, Ecore_Event_Key *ev);
+static Eina_Bool _e_keyrouter_send_key_events_release(int type, Ecore_Event_Key *ev);
+static void _e_keyrouter_send_key_event(int type, E_Client *ec, Ecore_Event_Key *ev);
+static Eina_Bool _e_keyrouter_is_key_grabbed(int key);
+static Eina_Bool _e_keyrouter_check_top_visible_window(E_Comp *c, E_Client *ec_focus, int arr_idx);
+static void _e_keyrouter_query_tizen_key_table(void);
+
+static Eina_Bool _e_keyrouter_client_cb_stack(void *data, int type, void *event);
+static Eina_Bool _e_keyrouter_client_cb_remove(void *data, int type, void *event);
+static void _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data);
+
+#endif