initial work for keyrouter 33/33133/1
authorDuna Oh <duna.oh@samsung.com>
Tue, 6 Jan 2015 07:21:59 +0000 (16:21 +0900)
committerDuna Oh <duna.oh@samsung.com>
Tue, 6 Jan 2015 07:21:59 +0000 (16:21 +0900)
Change-Id: I3dd6c8b11bab92575d291398a101299303c63bfb
Signed-off-by: Duna Oh <duna.oh@samsung.com>
.gitignore [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.ac [new file with mode: 0644]
packaging/e-mod-tizen-keyrouter.spec [new file with mode: 0644]
scripts/keygrab_status [new file with mode: 0755]
src/Makefile.am [new file with mode: 0644]
src/e_mod_main.c [new file with mode: 0644]
src/e_mod_main.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..a30d363
--- /dev/null
@@ -0,0 +1,8 @@
+#maintainer-clean removes everything
+MAINTAINERCLEANFILES = aclocal.m4 compile config.sub config.guess config.h.in \
+                      configure depcomp install-sh ltmain.sh Makefile.in missing
+
+SUBDIRS = src
+
+MAINTAINERCLEANFILES = \
+                      Makefile.in
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..1ac867a
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+#rm -rf autom4te.cache
+#rm -f aclocal.m4 ltmain.sh
+
+#echo "Running autoreconf..." ; autoreconf -v --install || exit 1
+#echo "Running configure..." ; ./configure --enable-maintainer-mode
+
+set  -x
+aclocal
+autoconf
+libtoolize --copy --force
+autoheader
+automake --foreign --add-missing --copy
+
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..805655a
--- /dev/null
@@ -0,0 +1,117 @@
+# Process this file with autoconf to produce a configure script.
+dnl Process this file with autoconf to produce a configure script.
+
+# Note )
+#
+# AC_DEFINE(VARIABLE, VALUE, DESCRIPTION)
+#   output the following to config.h
+#   /* DESCRIPTION */
+#   #define VARIABLE VALUE
+#
+# AC_SUBST(VARIABLE, [VALUE])
+#   define $(VARIABLE) as VALUE in Makefile
+
+dnl ========================================================================
+# initialization
+dnl ========================================================================
+AC_INIT([e-mod-tizen-keyrouter], [0.1], [duna.oh@samsung.com])
+
+# check for tools needed by automake generated Makefiles
+# -Wall  : Turn all warnings on.
+# -Werror: report warings as errors.
+# foreign: relax some GNU standard requirements
+#AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AM_INIT_AUTOMAKE([-Wall foreign])
+
+dnl ========================================================================
+# checks for programs
+dnl ========================================================================
+AC_PROG_CC
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+
+dnl ========================================================================
+# checks for libraries
+dnl ========================================================================
+
+dnl ========================================================================
+# checks for header files
+dnl ========================================================================
+#AC_HEADER_STDC
+AC_CHECK_HEADERS([math.h fcntl.h stdlib.h string.h unistd.h])
+
+dnl ========================================================================
+# checks for typedefs, structures, and compiler characteristics
+AC_C_CONST
+
+dnl ========================================================================
+# checks for library functions
+dnl ========================================================================
+#AC_FUNC_MALLOC
+AC_FUNC_MMAP
+AC_CHECK_FUNCS([memset munmap strcasecmp strdup])
+
+dnl ========================================================================
+# checks for pkg-config
+dnl ========================================================================
+PKG_PROG_PKG_CONFIG
+
+
+dnl ========================================================================
+# checks for pkg-config
+dnl ========================================================================
+PKG_CHECK_MODULES(ENLIGHTENMENT, [enlightenment,
+                                  dlog])
+ENLIGHTENMENT_CFLAGS="${ENLIGHTENMENT_CFLAGS} -D_GNU_SOURCE "
+AC_SUBST(ENLIGHTENMENT_CFLAGS)
+AC_SUBST(ENLIGHTENMENT_LIBS)
+
+# Find edje_cc
+#PKG_CHECK_MODULES(EDJE, [edje >= 0.5.0])
+#AC_ARG_WITH(edje-cc,
+#      AC_HELP_STRING([--with-edje-cc=PATH], [specify a specific path to edje_cc]),
+#      [
+#              v=$withval;
+#              EDJE_CC=$v
+#      ],
+#      [
+#              EDJE_CC=$(pkg-config --variable=prefix edje)/bin/edje_cc
+#      ]
+#)
+#AC_SUBST(EDJE_CC)
+#AC_MSG_CHECKING([Which edje_cc to use])
+#AC_MSG_RESULT(${EDJE_CC})
+
+
+dnl =======================================================================
+
+release=$(pkg-config --variable=release enlightenment)
+MODULE_ARCH="$host_os-$host_cpu-$release"
+AC_SUBST(MODULE_ARCH)
+AC_DEFINE_UNQUOTED(MODULE_ARCH, "$MODULE_ARCH", "Module architecture")
+
+datadir=$(pkg-config --variable=modules enlightenment)/${PACKAGE}
+AC_ARG_ENABLE(homedir-install,
+       AS_HELP_STRING([--enable-homedir-install], [Install module in homedir]),
+       [ datadir="${HOME}/.e/e/modules/${PACKAGE}" ]
+)
+
+dnl ========================================================================
+# output files
+dnl ========================================================================
+
+# create HEADER for all HEADER.in.
+# HEADERS contain definitions made with AC_DEFINE.
+# the following command will create config.h from config.h.in
+AC_CONFIG_HEADERS([config.h])
+
+# create FILE for all FILE.in.
+# FILES contains definitions made with AC_SUBST.
+AC_CONFIG_FILES([
+                Makefile
+                src/Makefile
+                ])
+
+AC_OUTPUT
+
+
diff --git a/packaging/e-mod-tizen-keyrouter.spec b/packaging/e-mod-tizen-keyrouter.spec
new file mode 100644 (file)
index 0000000..66bb347
--- /dev/null
@@ -0,0 +1,56 @@
+%bcond_with x
+
+Name: e-mod-tizen-keyrouter
+Version: 0.0.1
+Release: 1
+Summary: The Enlightenment Keyrouter Module for Tizen
+URL: http://www.enlightenment.org
+Group: Graphics & UI Framework/Other
+Source0: %{name}-%{version}.tar.gz
+License: BSD-2-Clause
+BuildRequires: pkgconfig(enlightenment)
+BuildRequires:  gettext
+BuildRequires:  pkgconfig(x11)
+BuildRequires:  pkgconfig(xi)
+BuildRequires:  pkgconfig(xtst)
+BuildRequires:  pkgconfig(xrandr)
+BuildRequires:  pkgconfig(utilX)
+BuildRequires:  pkgconfig(dlog)
+
+%if !%{with x}
+ExclusiveArch:
+%endif
+
+%description
+This package is a the Enlightenment Keyrouter Module for Tizen.
+
+%prep
+%setup -q
+
+%build
+
+export GC_SECTIONS_FLAGS="-fdata-sections -ffunction-sections -Wl,--gc-sections"
+export CFLAGS+=" -Wall -g -fPIC -rdynamic ${GC_SECTIONS_FLAGS}"
+export LDFLAGS+=" -Wl,--hash-style=both -Wl,--as-needed -Wl,--rpath=/usr/lib"
+
+%autogen
+%configure --prefix=/usr
+make
+
+%install
+rm -rf %{buildroot}
+
+# for license notification
+#mkdir -p %{buildroot}/usr/share/license
+#cp -a %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/usr/share/license/%{name}
+
+# install
+make install DESTDIR=%{buildroot}
+
+# clear useless textual files
+find  %{buildroot}%{_libdir}/enlightenment/modules/%{name} -name *.la | xargs rm
+
+%files
+%defattr(-,root,root,-)
+%{_libdir}/enlightenment/modules/e-mod-tizen-keyrouter
+#/usr/share/license/%{name}
diff --git a/scripts/keygrab_status b/scripts/keygrab_status
new file mode 100755 (executable)
index 0000000..8f448eb
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if [ "$1" = "" ]; then
+        VAL="1"
+else
+        VAL="$1"
+fi
+
+if [ -x /usr/bin/xprop ]; then
+        /usr/bin/xprop -root -f _GRAB_STATUS 32c -set _GRAB_STATUS ${VAL} &
+fi
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..f698443
--- /dev/null
@@ -0,0 +1,16 @@
+MAINTAINERCLEANFILES = Makefile.in
+MODULE = e-mod-tizen-keyrouter
+
+LDFLAGS +=
+
+pkgdir                 = $(libdir)/enlightenment/modules/$(MODULE)/$(MODULE_ARCH)
+pkg_LTLIBRARIES        = module.la
+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@
+module_la_DEPENDENCIES = $(top_builddir)/config.h
+
+#uninstall:
+#  rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE)
diff --git a/src/e_mod_main.c b/src/e_mod_main.c
new file mode 100644 (file)
index 0000000..510cace
--- /dev/null
@@ -0,0 +1,3146 @@
+#include "e.h"
+#include "e_mod_main.h"
+#include <string.h>
+
+#define LOG_TAG        "KEYROUTER"
+#include "dlog.h"
+
+EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Keyrouter Module of Window Manager" };
+
+KeyRouter keyrouter;
+
+EAPI void *
+e_modapi_init(E_Module *m)
+{
+   printf("---------------------------------------\n");
+   printf("---------------------------------------\n");
+   printf("---------------------------------------\n");
+   printf("LOAD %s MODULE\n", e_modapi.name);
+   printf("---------------------------------------\n");
+   printf("---------------------------------------\n");
+   printf("---------------------------------------\n");
+
+   if( !_e_keyrouter_init() )
+     {
+        SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed @ _e_keyrouter_init()..!\n", __FUNCTION__);
+        return NULL;
+     }
+
+       //Adding Event Handlers
+       keyrouter.e_event_generic_handler = ecore_event_handler_add(ECORE_X_EVENT_GENERIC, (Ecore_Event_Handler_Cb)_e_keyrouter_cb_event_generic, NULL);
+       keyrouter.e_event_any_handler = ecore_event_handler_add(ECORE_X_EVENT_ANY, (Ecore_Event_Handler_Cb)_e_keyrouter_cb_event_any, NULL);
+       keyrouter.e_window_property_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, (Ecore_Event_Handler_Cb)_e_keyrouter_cb_window_property, NULL);
+       keyrouter.e_client_stack_handler = ecore_event_handler_add(E_EVENT_CLIENT_STACK, (Ecore_Event_Handler_Cb)_e_keyrouter_cb_e_client_stack, NULL);
+       keyrouter.e_client_remove_handler = ecore_event_handler_add(E_EVENT_CLIENT_REMOVE, (Ecore_Event_Handler_Cb)_e_keyrouter_cb_e_client_remove, NULL);
+       keyrouter.e_window_create_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE, (Ecore_Event_Handler_Cb)_e_keyrouter_cb_window_create, NULL);
+       keyrouter.e_window_destroy_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, (Ecore_Event_Handler_Cb)_e_keyrouter_cb_window_destroy, NULL);
+       keyrouter.e_window_configure_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE,(Ecore_Event_Handler_Cb)_e_keyrouter_cb_window_configure, NULL);
+       keyrouter.e_window_stack_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STACK, (Ecore_Event_Handler_Cb)_e_keyrouter_cb_window_stack, NULL);
+       keyrouter.e_client_message_handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, (Ecore_Event_Handler_Cb)_e_keyrouter_cb_client_message, NULL);
+
+       if( !keyrouter.e_window_stack_handler )                 SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to add ECORE_X_EVENT_WINDOW_STACK handler\n", __FUNCTION__);
+       if( !keyrouter.e_window_configure_handler )             SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to add ECORE_X_EVENT_WINDOW_CONFIGURE handler\n", __FUNCTION__);
+       if( !keyrouter.e_window_destroy_handler )               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to add ECORE_X_EVENT_WINDOW_DESTROY handler\n", __FUNCTION__);
+       if( !keyrouter.e_window_create_handler )                        SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to add ECORE_X_EVENT_WINDOW_CREATE handler\n", __FUNCTION__);
+       if( !keyrouter.e_window_property_handler )              SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to add ECORE_X_EVENT_WINDOW_PROPERTY handler\n", __FUNCTION__);
+       if( !keyrouter.e_client_stack_handler )                 SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to add E_EVENT_BORDER_STACK handler\n", __FUNCTION__);
+       if( !keyrouter.e_client_remove_handler )                SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to add E_EVENT_BORDER_REMOVE handler\n", __FUNCTION__);
+       if( !keyrouter.e_event_generic_handler )                        SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to add ECORE_X_EVENT_GENERIC handler\n", __FUNCTION__);
+       if( !keyrouter.e_event_any_handler )                    SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to add ECORE_X_EVENT_ANY handler\n", __FUNCTION__);
+
+       return m;
+}
+
+EAPI int
+e_modapi_shutdown(E_Module *m EINA_UNUSED)
+{
+       //Removing Event Handlers
+       ecore_event_handler_del(keyrouter.e_event_generic_handler);
+       ecore_event_handler_del(keyrouter.e_event_any_handler);
+       ecore_event_handler_del(keyrouter.e_window_property_handler);
+       ecore_event_handler_del(keyrouter.e_client_stack_handler);
+       ecore_event_handler_del(keyrouter.e_client_remove_handler);
+       ecore_event_handler_del(keyrouter.e_window_create_handler);
+       ecore_event_handler_del(keyrouter.e_window_destroy_handler);
+       ecore_event_handler_del(keyrouter.e_window_configure_handler);
+       ecore_event_handler_del(keyrouter.e_window_stack_handler);
+
+       keyrouter.e_window_stack_handler = NULL;
+       keyrouter.e_window_configure_handler = NULL;
+       keyrouter.e_window_destroy_handler = NULL;
+       keyrouter.e_window_create_handler = NULL;
+       keyrouter.e_window_property_handler = NULL;
+       keyrouter.e_client_stack_handler = NULL;
+       keyrouter.e_client_remove_handler = NULL;
+       keyrouter.e_event_generic_handler = NULL;
+       keyrouter.e_event_any_handler = NULL;
+
+       if(keyrouter.e_longpress_timer)
+               ecore_timer_del(keyrouter.e_longpress_timer);
+       keyrouter.e_longpress_timer = NULL;
+
+       _e_keyrouter_fini();
+
+       return 1;
+}
+
+EAPI int
+e_modapi_save(E_Module *m EINA_UNUSED)
+{
+   /* Save something to be kept */
+   return 1;
+}
+
+static void
+_e_keyrouter_x_input_init(void)
+{
+       int event, error;
+       int major = 2, minor = 0;
+#ifdef _F_REMAP_MOUSE_BUTTON_TO_HWKEY_
+       XIGrabModifiers modifiers[] = {{XIAnyModifier, 0}};
+       int nmods = sizeof(modifiers)/sizeof(modifiers[0]);
+       int res = 0;
+#endif//_F_REMAP_MOUSE_BUTTON_TO_HWKEY_
+
+       if( !XQueryExtension(keyrouter.disp, "XInputExtension", &keyrouter.xi2_opcode, &event, &error) )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] XInput Extension isn't supported.\n", __FUNCTION__);
+               keyrouter.xi2_opcode = -1;
+               return;
+       }
+
+       if( XIQueryVersion(keyrouter.disp, &major, &minor) == BadRequest )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to query XI version.\n", __FUNCTION__);
+               keyrouter.xi2_opcode = -1;
+               return;
+       }
+
+       memset(&keyrouter.eventmask, 0L, sizeof(XIEventMask));
+       keyrouter.eventmask.deviceid = XIAllDevices;
+       keyrouter.eventmask.mask_len = XIMaskLen(XI_RawMotion);
+       keyrouter.eventmask.mask= calloc(keyrouter.eventmask.mask_len, sizeof(char));
+
+       XISetMask(keyrouter.eventmask.mask, XI_HierarchyChanged);
+
+#ifdef _F_REMAP_MOUSE_BUTTON_TO_HWKEY_
+       XISetMask(keyrouter.eventmask.mask, XI_ButtonPress);
+       XISetMask(keyrouter.eventmask.mask, XI_ButtonRelease);
+
+       res = XIGrabButton(keyrouter.disp, XIAllDevices, 2, keyrouter.rootWin, NULL, GrabModeAsync, GrabModeAsync, False, &keyrouter.eventmask, nmods, modifiers);
+       if(res < 0) SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to XIGrabButton(2), res=%d\n", __FUNCTION__, res);
+
+       res = XIGrabButton(keyrouter.disp, XIAllDevices, 3, keyrouter.rootWin, NULL, GrabModeAsync, GrabModeAsync, False, &keyrouter.eventmask, nmods, modifiers);
+       if(res < 0) SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to XIGrabButton(3), res=%d\n", __FUNCTION__, res);
+#endif//_F_REMAP_MOUSE_BUTTON_TO_HWKEY_
+       /* select XI events for a part */
+       XISelectEvents(keyrouter.disp, keyrouter.rootWin, &keyrouter.eventmask, 1);
+}
+
+static int
+_e_keyrouter_cb_event_any(void *data, int ev_type, void *event)
+{
+       XEvent *ev = (XEvent *)event;
+       XDeviceKeyEvent *xdevkey = (XDeviceKeyEvent *)ev;
+
+       int type = ev->xcookie.type;
+
+       if( type == keyrouter.DeviceKeyPress )
+       {
+               ev->type = KeyPress;
+               keyrouter.first_press_flag++;
+       }
+       else if( type == keyrouter.DeviceKeyRelease )
+       {
+               ev->type = KeyRelease;
+               keyrouter.first_press_flag--;
+       }
+       else
+               return 1;
+
+       ev->xany.display = keyrouter.disp;
+       ev->xkey.keycode = xdevkey->keycode;
+       ev->xkey.time = xdevkey->time;
+       ev->xkey.state = 0;
+       ev->xkey.root = keyrouter.rootWin;
+       ev->xkey.send_event = 1;
+       ev->xkey.subwindow = None;
+
+       if(!_e_keyrouter_is_waiting_key_list_empty(ev))
+               return 1;
+
+       if(_e_keyrouter_is_key_in_ignored_list(ev))
+               return 1;
+
+       _e_keyrouter_hwkey_event_handler(ev);
+
+       return 1;
+}
+
+static int LongPressRecognize(int keycode)
+{
+       longpress_info *lphdata = NULL;
+       Eina_List *ltemp;
+       longpress_info *datatmp;
+
+       EINA_LIST_FOREACH(keyrouter.longpress_list, ltemp, datatmp)
+       {
+               if(datatmp->keycode == keycode)
+               {
+                       lphdata = malloc(sizeof(longpress_info));
+                       lphdata->keycode = keycode;
+                       lphdata->longpress_timeout = datatmp->longpress_timeout;
+                       lphdata->longpress_window = datatmp->longpress_window;
+                       keyrouter.pressinfo->longpress_timeout = datatmp->longpress_timeout;
+                       keyrouter.timer_flag = 1;
+                       keyrouter.e_longpress_timer = ecore_timer_add((double)lphdata->longpress_timeout/1000.0, LongPressEventDeliver, lphdata);
+                       break;
+               }
+       }
+
+       if( !keyrouter.e_longpress_timer )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to add Long_Press_Timer \n", __FUNCTION__);
+               free(lphdata);
+       }
+
+       return 0;
+}
+
+static Eina_Bool LongPressEventDeliver(void *data)
+{
+       longpress_info *lpinfo;
+       key_event_info* key_data;
+       int menu_keycode, back_keycode;
+       int col=0;
+       Eina_Bool ret_val = EINA_FALSE;
+
+       lpinfo = (longpress_info*)data;
+       if(!lpinfo)
+               return ret_val;
+
+       menu_keycode = ecore_x_keysym_keycode_get(KEY_MENU);
+       back_keycode = ecore_x_keysym_keycode_get(KEY_BACK);
+
+       if(XkbKeycodeToKeysym(keyrouter.disp, lpinfo->keycode, col, 0) == XkbKeycodeToKeysym(keyrouter.disp, menu_keycode, col, 0))
+       {
+               if(ecore_x_client_message32_send(lpinfo->longpress_window, keyrouter.atomMenuLongPress, ECORE_X_EVENT_MASK_NONE, lpinfo->longpress_timeout, 0, 0, 0, 0))
+                       ret_val = EINA_TRUE;
+       }
+       else if(XkbKeycodeToKeysym(keyrouter.disp, lpinfo->keycode, col, 0) == XkbKeycodeToKeysym(keyrouter.disp, back_keycode, col, 0))
+       {
+               if(ecore_x_client_message32_send(lpinfo->longpress_window, keyrouter.atomBackLongPress, ECORE_X_EVENT_MASK_NONE, lpinfo->longpress_timeout, 0, 0, 0, 0))
+                       ret_val = EINA_TRUE;
+       }
+
+       // Delete timer & Clear flag
+       keyrouter.short_press_flag = 0;
+       keyrouter.timer_flag = 0;
+       ecore_timer_del(keyrouter.e_longpress_timer);
+       keyrouter.e_longpress_timer = NULL;
+
+       key_data = malloc(sizeof(key_event_info));
+       key_data->ev_type = KeyRelease;
+       key_data->keycode = lpinfo->keycode;
+       keyrouter.ignored_key_list = eina_list_append(keyrouter.ignored_key_list, key_data);
+       free(lpinfo);
+
+       return ret_val;
+}
+
+static Eina_Bool ShortPressEventDeliver(longpress_info *kevinfo)
+{
+       keyrouter.timer_flag = 0;
+       keyrouter.short_press_flag = 1;
+       ecore_timer_del(keyrouter.e_longpress_timer);
+       keyrouter.e_longpress_timer = NULL;
+       XEvent xev;
+
+       xev.xkey.state = 0;
+       xev.xkey.display = keyrouter.disp;
+       xev.xkey.root = keyrouter.rootWin;
+       xev.xkey.window= kevinfo->longpress_window;
+       xev.xkey.keycode = kevinfo->keycode;
+       xev.xkey.time = kevinfo->evtime;
+       xev.xkey.type = KeyPress;
+       xev.xkey.send_event = 1;
+       xev.xkey.subwindow = None;
+
+       free(keyrouter.pressinfo);
+       keyrouter.pressinfo = NULL;
+       _e_keyrouter_hwkey_event_handler(&xev);
+       return True;
+}
+
+static void _e_keyrouter_cancel_key(XEvent *xev, int keycode)
+{
+       keylist_node *tmp_ptr;
+       keylist_node* ptr;
+
+       SECURE_SLOGD("\e[32m[keyrouter] Begin of cancel process of a keycode(%d)!\e[0m\n", keycode);
+
+       for( ptr = keyrouter.HardKeys[keycode].pressed_win_ptr; (NULL != ptr) ; )
+       {
+               xev->xkey.window = ptr->wid;
+
+               //Send Cancel KeyPress
+               xev->xkey.type = KeyPress;
+               xev->xkey.keycode = keyrouter.cancel_key.keycode;
+               SECURE_SLOGD("\e[32m[keyrouter] Deliver KeyPress (keycode:%d) to window (0x%x) !\e[0m\n", xev->xkey.keycode, (int)xev->xkey.window);
+               XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+
+               //Send KeyRelease of the keycode
+               xev->xkey.type = KeyRelease;
+               xev->xkey.keycode = keycode;
+               SECURE_SLOGD("\e[32m[keyrouter] Deliver KeyRelease (keycode:%d) to window (0x%x) !\e[0m\n", xev->xkey.keycode, (int)xev->xkey.window);
+               XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+
+               //Cancel KeyRelease
+               xev->xkey.type = KeyRelease;
+               xev->xkey.keycode = keyrouter.cancel_key.keycode;
+               SECURE_SLOGD("\e[32m[keyrouter] Deliver KeyRelease (keycode:%d) to window (0x%x) !\e[0m\n", xev->xkey.keycode, (int)xev->xkey.window);
+               XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+
+               tmp_ptr = ptr;
+               ptr = ptr->next ;
+               free(tmp_ptr);
+       }
+
+       SECURE_SLOGD("\e[32m[keyrouter] End of cancel process of a keycode(%d)!\e[0m\n", keycode);
+
+       keyrouter.HardKeys[keycode].pressed_win_ptr = NULL;
+}
+
+static void
+_e_keyrouter_hwkey_event_handler(XEvent *ev)
+{
+       int i;
+       key_event_info* key_data;
+       int result;
+
+       //KeyRelease handling for key composition
+       if( ev->type == KeyRelease )
+       {
+               if((keyrouter.longpress_enabled == 1) && keyrouter.timer_flag == 1)
+               {
+                       result = ShortPressEventDeliver(keyrouter.pressinfo);
+                       if(result == False)
+                               return;
+               }
+               //deliver the key
+               DeliverDeviceKeyEvents(ev);
+
+               ResetModKeyInfo();
+               return;
+       }
+       else if( ev->type == KeyPress ) //KeyPress handling for key composition
+       {
+               SECURE_SLOGD("\n\e[31m[keyrouter][%s] KeyPress (keycode:%d)\e[0m\n", __FUNCTION__, ev->xkey.keycode);
+
+               if((keyrouter.longpress_enabled == 1) && keyrouter.short_press_flag == 0 && keyrouter.timer_flag == 0 && keyrouter.first_press_flag == 1)
+               {
+                       if(keyrouter.HardKeys[ev->xkey.keycode].longpress == True)
+                       {
+                               keyrouter.pressinfo = malloc(sizeof(longpress_info));
+                               keyrouter.pressinfo->keycode = ev->xkey.keycode;
+                               keyrouter.pressinfo->longpress_window = ev->xkey.window;
+                               keyrouter.pressinfo->evtime = ev->xkey.time;
+                               result = LongPressRecognize(ev->xkey.keycode);
+                               return;
+                       }
+               }
+               if((keyrouter.longpress_enabled == 1) && keyrouter.short_press_flag == 0 && keyrouter.timer_flag == 1)
+               {
+                       result = ShortPressEventDeliver(keyrouter.pressinfo);
+                       //Two key Press... if modkey????
+               }
+               keyrouter.short_press_flag = 0;
+               keyrouter.pressinfo = NULL;
+
+               if(!keyrouter.modkey_set)
+               {
+                       for(i=0 ; i < NUM_KEY_COMPOSITION_ACTIONS ; i++)
+                       {
+                               if(!keyrouter.modkey[i].set)
+                               {
+                                       //check modifier key
+                                       keyrouter.modkey[i].idx_mod = IsModKey(ev, i);
+
+                                       if(keyrouter.modkey[i].idx_mod)
+                                       {
+                                               SECURE_SLOGD("\n\e[35m[keyrouter][%s][%d] Modifier Key ! (keycode=%d)\e[0m\n", __FUNCTION__, i, ev->xkey.keycode);
+                                               keyrouter.modkey[i].set = 1;
+                                               keyrouter.modkey_set = 1;
+                                               keyrouter.modkey[i].time = ev->xkey.time;
+                                       }
+                               }
+                       }
+
+                       //deliver the key
+                       DeliverDeviceKeyEvents(ev);
+                       return;
+               }
+               else
+               {
+                       for(i=0 ; i < NUM_KEY_COMPOSITION_ACTIONS ; i++)
+                       {
+                               keyrouter.modkey[i].composited = IsKeyComposited(ev, i);
+
+                               if(keyrouter.modkey[i].composited)
+                               {
+                                       SECURE_SLOGD("\n\e[35m[keyrouter][%s][%d] Composition Key ! (keycode=%d)\e[0m\n", __FUNCTION__, i, ev->xkey.keycode);
+
+                                       _e_keyrouter_cancel_key(ev, keyrouter.modkey[i].keys[keyrouter.modkey[i].idx_mod-1].keycode);
+
+                                       //Do Action : ex> send ClientMessage to root window
+                                       DoKeyCompositionAction(i, 1);
+
+                                       if(keyrouter.modkey[i].press_only)
+                                       {
+                                               //Put Modifier/composited keys' release in ignored_key_list to ignore them
+                                               key_data = malloc(sizeof(key_event_info));
+                                               key_data->ev_type = KeyRelease;
+                                               key_data->keycode = keyrouter.modkey[i].keys[0].keycode;
+                                               keyrouter.ignored_key_list = eina_list_append(keyrouter.ignored_key_list, key_data);
+                                               SECURE_SLOGD("[keyrouter][%s] ignored key added (keycode=%d, type=%d)\n", __FUNCTION__, key_data->keycode, key_data->ev_type);
+
+                                               key_data = malloc(sizeof(key_event_info));
+                                               key_data->ev_type = KeyRelease;
+                                               key_data->keycode = keyrouter.modkey[i].keys[1].keycode;
+                                               keyrouter.ignored_key_list = eina_list_append(keyrouter.ignored_key_list, key_data);
+                                               SECURE_SLOGD("[keyrouter][%s] ignored key added (keycode=%d, type=%d)\n", __FUNCTION__, key_data->keycode, key_data->ev_type);
+                                       }
+                                       else//need to be waited for keys
+                                       {
+                                               //Put Modifier/composited keys' release in waiting_key_list to check them
+                                               key_data = malloc(sizeof(key_event_info));
+                                               key_data->ev_type = KeyRelease;
+                                               key_data->keycode = keyrouter.modkey[i].keys[0].keycode;
+                                               key_data->modkey_index = i;
+                                               keyrouter.waiting_key_list = eina_list_append(keyrouter.waiting_key_list, key_data);
+                                               SECURE_SLOGD("[keyrouter][%s] waiting key added (keycode=%d, type=%d)\n", __FUNCTION__, key_data->keycode, key_data->ev_type);
+
+                                               key_data = malloc(sizeof(key_event_info));
+                                               key_data->ev_type = KeyRelease;
+                                               key_data->keycode = keyrouter.modkey[i].keys[1].keycode;
+                                               key_data->modkey_index = i;
+                                               keyrouter.waiting_key_list = eina_list_append(keyrouter.waiting_key_list, key_data);
+                                               SECURE_SLOGD("[keyrouter][%s] waiting key added (keycode=%d, type=%d)\n", __FUNCTION__, key_data->keycode, key_data->ev_type);
+                                       }
+
+                                       ResetModKeyInfo();
+                                       return;
+                               }
+                       }
+
+                       //deliver the key
+                       DeliverDeviceKeyEvents(ev);
+
+                       ResetModKeyInfo();
+                       return;
+               }
+       }
+}
+
+static int
+_e_keyrouter_cb_event_generic(void *data, int ev_type, void *event)
+{
+       Ecore_X_Event_Generic *e = (Ecore_X_Event_Generic *)event;
+       XIDeviceEvent *evData = (XIDeviceEvent *)(e->data);
+       XEvent xev;
+
+#ifdef _F_REMAP_MOUSE_BUTTON_TO_HWKEY_
+       int keycode = 0;
+       static int home_keycode = 0;
+       static int back_keycode = 0;
+#endif//_F_REMAP_MOUSE_BUTTON_TO_HWKEY_
+
+       if( e->extension != keyrouter.xi2_opcode )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Invalid event !(extension:%d, evtype:%d)\n", __FUNCTION__, e->extension, e->evtype);
+               return 1;
+       }
+
+       if( !evData || evData->send_event )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Generic event data is not available or the event was sent via XSendEvent (and will be ignored) !\n", __FUNCTION__);
+               return 1;
+       }
+
+       switch( e->evtype )
+       {
+               case XI_HierarchyChanged:
+                       _e_keyrouter_xi2_device_hierarchy_handler((XIHierarchyEvent *)evData);
+                       break;
+
+#ifdef _F_REMAP_MOUSE_BUTTON_TO_HWKEY_
+               case XI_ButtonPress:
+               case XI_ButtonRelease:
+                       if( evData->detail == 2 )//Home key
+                       {
+                               if(!home_keycode) home_keycode = ecore_x_keysym_keycode_get(KEY_HOME);
+                               keycode = home_keycode;
+                       }
+                       else if( evData->detail == 3 )//Back key
+                       {
+                               if(!back_keycode) back_keycode = ecore_x_keysym_keycode_get(KEY_BACK);
+                               keycode = back_keycode;
+                       }
+
+                       if(!keycode)
+                               break;
+
+                       xev.xkey.display = keyrouter.disp;
+                       xev.xkey.root = keyrouter.rootWin;
+                       xev.xkey.keycode = keycode;
+                       xev.xkey.time = evData->time;
+                       xev.xkey.type = (XI_ButtonPress==e->evtype) ? KeyPress : KeyRelease;
+                       xev.xkey.state = 0;
+                       xev.xkey.send_event = 1;
+                       xev.xkey.subwindow = None;
+
+                       if(xev.xkey.type == KeyPress) keyrouter.first_press_flag++;
+                       else if(xev.xkey.type == KeyRelease) keyrouter.first_press_flag--;
+
+                       if(!_e_keyrouter_is_waiting_key_list_empty(&xev))
+                               return 1;
+
+                       if(_e_keyrouter_is_key_in_ignored_list(&xev))
+                               return 1;
+
+                       _e_keyrouter_hwkey_event_handler(&xev);
+                       break;
+#endif//_F_REMAP_MOUSE_BUTTON_TO_HWKEY_
+
+               case XI_KeyPress:
+               case XI_KeyRelease:
+                       xev.type = e->evtype;
+                       xev.xkey.keycode = evData->detail;
+                       xev.xany.display = keyrouter.disp;
+                       xev.xkey.time = evData->time;
+                       xev.xkey.state = 0;
+                       xev.xkey.send_event = 1;
+                       xev.xkey.subwindow = None;
+                       xev.xkey.root = keyrouter.rootWin;
+
+                       if(xev.type == XI_KeyPress) keyrouter.first_press_flag++;
+                       else if(xev.type == XI_KeyRelease) keyrouter.first_press_flag--;
+
+                       if(!_e_keyrouter_is_waiting_key_list_empty(&xev))
+                               return 1;
+
+                       if(_e_keyrouter_is_key_in_ignored_list(&xev))
+                               return 1;
+
+                       _e_keyrouter_hwkey_event_handler(&xev);
+                       break;
+       }
+
+       return 1;
+}
+
+static int
+_e_keyrouter_cb_window_create(void *data, int ev_type, void *ev)
+{
+       Ecore_X_Window_Attributes att;
+       Ecore_X_Event_Window_Create *e = ev;
+
+       //Check if current window is TOP-level window or not
+       if( !e || keyrouter.rootWin != e->parent || !e->win )
+               return 1;
+
+       //Setting PropertyChangeMask and SubstructureNotifyMask for TOP-level window (e->win)
+       ecore_x_window_attributes_get(e->win, &att);
+       XSelectInput(keyrouter.disp, e->win, att.event_mask.mine | PropertyChangeMask | StructureNotifyMask);
+       XSync(keyrouter.disp, False);
+
+       int ret = 0, count = 0;
+       int i, keycode, grab_mode;
+       unsigned int *prop_data = NULL;
+
+       //Get the window property using the atom
+       ret = ecore_x_window_prop_property_get (e->win, keyrouter.atomGrabKey, ECORE_X_ATOM_CARDINAL, 32, (unsigned char **)&prop_data, &count);
+
+       if( !ret || !prop_data )
+               goto out;
+
+       //add to list to watch property
+       for( i=0 ; i < count ; i++ )
+       {
+               grab_mode = prop_data[i] & GRAB_MODE_MASK;
+               keycode = prop_data[i] & (~GRAB_MODE_MASK);
+
+               _e_keyrouter_update_key_delivery_list(e->win, keycode, grab_mode, 1);
+       }
+
+out:
+       if(prop_data)   free(prop_data);
+       return 1;
+ }
+
+static int
+_e_keyrouter_cb_window_property(void *data, int ev_type, void *ev)
+{
+       Ecore_X_Event_Window_Property *e = ev;
+
+       int ret = 0, count = 0;
+       unsigned int *prop_data = NULL;
+
+       int res = -1;
+       unsigned int ret_val = 0;
+       unsigned int long_enable_data = 0;
+
+       if( e->atom == keyrouter.atomDeviceStatus && e->win == keyrouter.rootWin )
+       {
+               res = ecore_x_window_prop_card32_get(e->win, keyrouter.atomDeviceStatus, &ret_val, 1);
+
+               if( res == 1 )
+               {
+                       Device_Status(ret_val);
+               }
+
+               goto out;
+       }
+
+       if( e->atom == keyrouter.atomGrabStatus && e->win == keyrouter.rootWin )
+       {
+               res = ecore_x_window_prop_card32_get(e->win, keyrouter.atomGrabStatus, &ret_val, 1);
+
+               if( res == 1 )
+               {
+                       Keygrab_Status(ret_val);
+               }
+
+               goto out;
+       }
+
+       if( e->atom == keyrouter.atomLongPressEnable && e->win == keyrouter.rootWin)
+       {
+               res = ecore_x_window_prop_card32_get(e->win, keyrouter.atomLongPressEnable, &long_enable_data, 1);
+               if(res == 1)
+               {
+                       keyrouter.longpress_enabled = long_enable_data;
+               }
+               goto out;
+       }
+
+       //See the client window has interesting atom (_atomGrabKey)
+       if( e->atom != keyrouter.atomGrabKey)
+               goto out;
+
+       //Get the window property using the atom
+       ret = ecore_x_window_prop_property_get (e->win, e->atom, ECORE_X_ATOM_CARDINAL, 32, (unsigned char **)&prop_data, &count);
+
+       if( !ret || !prop_data )
+       {
+               RemoveWindowDeliveryList(e->win, 0, 0);
+               goto out;
+       }
+
+       RemoveWindowDeliveryList(e->win, 0, 0);
+
+       int i;
+       int keycode;
+       int grab_mode;
+
+       //property¸¦ º¸°í list¿¡ add
+       for( i=0 ; i < count ; i++ )
+       {
+               grab_mode = prop_data[i] & GRAB_MODE_MASK;
+               keycode = prop_data[i] & (~GRAB_MODE_MASK);
+
+               _e_keyrouter_update_key_delivery_list(e->win, keycode, grab_mode, 1);
+       }
+
+out:
+       if(prop_data)   free(prop_data);
+       return 1;
+}
+
+static int
+_e_keyrouter_cb_e_client_stack(void *data, int ev_type, void *ev)
+{
+       E_Event_Client *e = ev;
+
+       if(!e->ec)
+               return 1;
+
+       keyrouter.isWindowStackChanged = 1;
+       AdjustTopPositionDeliveryList(e_client_util_win_get(e->ec), 1);
+
+       return 1;
+}
+
+static int
+_e_keyrouter_cb_e_client_remove(void *data, int ev_type, void *ev)
+{
+       E_Event_Client *e = ev;
+
+       if(!e->ec)
+               return 1;
+       else
+       {
+               keyrouter.isWindowStackChanged = 1;
+               RemoveWindowDeliveryList(e_client_util_win_get(e->ec), 0, 1);
+               return 1;
+       }
+
+       return 1;
+}
+
+static int
+_e_keyrouter_cb_window_destroy(void *data, int ev_type, void *ev)
+{
+       E_Client *ec;
+       Ecore_X_Event_Window_Destroy *e = ev;
+
+       //Skip for client windows which have border as their parents
+       ec = e_pixmap_find_client(E_PIXMAP_TYPE_X, e->win);
+       if (ec)
+               return 1;
+
+       keyrouter.isWindowStackChanged = 1;
+       RemoveWindowDeliveryList(e->win, 0, 1);
+
+       return 1;
+}
+
+static int
+_e_keyrouter_cb_window_configure(void *data, int ev_type, void *ev)
+{
+       E_Client *ec;
+       Ecore_X_Event_Window_Configure *e = ev;
+
+       //Skip for client windows which have border as their parents
+       ec = e_pixmap_find_client(E_PIXMAP_TYPE_X, e->win);
+        if (ec)
+               return 1;
+
+       if( keyrouter.rootWin != e->event_win )
+               return 1;
+
+       keyrouter.isWindowStackChanged = 1;
+       AdjustTopPositionDeliveryList(e->win, !!e->abovewin);
+
+       return 1;
+}
+
+static int
+_e_keyrouter_cb_client_message (void* data, int type, void* event)
+{
+       int event_type = 0;
+       int keycode;
+       int cancel = 0;
+       Ecore_X_Event_Client_Message* ev;
+       Ecore_X_Window longpress_win;;
+       int longpress_timeout;
+       longpress_info *linfo;
+       int i, col=0;
+       KeySym msgsym;
+       longpress_info *datatmp;
+       Eina_List *ltemp;
+       unsigned int enable = 1;
+
+       ev = event;
+       if(ev->message_type != keyrouter.atomHWKeyEmulation) return 1;
+       if(ev->format == 8)
+       {
+               if( ev->data.b[0] == 'P' )
+                       event_type = KeyPress;
+               else if( ev->data.b[0] == 'R' )
+                       event_type = KeyRelease;
+
+               if( ev->data.b[1] == 'C' )
+                       cancel = 1;
+
+               switch(event_type)
+               {
+                       case KeyPress:
+                       case KeyRelease:
+                               keycode = XKeysymToKeycode(keyrouter.disp, XStringToKeysym(&ev->data.b[2]));
+                               _e_keyrouter_do_hardkey_emulation(NULL, event_type, 0, keycode, cancel);
+                               break;
+
+                       default:
+                               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][cb_client_message] Unknown event type ! (type=%d)\n", event_type);
+               }
+       }
+
+       else if(ev->format == 32)
+       {
+               longpress_win = None;
+               keycode = 0;
+               longpress_timeout = 0;
+
+               //if( ev->data.l[0] != NULL )
+               {
+                       longpress_win = (Ecore_X_Window)ev->data.l[0];
+               }
+               //if( ev->data.l[1] != NULL )
+               {
+                       keycode = (int)ev->data.l[1];
+               }
+               //if( ev->data.l[2] != NULL )
+               {
+                       longpress_timeout= (int)ev->data.l[2];
+               }
+               if( longpress_win && keycode && longpress_timeout )
+               {
+                       if(keyrouter.HardKeys[keycode].longpress == False)
+                       {
+                               msgsym = XkbKeycodeToKeysym(keyrouter.disp, (KeyCode)keycode, col, 0);
+                               for(i=MIN_KEYCODE; i<MAX_HARDKEYS; i++)
+                               {
+                                       if(XkbKeycodeToKeysym(keyrouter.disp, i, col, 0) == msgsym)
+                                       {
+                                               keyrouter.HardKeys[i].longpress = True;
+                                               linfo = malloc(sizeof(longpress_info));
+                                               linfo->longpress_window = longpress_win;
+                                               linfo->keycode = i;
+                                               linfo->longpress_timeout = longpress_timeout;
+                                               keyrouter.longpress_list = eina_list_append(keyrouter.longpress_list, linfo);
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               msgsym = XkbKeycodeToKeysym(keyrouter.disp, (KeyCode)keycode, col, 0);
+                               for(i=MIN_KEYCODE; i<MAX_HARDKEYS; i++)
+                               {
+                                       if(XkbKeycodeToKeysym(keyrouter.disp, i, col, 0) == msgsym)
+                                       {
+                                               EINA_LIST_FOREACH(keyrouter.longpress_list, ltemp, datatmp)
+                                               {
+                                                       if(datatmp->keycode == i)
+                                                       {
+                                                               datatmp->longpress_window = longpress_win;
+                                                               datatmp->longpress_timeout = longpress_timeout;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       keyrouter.longpress_enabled = enable;
+                       ecore_x_window_prop_card32_set(keyrouter.rootWin, keyrouter.atomLongPressEnable, &enable, 1);
+               }
+       }
+
+       return 1;
+}
+
+static int
+_e_keyrouter_cb_window_stack(void *data, int ev_type, void *ev)
+{
+       E_Client *ec;
+       Ecore_X_Event_Window_Stack *e = ev;
+
+       //Skip for client windows which have border as their parents
+       ec = e_pixmap_find_client(E_PIXMAP_TYPE_X, e->win);
+       if (ec)
+               return 1;
+
+       if( keyrouter.rootWin != e->event_win )
+               return 1;
+
+       keyrouter.isWindowStackChanged = 1;
+       AdjustTopPositionDeliveryList(e->win, !e->detail);
+
+       return 1;
+}
+
+//e17 bindings functions and action callbacks
+
+static int
+_e_keyrouter_modifiers(E_Binding_Modifier modifiers)
+{
+   int mod = 0;
+
+   if (modifiers & E_BINDING_MODIFIER_SHIFT) mod |= ECORE_EVENT_MODIFIER_SHIFT;
+   if (modifiers & E_BINDING_MODIFIER_CTRL) mod |= ECORE_EVENT_MODIFIER_CTRL;
+   if (modifiers & E_BINDING_MODIFIER_ALT) mod |= ECORE_EVENT_MODIFIER_ALT;
+   if (modifiers & E_BINDING_MODIFIER_WIN) mod |= ECORE_EVENT_MODIFIER_WIN;
+   /* see comment in e_bindings on numlock
+      if (modifiers & ECORE_X_LOCK_NUM) mod |= ECORE_X_LOCK_NUM;
+   */
+
+   return mod;
+}
+
+static void _e_keyrouter_do_bound_key_action(XEvent *xev)
+{
+       Ecore_Event_Key *ev;
+       int keycode = xev->xkey.keycode;
+
+       if( !keyrouter.HardKeys[keycode].bind )
+       {
+               SECURE_SLOGD("[keyrouter][do_bound_key_action] bind info of key(%d) is NULL !\n", keycode);
+               return;
+       }
+
+       ev = malloc(sizeof(Ecore_Event_Key));
+
+       if( !ev )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][do_bound_key_action] Failed to allocate memory for Ecore_Event_Key !\n");
+               return;
+       }
+
+       ev->keyname = (char *)malloc(strlen(keyrouter.HardKeys[keycode].bind->key)+1);
+       ev->key = (char *)malloc(strlen(keyrouter.HardKeys[keycode].bind->key)+1);
+
+       if( !ev->keyname || !ev->key )
+       {
+               free(ev);
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][do_bound_key_action] Failed to allocate memory for key name !\n");
+               return;
+       }
+
+       strncpy((char *)ev->keyname, keyrouter.HardKeys[keycode].bind->key, strlen(keyrouter.HardKeys[keycode].bind->key)+1);
+       strncpy((char *)ev->key, keyrouter.HardKeys[keycode].bind->key, strlen(keyrouter.HardKeys[keycode].bind->key)+1);
+
+       ev->compose = NULL;
+       ev->string = NULL;
+       ev->modifiers = 0;
+       ev->timestamp = xev->xkey.time;
+       ev->event_window = xev->xkey.window;
+       ev->root_window = xev->xkey.root;
+       ev->same_screen = xev->xkey.same_screen;
+       ev->window = xev->xkey.subwindow ? xev->xkey.subwindow : xev->xkey.window;
+
+       if( xev->type == KeyPress )
+               e_bindings_key_down_event_handle(keyrouter.HardKeys[keycode].bind->ctxt, NULL, ev);
+       else if( xev->type == KeyRelease )
+               e_bindings_key_up_event_handle(keyrouter.HardKeys[keycode].bind->ctxt, NULL, ev);
+
+       free(ev);
+}
+
+static void _e_keyrouter_xi2_device_hierarchy_handler(XIHierarchyEvent *event)
+{
+       int i;
+
+       if( event->flags & XIDeviceEnabled || event->flags & XIDeviceDisabled )
+       {
+               for( i = 0 ; i < event->num_info ; i++ )
+               {
+                       if( event->info[i].flags & XIDeviceEnabled )
+                       {
+                               _e_keyrouter_device_add(event->info[i].deviceid, event->info[i].use);
+                       }
+                       else if( event->info[i].flags & XIDeviceDisabled )
+                       {
+                               _e_keyrouter_device_remove(event->info[i].deviceid, event->info[i].use);
+                       }
+               }
+       }
+}
+
+static Eina_Bool _e_keyrouter_is_waiting_key_list_empty(XEvent *ev)
+{
+       int modkey_index;
+       Eina_List* l;
+       key_event_info* data;
+       key_event_info* key_data;
+
+       if( !keyrouter.waiting_key_list )
+       {
+               return EINA_TRUE;
+       }
+
+       SECURE_SLOGD("[keyrouter][%s] waiting_key_list is NOT empty !\n", __FUNCTION__);
+       SECURE_SLOGD("[keyrouter][%s] type=%s, keycode=%d", __FUNCTION__, (ev->xkey.type==KeyPress) ? "KeyPress" : "KeyRelease", ev->xkey.keycode);
+
+       EINA_LIST_FOREACH(keyrouter.waiting_key_list, l, data)
+       {
+               if( data && ev->type == data->ev_type && ev->xkey.keycode == data->keycode )
+               {
+                       //found !!!
+                       SECURE_SLOGD("[keyrouter][%s] found !!! (keycode:%d, type=%d)\n", __FUNCTION__, data->keycode, data->ev_type);
+                       goto found;
+               }
+       }
+
+       SECURE_SLOGD("[keyrouter][%s] not found !!! (keycode:%d, type=%d)\n", __FUNCTION__, ev->xkey.keycode, ev->type);
+
+       //If a key press is coming before the waiting_key_list is cleared,
+       //put its release into ignored_list.
+       if(ev->type == KeyPress)
+       {
+               key_data = malloc(sizeof(key_event_info));
+               key_data->ev_type = KeyRelease;
+               key_data->keycode = ev->xkey.keycode;
+               keyrouter.ignored_key_list = eina_list_append(keyrouter.ignored_key_list, key_data);
+               SECURE_SLOGD("[keyrouter][%s] ignored key added (keycode=%d, type=%d)\n", __FUNCTION__, key_data->keycode, key_data->ev_type);
+       }
+       else if(ev->type == KeyRelease)
+       {
+               //If a key release which is contained in ignored_key_list is coming,
+               //remove it from ignored_key_list.
+               SECURE_SLOGD("[keyrouter][%s] check a key is exiting in ignored key list (keycode=%d, type=%d)\n", __FUNCTION__, ev->xkey.keycode, ev->type);
+               _e_keyrouter_is_key_in_ignored_list(ev);
+       }
+
+       return EINA_FALSE;
+
+found:
+       modkey_index = data->modkey_index;
+       keyrouter.waiting_key_list = eina_list_remove(keyrouter.waiting_key_list, data);
+       SECURE_SLOGD("[keyrouter][%s][%d] key was remove from waiting_key_list !(keycode:%d, type:%d)\n",
+               __FUNCTION__, modkey_index, ev->xkey.keycode, ev->type);
+
+       if(!keyrouter.waiting_key_list)
+       {
+               SECURE_SLOGD("[keyrouter][%s] Waiting conditions are satified !\n", __FUNCTION__);
+
+               //Do Action : ex> send ClientMessage to root window
+               DoKeyCompositionAction(modkey_index, 0);
+       }
+
+       return EINA_FALSE;
+}
+
+
+static Eina_Bool _e_keyrouter_is_key_in_ignored_list(XEvent *ev)
+{
+       Eina_List* l;
+       key_event_info* data;
+
+       if( !keyrouter.ignored_key_list )
+       {
+               return EINA_FALSE;
+       }
+
+       SECURE_SLOGD("[keyrouter][%s] ignored_key_list is NOT empty !\n", __FUNCTION__);
+
+       EINA_LIST_FOREACH(keyrouter.ignored_key_list, l, data)
+       {
+               if( data && ev->type == data->ev_type && ev->xkey.keycode == data->keycode )
+               {
+                       //found !!!
+                       SECURE_SLOGD("[keyrouter][%s] found !!! (keycode:%d, type=%d)\n", __FUNCTION__, data->keycode, data->ev_type);
+                       goto found;
+               }
+       }
+
+       SECURE_SLOGD("[keyrouter][%s] not found !!! (keycode:%d, type=%d)\n", __FUNCTION__, ev->xkey.keycode, ev->type);
+
+       return EINA_FALSE;
+
+found:
+       keyrouter.ignored_key_list = eina_list_remove(keyrouter.ignored_key_list, data);
+       SECURE_SLOGD("[keyrouter][%s] key was remove from ignored_list !(keycode:%d, type:%d)\n", __FUNCTION__, ev->xkey.keycode, ev->type);
+
+       return EINA_TRUE;
+}
+
+static void _e_keyrouter_device_add(int id, int type)
+{
+       int ndevices;
+       Eina_List* l;
+       XIDeviceInfo *info = NULL;
+       KeyrouterDeviceType kdtype = E_KEYROUTER_NONE;
+       E_Keyrouter_Device_Info *kdi = NULL;
+
+       EINA_LIST_FOREACH(keyrouter.device_list, l, kdi)
+       {
+               if( (kdi) && (kdi->type==E_KEYROUTER_HWKEY) && (kdi->id == id) )
+               {
+                       SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter] Slave key device (id=%d, name=%s) was added !\n", id, kdi->name);
+                       detachSlave(id);
+                       return;
+               }
+       }
+       switch(type)
+       {
+               case XISlavePointer:
+                       info = XIQueryDevice(keyrouter.disp, id, &ndevices);
+                       if( !info || ndevices <= 0 )
+                       {
+                               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter] There is no queried XI device. (device id=%d, type=%d)\n", id, type);
+                               goto out;
+                       }
+                       if( strcasestr(info->name, "XTEST" ) || strcasestr(info->name, "Touch" ) || strcasestr(info->name, "mouse") )
+                               goto out;
+                       SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter] XISlavePointer but has key events... (device id=%d, name=%s)\n", id, info->name);
+                       kdtype = E_KEYROUTER_KEYBOARD;
+                       goto keyboard_added;
+
+                       break;
+               case XISlaveKeyboard:
+                       info = XIQueryDevice(keyrouter.disp, id, &ndevices);
+
+                       if( !info || ndevices <= 0 )
+                       {
+                               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] There is no queried XI device. (device id=%d, type=%d)\n", __FUNCTION__, id, type);
+                               goto out;
+                       }
+                       if( strcasestr(info->name, "XTEST" ) )
+                               goto out;
+keyboard_added:
+                       if( (kdtype == E_KEYROUTER_NONE) && strcasestr(info->name, "keyboard" ) )
+                               kdtype = E_KEYROUTER_KEYBOARD;
+                       else
+                               kdtype = E_KEYROUTER_HOTPLUGGED;
+
+                       E_Keyrouter_Device_Info *data = malloc(sizeof(E_Keyrouter_Device_Info));
+
+                       if( !data )
+                       {
+                               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to allocate memory for device info !\n", __FUNCTION__);
+                               goto out;
+                       }
+
+                       data->type = kdtype;
+                       data->id = id;
+                       data->name = eina_stringshare_add(info->name);
+                       keyrouter.device_list = eina_list_append(keyrouter.device_list, data);
+
+                       _e_keyrouter_grab_hwkeys(id);
+       }
+
+out:
+       if( info )      XIFreeDeviceInfo(info);
+}
+
+static void _e_keyrouter_device_remove(int id, int type)
+{
+       Eina_List* l;
+       E_Keyrouter_Device_Info *data;
+
+       if( !keyrouter.device_list )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] device list is empty ! something's wrong ! (id=%d, type=%d)\n", __FUNCTION__, id, type);
+               goto out;
+       }
+
+       EINA_LIST_FOREACH(keyrouter.device_list, l, data)
+       {
+               if( data && data->id == id )
+               {
+                       switch( data->type )
+                       {
+                               case E_KEYROUTER_HWKEY:
+                                       break;
+
+                               case E_KEYROUTER_HOTPLUGGED:
+                               case E_KEYROUTER_KEYBOARD:
+                                       SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Slave hotplugged key|keyboard device (id=%d, name=%s, type=%d) was removed/disabled !\n",
+                                               __FUNCTION__, id, data->name, type);
+                                       keyrouter.device_list = eina_list_remove(keyrouter.device_list, data);
+                                       free(data);
+                                       goto out;
+
+                               default:
+                                       SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Unknown type of device ! (id=%d, type=%d, name=%s, device type=%d)\n",
+                                               __FUNCTION__, data->id, type, data->name, data->type);
+                                       keyrouter.device_list = eina_list_remove(keyrouter.device_list, data);
+                                       free(data);
+                                       goto out;
+                       }
+               }
+       }
+
+out:
+       return;
+}
+
+static E_Zone* _e_keyrouter_get_zone()
+{
+       const Eina_List *cl;
+       E_Comp *c;
+       E_Zone *zone = NULL;
+
+       if( keyrouter.zone )
+               return keyrouter.zone;
+
+       EINA_LIST_FOREACH(e_comp_list(), cl, c)
+       {
+               Eina_List *zl;
+               E_Zone *z;
+
+               EINA_LIST_FOREACH(c->zones, zl, z)
+               {
+                       if (z)
+                       zone = z;
+               }
+       }
+
+       return zone;
+}
+
+int _e_keyrouter_init()
+{
+       int ret = 1;
+       int grab_result;
+       unsigned int enable = 0;
+
+       _e_keyrouter_structure_init();
+       keyrouter.disp = NULL;
+       keyrouter.disp = ecore_x_display_get();
+
+       if( !keyrouter.disp )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "\e[32m[keyrouter] Failed to open display..!\e[0m\n");
+               ret = 0;
+               goto out;
+       }
+
+       keyrouter.rootWin = DefaultRootWindow(keyrouter.disp);
+
+       _e_keyrouter_x_input_init();
+       InitGrabKeyDevices();
+       _e_keyrouter_bindings_init();
+
+       keyrouter.atomDeviceStatus = ecore_x_atom_get(STR_ATOM_DEVICE_STATUS);
+       keyrouter.atomGrabStatus = ecore_x_atom_get(STR_ATOM_GRAB_STATUS);
+       keyrouter.atomGrabKey = ecore_x_atom_get(STR_ATOM_GRAB_KEY);
+       keyrouter.atomGrabExclWin = ecore_x_atom_get(STR_ATOM_GRAB_EXCL_WIN);
+       keyrouter.atomGrabORExclWin = ecore_x_atom_get(STR_ATOM_GRAB_OR_EXCL_WIN);
+       keyrouter.atomHWKeyEmulation = ecore_x_atom_get(PROP_HWKEY_EMULATION);
+       keyrouter.atomMenuLongPress = ecore_x_atom_get(STR_ATOM_KEY_MENU_LONGPRESS);
+       keyrouter.atomBackLongPress = ecore_x_atom_get(STR_ATOM_KEY_BACK_LONGPRESS);
+       keyrouter.atomLongPressEnable = ecore_x_atom_get(STR_ATOM_LONG_PRESS_ENABLE);
+       keyrouter.atomNotiWindow = ecore_x_atom_get(STR_ATOM_KEYROUTER_NOTIWINDOW);
+
+       keyrouter.input_window = ecore_x_window_input_new(keyrouter.rootWin, -1, -1, 1, 1);
+       keyrouter.noti_window = ecore_x_window_input_new(keyrouter.rootWin, -1, -1, 1, 1);
+       keyrouter.longpress_enabled = enable;
+
+       ecore_x_window_prop_card32_set(keyrouter.rootWin, keyrouter.atomLongPressEnable, &enable, 1);
+
+       if(!keyrouter.input_window)
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter] Failed to create input_window !\n");
+       }
+       else
+       {
+               ecore_x_window_prop_property_set(keyrouter.rootWin, keyrouter.atomHWKeyEmulation, ECORE_X_ATOM_WINDOW, 32, &keyrouter.input_window, 1);
+       }
+
+       if(!keyrouter.noti_window)
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter] Failed to create noti_window !\n");
+       }
+       else
+       {
+               ecore_x_window_prop_property_set(keyrouter.rootWin, keyrouter.atomNotiWindow, ECORE_X_ATOM_WINDOW, 32, &keyrouter.noti_window, 1);
+       }
+
+       keyrouter.zone = _e_keyrouter_get_zone();
+       if( !keyrouter.zone )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter] Failed to get zone !\n");
+               ret = 0;
+               goto out;
+       }
+
+       grab_result = GrabKeyDevices(keyrouter.rootWin);
+
+       if( !grab_result )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "\e[32m[keyrouter] Failed to GrabDevices() !\e[0m\n");
+               ret = 0;
+               goto out;
+       }
+
+       keyrouter.DeviceKeyPress = keyrouter.nInputEvent[INPUTEVENT_KEY_PRESS];
+       keyrouter.DeviceKeyRelease = keyrouter.nInputEvent[INPUTEVENT_KEY_RELEASE];
+
+       keyrouter.modkey = calloc(NUM_KEY_COMPOSITION_ACTIONS, sizeof(ModifierKey));
+
+       if(!keyrouter.modkey)
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "\e[32m[keyrouter] Failed to allocate memory for key composition !\e[0m\n");
+               ret = 0;
+               goto out;
+       }
+
+       InitModKeys();
+       BuildKeyGrabList(keyrouter.rootWin);
+
+out:
+       return ret;
+}
+
+void _e_keyrouter_fini()
+{
+       UngrabKeyDevices();
+}
+
+static void _e_keyrouter_structure_init()
+{
+       memset(&keyrouter, 0L, sizeof(keyrouter));
+
+       keyrouter.DeviceKeyPress = -1;
+       keyrouter.DeviceKeyRelease = -1;
+       keyrouter.xi2_opcode = -1;
+       keyrouter.isWindowStackChanged = 1;
+       keyrouter.prev_sent_keycode = 0;
+       keyrouter.resTopVisibleCheck = 0;
+       keyrouter.device_list = NULL;
+       keyrouter.ignored_key_list = NULL;
+       keyrouter.waiting_key_list = NULL;
+       keyrouter.hwkeymap_info_list = NULL;
+       keyrouter.longpress_list = NULL;
+       keyrouter.pressinfo = NULL;
+       keyrouter.num_hwkey_devices = 0;
+       keyrouter.timer_flag=0;
+       keyrouter.short_press_flag = 0;
+       keyrouter.first_press_flag = 0;
+       keyrouter.longpress_enabled = 0;
+
+       keyrouter.atomGrabKey = None;
+       keyrouter.atomDeviceStatus = None;
+       keyrouter.atomGrabStatus = None;
+       keyrouter.atomGrabExclWin = None;
+       keyrouter.atomGrabORExclWin = None;
+       keyrouter.atomMenuLongPress = None;
+       keyrouter.atomBackLongPress = None;
+       keyrouter.atomLongPressEnable = None;
+}
+
+static void _e_keyrouter_grab_hwkeys(int devid)
+{
+       int i, j, k;
+       int result;
+       KeySym ksym;
+
+       int min_keycode, max_keycode, keysyms_per_keycode;
+       KeySym *keymap = NULL, *origkeymap = NULL;
+
+       XIGrabModifiers modifiers[] = {{XIAnyModifier, 0}};
+       int nmods = sizeof(modifiers)/sizeof(modifiers[0]);
+       XIEventMask mask;
+
+       if(!keyrouter.hwkeymap_info_list)
+       {
+               XDisplayKeycodes (keyrouter.disp, &min_keycode, &max_keycode);
+               origkeymap = XGetKeyboardMapping (keyrouter.disp, min_keycode,
+                                                 (max_keycode - min_keycode + 1),
+                                                 &keysyms_per_keycode);
+
+               if(!origkeymap)
+               {
+                       SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter] Failed to get keyboard mapping from X \n");
+                       return;
+               }
+
+               for( i = 0 ; i < NUM_HWKEYS ; i++ )
+               {
+                       if(!HWKeys[i])
+                               break;
+
+                       Eina_Inlist *l = keyrouter.hwkeymap_info_list;
+
+                       ksym = XStringToKeysym(HWKeys[i]);
+
+                       if((ksym == NoSymbol) ||(ksym == keyrouter.cancel_key.keysym))
+                               continue;
+
+                       hwkeymap_info *hki = NULL;
+
+                       hki = calloc(1, sizeof(hwkeymap_info));
+
+                       if(!hki)
+                       {
+                               SLOG(LOG_ERROR, "KEYROUTER", "[keyrouter] Failed to allocate memory for HW keymap information !\n");
+                               XFree(origkeymap);
+                               return;
+                       }
+
+                       hki->key_name = HWKeys[i];
+                       hki->key_sym = ksym;
+                       hki->keycodes = NULL;
+
+                       keymap = origkeymap;
+                       k = 0;
+                       for (j = min_keycode; j <= max_keycode; j++)
+                       {
+                               if(ksym == keymap[0])
+                                       k++;
+                               keymap += keysyms_per_keycode;
+                       }
+
+                       hki->num_keycodes = k;
+
+                       int *keycodes = calloc(1, sizeof(int)*(hki->num_keycodes));
+
+                       if(!keycodes)
+                       {
+                               SLOG(LOG_ERROR, "KEYROUTER", "[keyrouter] Failed to allocate memory for keycode array !\n");
+                               XFree(origkeymap);
+                               free(hki);
+                               return;
+                       }
+
+                       keymap = origkeymap;
+                       k = 0;
+                       for (j = min_keycode; j <= max_keycode; j++)
+                       {
+                               if(ksym == keymap[0])
+                               {
+                                       keycodes[k] = j;
+                                       k++;
+                               }
+                               keymap += keysyms_per_keycode;
+                       }
+
+                       hki->keycodes = keycodes;
+                       l = eina_inlist_append(l, (Eina_Inlist *)hki);
+                       keyrouter.hwkeymap_info_list = l;
+               }
+
+               if(origkeymap)
+                       XFree(origkeymap);
+       }
+
+       hwkeymap_info *hkinfo = NULL;
+       Eina_Inlist *lst = keyrouter.hwkeymap_info_list;
+
+       if(devid)
+       {
+               mask.deviceid = devid;
+               mask.mask_len = XIMaskLen(XI_LASTEVENT);
+               mask.mask = calloc(mask.mask_len, sizeof(char));
+               XISetMask(mask.mask, XI_KeyPress);
+               XISetMask(mask.mask, XI_KeyRelease);
+       }
+
+       EINA_INLIST_FOREACH(lst, hkinfo)
+       {
+               if(!hkinfo->keycodes)
+                       continue;
+
+               for(k = 0 ; k < hkinfo->num_keycodes ; k++)
+               {
+                       if(devid)
+                       {
+                               result = XIGrabKeycode(keyrouter.disp, devid, hkinfo->keycodes[k], keyrouter.rootWin, GrabModeAsync, GrabModeAsync, False, &mask, nmods, modifiers);
+
+                               if(result < 0)
+                               {
+                                       SECURE_SLOGD("[keyrouter][grab_hwkeys] Failed to grab keycode (=%d) !\n", hkinfo->keycodes[k]);
+                                       continue;
+                               }
+                       }
+
+                       //disable repeat for a key
+                       _e_keyrouter_set_key_repeat(hkinfo->keycodes[k], 0);//OFF
+               }
+       }
+
+       if(devid)
+       {
+               free(mask.mask);
+       }
+}
+
+static void
+_e_keyrouter_set_key_repeat(int key, int auto_repeat_mode)
+{
+       XKeyboardControl values;
+
+       values.auto_repeat_mode = auto_repeat_mode;
+
+       if (key != -1)
+       {
+               values.key = key;
+               XChangeKeyboardControl(keyrouter.disp, KBKey | KBAutoRepeatMode, &values);
+       }
+       else
+       {
+               XChangeKeyboardControl(keyrouter.disp, KBAutoRepeatMode, &values);
+       }
+}
+
+
+static void _e_keyrouter_bindings_init()
+{
+       int i;
+       int keycode;
+       KeySym ksym;
+
+       for( i = 0 ; i < NUM_HWKEYS ; i++ )
+       {
+               if( HWKeys[i] )
+               {
+                       ksym = XStringToKeysym(HWKeys[i]);
+
+                       if( ksym )
+                               keycode = XKeysymToKeycode(keyrouter.disp, ksym);
+                       else
+                               keycode = 0;
+
+                       if( !keycode || keycode >= 255 )
+                       {
+                               continue;
+                       }
+
+                       //get bound key information
+                       keyrouter.HardKeys[keycode].bind = e_bindings_key_find(HWKeys[i], E_BINDING_MODIFIER_NONE, 1);
+
+                       if( !keyrouter.HardKeys[keycode].bind || strcmp(keyrouter.HardKeys[keycode].bind->key, HWKeys[i]) )
+                       {
+                               continue;
+                       }
+
+                       //ungrab bound key(s)
+                       ecore_x_window_key_ungrab(keyrouter.rootWin, keyrouter.HardKeys[keycode].bind->key,
+                                      _e_keyrouter_modifiers(keyrouter.HardKeys[keycode].bind->mod), keyrouter.HardKeys[keycode].bind->any_mod);
+
+                       SECURE_SLOGD("[keyrouter][bindings_init] %s (keycode:%d) was bound !!\n", keyrouter.HardKeys[keycode].bind->key, keycode);
+               }
+               else
+                       break;
+       }
+}
+
+static void
+_e_keyrouter_update_key_delivery_list(Ecore_X_Window win, int keycode, const int grab_mode, const int IsOnTop)
+{
+       int c=0;
+       int result = 0;
+       Eina_Bool found = EINA_FALSE;
+       hwkeymap_info *hkinfo = NULL;
+       Eina_Inlist *lst;
+
+       if(!keyrouter.hwkeymap_info_list)
+               goto grab_a_keycode_only;
+
+       lst = keyrouter.hwkeymap_info_list;
+       EINA_INLIST_FOREACH(lst, hkinfo)
+       {
+               if(hkinfo && hkinfo->keycodes)
+               {
+                       for(c = 0 ; c < hkinfo->num_keycodes ; c++)
+                       {
+                               if(hkinfo->keycodes[c] == keycode)
+                               {
+                                       found = EINA_TRUE;
+                                       break;
+                               }
+                       }
+
+                       if(!found) continue;
+
+                       for(c = 0 ; c < hkinfo->num_keycodes ; c++)
+                       {
+                               result = AddWindowToDeliveryList(win, hkinfo->keycodes[c], grab_mode, 1);
+
+                               if( result )
+                                       SECURE_SLOGD("\e[32m[keyrouter][%s] Failed to add window (0x%x) to delivery list ! keycode=%x, grab_mode=0x%X\e[0m\n", __FUNCTION__, win, hkinfo->keycodes[c], grab_mode);
+                       }
+
+                       return;
+               }
+       }
+
+       return;
+
+grab_a_keycode_only:
+
+               result = AddWindowToDeliveryList(win,  keycode, grab_mode, 1);
+
+               if( result )
+               {
+                       SECURE_SLOGD("\e[32m[keyrouter][%s] Failed to add window (0x%x) to delivery list ! keycode=%x, grab_mode=0x%X\e[0m\n", __FUNCTION__, win, keycode, grab_mode);
+               }
+}
+
+static int GetItemFromWindow(Window win, const char* atom_name, unsigned int **key_list)
+{
+       Atom ret_type;
+       int ret_format;
+       unsigned long nr_item = 0;
+       unsigned long sz_remains_data;
+       Atom grabKey;
+
+       grabKey = XInternAtom(keyrouter.disp, atom_name, False);
+
+       if (XGetWindowProperty(keyrouter.disp, win, grabKey, 0, 0x7fffffff, False, XA_CARDINAL,
+                               &ret_type, &ret_format, &nr_item,
+                               &sz_remains_data, (unsigned char **)key_list) != Success)
+       {
+               nr_item = 0;
+       }
+
+       return nr_item;
+}
+
+static void BuildKeyGrabList(Window root)
+{
+       Window tmp;
+       Window *childwins = NULL;
+       unsigned int num_children;
+       register unsigned int i, j;
+       int grab_mode, keycode;
+       unsigned int *key_list = NULL;
+       int n_items = 0;
+    int res;
+
+       XGrabServer(keyrouter.disp);
+       res = XQueryTree(keyrouter.disp, root, &tmp, &tmp, &childwins, &num_children);
+       XUngrabServer(keyrouter.disp);
+    if (0 == res) return;
+
+       for( i=0 ; i < num_children; i++ )
+       {
+               BuildKeyGrabList(childwins[i]);
+
+               n_items = GetItemFromWindow(childwins[i], STR_ATOM_GRAB_KEY, &key_list);
+               if( n_items )
+               {
+                       for( j=0 ; j < n_items ; j++ )
+                       {
+                               grab_mode = key_list[j] & GRAB_MODE_MASK;
+                               keycode = key_list[j] & (~GRAB_MODE_MASK);
+
+                               _e_keyrouter_update_key_delivery_list(childwins[i], keycode, grab_mode, 1);
+                       }
+
+                       if ( key_list )
+                       {
+                               XFree(key_list);
+                               key_list = NULL;
+                       }
+               }
+       }
+
+       if( key_list ) XFree(key_list);
+       if( childwins ) XFree(childwins);
+}
+
+static void InitGrabKeyDevices()
+{
+       memset(keyrouter.HardKeys, (int)NULL, sizeof(keyrouter.HardKeys));
+}
+
+//Function for getting device pointer through device name
+static int GrabKeyDevice(Window win,
+               const char* DeviceName,
+               const int DeviceID)
+{
+       int result;
+       XEventClass eventList[32];
+       XEventClass cls;
+
+       XDevice* pDev = NULL;
+
+       pDev = XOpenDevice(keyrouter.disp, DeviceID);
+
+       if( !pDev )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Fail to open the device (id=%d) !\n", __FUNCTION__, DeviceID);
+               goto out;
+       }
+
+       /* key events */
+       DeviceKeyPress(pDev, keyrouter.nInputEvent[INPUTEVENT_KEY_PRESS], cls);
+       if( cls )       eventList[INPUTEVENT_KEY_PRESS] = cls;
+       DeviceKeyRelease(pDev, keyrouter.nInputEvent[INPUTEVENT_KEY_RELEASE], cls);
+       if( cls )       eventList[INPUTEVENT_KEY_RELEASE] = cls;
+
+       result = XGrabDevice(keyrouter.disp, pDev, win, False, INPUTEVENT_KEY_RELEASE+1, eventList, GrabModeAsync, GrabModeAsync, CurrentTime);
+
+       if( result )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Fail to grab the device (error=%d, id=%d) !\n", __FUNCTION__, result, DeviceID);
+               if( pDev )      XCloseDevice(keyrouter.disp, pDev);
+               goto out;
+       }
+
+       return 1;
+
+out:
+       return 0;
+}
+
+static void detachSlave(int DeviceID)
+{
+       XIDetachSlaveInfo detach;
+       detach.type = XIDetachSlave;
+       detach.deviceid = DeviceID;
+
+       XIChangeHierarchy(keyrouter.disp, (XIAnyHierarchyChangeInfo*)&detach, 1);
+}
+
+static int GrabKeyDevices(Window win)
+{
+       int i, ndevices, result;
+       XIDeviceInfo *dev, *info = NULL;
+       KeyrouterDeviceType kdtype;
+
+       info = XIQueryDevice(keyrouter.disp, XIAllDevices, &ndevices);
+
+       if( !info )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] There is no queried XI device.\n", __FUNCTION__);
+               return 0;
+       }
+
+       for( i = 0; i < ndevices ; i++ )
+       {
+               dev = &info[i];
+               kdtype = E_KEYROUTER_HWKEY;
+
+               switch(dev->use)
+               {
+                       case XISlavePointer:
+                               if( strcasestr(dev->name, "XTEST" ) || strcasestr(dev->name, "Touch" ) || strcasestr(dev->name, "mouse") )
+                                       continue;
+
+                               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter] XISlavePointer but has key events... (device id=%d, name=%s)\n", dev->deviceid, dev->name);
+                               kdtype = E_KEYROUTER_KEYBOARD;
+                               goto keyboard_added;
+                               break;
+                       case XISlaveKeyboard:
+                               if( strcasestr(dev->name, "XTEST" ) )
+                                       continue;
+
+                               if( strcasestr(dev->name, "keyboard") )
+                                       kdtype = E_KEYROUTER_KEYBOARD;
+
+keyboard_added:
+                               if( kdtype == E_KEYROUTER_HWKEY )
+                               {
+                                       result = GrabKeyDevice(win, dev->name, dev->deviceid);
+                                       if(!result)
+                                       {
+                                               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter] Failed to grab key device(name=%s, result=%d)\n", dev->name, result);
+                                               continue;
+                                       }
+
+                                       _e_keyrouter_grab_hwkeys(0);
+                               }
+                               else
+                               {
+                                       _e_keyrouter_grab_hwkeys(dev->deviceid);
+                               }
+
+                               E_Keyrouter_Device_Info *data = malloc(sizeof(E_Keyrouter_Device_Info));
+
+                               if( data )
+                               {
+                                       data->id = dev->deviceid;
+                                       data->name = eina_stringshare_add(dev->name);
+                                       data->type = kdtype;
+                                       keyrouter.device_list = eina_list_append(keyrouter.device_list, data);
+                               }
+
+                               if( kdtype == E_KEYROUTER_HWKEY )
+                               {
+                                       detachSlave(dev->deviceid);
+                                       keyrouter.num_hwkey_devices++;
+                               }
+               }
+       }
+
+       XIFreeDeviceInfo(info);
+
+       return 1;
+}
+
+static void reattachSlave(int slave, int master)
+{
+       XIAttachSlaveInfo attach;
+
+       attach.type = XIAttachSlave;
+       attach.deviceid = slave;
+       attach.new_master = master;
+
+       XIChangeHierarchy(keyrouter.disp, (XIAnyHierarchyChangeInfo*)&attach, 1);
+}
+static void UngrabKeyDevices()
+{
+       int i, ndevices;
+       XIDeviceInfo *dev, *info = NULL;
+       XDevice* pDev = NULL;
+
+       info = XIQueryDevice(keyrouter.disp, XIAllDevices, &ndevices);
+
+       if( !info )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] There is no queried XI device.\n", __FUNCTION__);
+               return;
+       }
+
+       for( i = 0; i < ndevices ; i++ )
+       {
+               dev = &info[i];
+
+               if( XIFloatingSlave != dev->use )
+                       continue;
+
+               if( dev->num_classes > 1 )//only for Floated SlaveKeyboard
+                       continue;
+
+               pDev = XOpenDevice(keyrouter.disp, dev->deviceid);
+
+               if( !pDev )
+                       continue;
+
+               XUngrabDevice(keyrouter.disp, pDev, CurrentTime);
+
+               if( pDev )
+               {
+                       XCloseDevice(keyrouter.disp, pDev);
+                       pDev = NULL;
+               }
+
+               reattachSlave(dev->deviceid, 3);//reattach to Virtual Core Keyboard
+       }
+
+       XIFreeDeviceInfo(info);
+}
+
+static void PrintKeyDeliveryList()
+{
+       int index;
+
+       for( index=0 ; index < MAX_HARDKEYS ; index++ )
+       {
+               char *keyname;
+               int pid;
+               KeySym ks;
+
+               if( keyrouter.HardKeys[index].keycode == 0 )//empty
+                       continue;
+               ks = XkbKeycodeToKeysym(keyrouter.disp, index, 0, 0);
+
+               SECURE_SLOGD("\n");
+               keyname = XKeysymToString(ks);
+
+               if( !keyname )
+               {
+                       continue;
+               }
+
+               if( !strncmp(keyname, KEY_VOLUMEDOWN, LEN_KEY_VOLUMEDOWN) )
+               {
+                       SECURE_SLOGD("[ KEY_VOLUMEDOWN : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_VOLUMEUP, LEN_KEY_VOLUMEUP) )
+               {
+                       SECURE_SLOGD("[ KEY_VOLUMEUP : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_PAUSE, LEN_KEY_PAUSE) )
+               {
+                       SECURE_SLOGD("[ KEY_PAUSE : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_SEND, LEN_KEY_SEND) )
+               {
+                       SECURE_SLOGD("[ KEY_SEND : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_SELECT, LEN_KEY_SELECT) )
+               {
+                       SECURE_SLOGD("[ KEY_SELECT : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_END, LEN_KEY_END) )
+               {
+                       SECURE_SLOGD("[ KEY_END : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_POWER, LEN_KEY_POWER) )
+               {
+                       SECURE_SLOGD("[ KEY_POWER : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_CAMERA, LEN_KEY_CAMERA) )
+               {
+                       SECURE_SLOGD("[ KEY_CAMERA : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_CONFIG, LEN_KEY_CONFIG) )
+               {
+                       SECURE_SLOGD("[ KEY_CONFIG : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_MEDIA, LEN_KEY_MEDIA) )
+               {
+                       SECURE_SLOGD("[ KEY_MEDIA : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_PLAYCD, LEN_KEY_PLAYCD) )
+               {
+                       SECURE_SLOGD("[ KEY_PLAYCD : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_STOPCD, LEN_KEY_STOPCD) )
+               {
+                       SECURE_SLOGD("[ KEY_STOPCD : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_PAUSECD, LEN_KEY_PAUSECD) )
+               {
+                       SECURE_SLOGD("[ KEY_PAUSECD : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_NEXTSONG, LEN_KEY_NEXTSONG) )
+               {
+                       SECURE_SLOGD("[ KEY_NEXTSONG : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_PREVIOUSSONG, LEN_KEY_PREVIOUSSONG) )
+               {
+                       SECURE_SLOGD("[ KEY_PREVIOUSSONG : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_REWIND, LEN_KEY_REWIND) )
+               {
+                       SECURE_SLOGD("[ KEY_REWIND : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_FASTFORWARD, LEN_KEY_FASTFORWARD) )
+               {
+                       SECURE_SLOGD("[ KEY_FASTFORWARD : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_PLAYPAUSE, LEN_KEY_PLAYPAUSE) )
+               {
+                       SECURE_SLOGD("[ KEY_PLAYPAUSE : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_MUTE, LEN_KEY_MUTE) )
+               {
+                       SECURE_SLOGD("[ KEY_MUTE : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_HOMEPAGE, LEN_KEY_HOMEPAGE) )
+               {
+                       SECURE_SLOGD("[ KEY_HOMEPAGE : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_WEBPAGE, LEN_KEY_WEBPAGE) )
+               {
+                       SECURE_SLOGD("[ KEY_WEBPAGE : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_MAIL, LEN_KEY_MAIL) )
+               {
+                       SECURE_SLOGD("[ KEY_MAIL : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_SCREENSAVER, LEN_KEY_SCREENSAVER) )
+               {
+                       SECURE_SLOGD("[ KEY_SCREENSAVER : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_BRIGHTNESSUP, LEN_KEY_BRIGHTNESSUP) )
+               {
+                       SECURE_SLOGD("[ KEY_BRIGHTNESSUP : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_BRIGHTNESSDOWN, LEN_KEY_BRIGHTNESSDOWN) )
+               {
+                       SECURE_SLOGD("[ KEY_BRIGHTNESSDOWN : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_SOFTKBD, LEN_KEY_SOFTKBD) )
+               {
+                       SECURE_SLOGD("[ KEY_SOFTKBD : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_QUICKPANEL, LEN_KEY_QUICKPANEL) )
+               {
+                       SECURE_SLOGD("[ KEY_QUICKPANEL : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_TASKSWITCH, LEN_KEY_TASKSWITCH) )
+               {
+                       SECURE_SLOGD("[ KEY_TASKSWITCH : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_APPS, LEN_KEY_APPS) )
+               {
+                       SECURE_SLOGD("[ KEY_APPS : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_SEARCH, LEN_KEY_SEARCH) )
+               {
+                       SECURE_SLOGD("[ KEY_SEARCH : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_VOICE, LEN_KEY_VOICE) )
+               {
+                       SECURE_SLOGD("[ KEY_VOICE : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_LANGUAGE, LEN_KEY_LANGUAGE) )
+               {
+                       SECURE_SLOGD("[ KEY_LANGUAGE : %s : %d ]\n", keyname, index);
+               }
+               /*else if( !strncmp(keyname, KEY_CONNECT, LEN_KEY_CONNECT) )
+               {
+                       SECURE_SLOGD("[ KEY_CONNECT : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_GAMEPLAY, LEN_KEY_GAMEPLAY) )
+               {
+                       SECURE_SLOGD("[ KEY_GAMEPLAY : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_VOICEWAKEUP_LPSD, LEN_KEY_VOICEWAKEUP_LPSD) )
+               {
+                       SECURE_SLOGD("[ KEY_VOICEWAKEUP_LPSD : %s : %d ]\n", keyname, index);
+               }
+               else if( !strncmp(keyname, KEY_VOICEWAKEUP, LEN_KEY_VOICEWAKEUP) )
+               {
+                       SECURE_SLOGD("[ KEY_VOICEWAKEUP : %s : %d ]\n", keyname, index);
+               }*/
+               else
+               {
+                       SECURE_SLOGD("[ UNKNOWN : %d ]\n", keyrouter.HardKeys[index].keycode);
+               }
+
+               //Print EXCLUSIVE mode of grab
+               if( NULL != keyrouter.HardKeys[index].excl_ptr )
+               {
+                       ecore_x_netwm_pid_get((int)(keyrouter.HardKeys[index].excl_ptr->wid), &pid);
+                       SECURE_SLOGD("\e[32m== EXCLUSIVE : Window(0x%X) -> pid(%d)\e[0m\n", (int)(keyrouter.HardKeys[index].excl_ptr->wid), pid);
+               }
+               else
+               {
+                       SECURE_SLOGD("== EXCLUSIVE : None\n");
+               }
+
+               //Print OR_EXCLUSIVE mode of grab
+               if( NULL != keyrouter.HardKeys[index].or_excl_ptr )
+               {
+                       keylist_node* or_excl_ptr;
+                       or_excl_ptr = keyrouter.HardKeys[index].or_excl_ptr;
+                       SECURE_SLOGD("\e[32m== OR_EXCLUSIVE : ");
+
+                       do
+                       {
+                               ecore_x_netwm_pid_get((unsigned int)(or_excl_ptr->wid), &pid);
+                               SECURE_SLOGD("Window(0x%X) -> pid(%d)", (unsigned int)(or_excl_ptr->wid), pid);
+                               or_excl_ptr = or_excl_ptr->next;
+                       } while( or_excl_ptr );
+                       SECURE_SLOGD("None\e[0m\n");
+               }
+               else
+               {
+                       SECURE_SLOGD("== OR_EXCLUSIVE : None\n");
+               }
+
+               //Print TOP_POSITION mode of grab
+               if( NULL != keyrouter.HardKeys[index].top_ptr )
+               {
+                       keylist_node* top_ptr;
+                       top_ptr = keyrouter.HardKeys[index].top_ptr;
+                       SECURE_SLOGD("\e[32m== TOP_POSITION : ");
+
+                       do
+                       {
+                               ecore_x_netwm_pid_get((unsigned int)(top_ptr->wid), &pid);
+                               SECURE_SLOGD("Window(0x%X) -> pid(%d)", (unsigned int)(top_ptr->wid), pid);
+                               top_ptr = top_ptr->next;
+                       } while( top_ptr );
+                       SECURE_SLOGD("None\e[0m\n");
+               }
+               else
+               {
+                       SECURE_SLOGD("== TOP_POSITION : None\n");
+               }
+
+               //Print SHARED mode of grab
+               if( NULL != keyrouter.HardKeys[index].shared_ptr )
+               {
+                       keylist_node* shared_ptr;
+                       shared_ptr = keyrouter.HardKeys[index].shared_ptr;
+                       SECURE_SLOGD("\e[32m== SHARED : ");
+
+                       do
+                       {
+                               ecore_x_netwm_pid_get((unsigned int)(shared_ptr->wid), &pid);
+                               SECURE_SLOGD("Window(0x%X) -> pid(%d)", (unsigned int)(shared_ptr->wid), pid);
+                               shared_ptr = shared_ptr->next;
+                       } while( shared_ptr );
+                       SECURE_SLOGD("None\e[0m\n");
+               }
+               else
+               {
+                       SECURE_SLOGD("== SHARED : None\n");
+               }
+
+               if (ks >= 0x01000100 && ks <= 0x0110ffff)
+                       free(keyname);
+       }
+
+       return;
+}
+
+static int RemoveWindowDeliveryList(Window win, int isTopPositionMode, int UnSetExclusiveProperty)
+{
+
+       int index;
+       int mode_count = 0;
+
+       //Remove win from EXCLUSIVE, TOP_POSITION and SHARED  grab list !
+       //If isTopPosition is true, remove win only from TOP_POSITION grab list !
+       for( index=0 ; index < MAX_HARDKEYS ; index++ )
+       {
+               if( keyrouter.HardKeys[index].keycode == 0 )//empty
+                       continue;
+
+               if( isTopPositionMode )
+               {
+                       //Check & Delete TOP_POSITION mode of grab
+                       if( NULL != keyrouter.HardKeys[index].top_ptr )
+                       {
+                               int flags = 0;
+                               keylist_node* current;
+                               keylist_node* next_current;
+
+                               current = keyrouter.HardKeys[index].top_ptr;
+
+                               if( !current ) continue;
+
+                               next_current = current->next;
+
+                               do
+                               {
+                                       if( win == keyrouter.HardKeys[index].top_ptr->wid )
+                                       {
+                                               if( current->next )
+                                                       keyrouter.HardKeys[index].top_ptr = current->next;
+                                               else
+                                               {
+                                                       keyrouter.HardKeys[index].top_ptr = NULL;
+                                                       keyrouter.HardKeys[index].top_tail = NULL;
+                                                       mode_count += TOP_GRAB_MODE;
+                                               }
+
+                                               if( current )
+                                                       free(current);
+                                               flags = 1;
+                                               break;
+                                       }
+
+                                       if( NULL == next_current )
+                                       {
+                                               break;
+                                       }
+
+                                       if( win == next_current->wid )
+                                       {
+                                               if( next_current->next )
+                                                       current->next = next_current->next;
+                                               else
+                                               {
+                                                       current->next = NULL;
+                                                       keyrouter.HardKeys[index].top_tail = current;
+                                               }
+
+                                               if( next_current )
+                                                       free(next_current);
+                                               flags = 1;
+                                               break;
+                                       }
+
+                                       current = next_current;
+                                       next_current = next_current->next;
+
+                               } while( NULL != next_current );
+
+                               if( flags )
+                               {
+                                       continue;
+                               }
+                       }
+               }
+               else//isTopPositionMode == 0
+               {
+                       //Check & Delete EXCLUSIVE mode of grab
+                       if( NULL != keyrouter.HardKeys[index].excl_ptr )
+                       {
+                               if( win == keyrouter.HardKeys[index].excl_ptr->wid )
+                               {
+                                       if( UnSetExclusiveProperty )
+                                       {
+                                               UnSetExclusiveGrabInfoToRootWindow(keyrouter.HardKeys[index].keycode, EXCLUSIVE_GRAB);
+                                       }
+
+                                       if( keyrouter.HardKeys[index].excl_ptr )
+                                               free(keyrouter.HardKeys[index].excl_ptr);
+                                       keyrouter.HardKeys[index].excl_ptr = NULL;
+                                       mode_count += EXCL_GRAB_MODE;
+                                       continue;//need to check another keycode
+                               }
+                       }
+
+                       //Check & Delete OR_EXCLUSIVE mode of grab
+                       if( NULL != keyrouter.HardKeys[index].or_excl_ptr )
+                       {
+                               int flags = 0;
+                               keylist_node* current = NULL;
+                               keylist_node* next_current = NULL;
+
+                               current = keyrouter.HardKeys[index].or_excl_ptr;
+                               if (current)
+                               {
+                                       next_current = current->next;
+                                       do
+                                       {
+                                               if (win == keyrouter.HardKeys[index].or_excl_ptr->wid)
+                                               {
+                                                       if (current->next)
+                                                               keyrouter.HardKeys[index].or_excl_ptr = current->next;
+                                                       else
+                                                       {
+                                                               keyrouter.HardKeys[index].or_excl_ptr = NULL;
+                                                               mode_count += OR_EXCL_GRAB_MODE;
+                                                       }
+
+                                                       if (current)
+                                                       {
+                                                               free(current);
+                                                               current = NULL;
+                                                       }
+                                                       flags = 1;
+                                                       break;
+                                               }
+
+                                               if (NULL == next_current)
+                                               {
+                                                       break;
+                                               }
+
+                                               if (win == next_current->wid)
+                                               {
+                                                       if (next_current->next)
+                                                               current->next = next_current->next;
+                                                       else
+                                                               current->next = NULL;
+
+                                                       if (next_current)
+                                                       {
+                                                               free(next_current);
+                                                               next_current = NULL;
+                                                       }
+                                                       flags = 1;
+                                                       break;
+                                               }
+
+                                               current = next_current;
+                                               next_current = next_current->next;
+                                       } while (next_current);
+                               }
+                               if( NULL == keyrouter.HardKeys[index].or_excl_ptr )
+                                       UnSetExclusiveGrabInfoToRootWindow(keyrouter.HardKeys[index].keycode, OR_EXCLUSIVE_GRAB);
+
+                               if( flags )
+                               {
+                                       continue;
+                               }
+                       }
+
+                       //Check & Delete TOP_POSITION mode of grab
+                       if( NULL != keyrouter.HardKeys[index].top_ptr )
+                       {
+                               int flags = 0;
+                               keylist_node* current;
+                               keylist_node* next_current;
+
+                               current = keyrouter.HardKeys[index].top_ptr;
+
+                               if( !current )
+                                       goto null_top_ptr;
+
+                               next_current = current->next;
+
+                               do
+                               {
+                                       if( win == keyrouter.HardKeys[index].top_ptr->wid )
+                                       {
+                                               if( current->next )
+                                                       keyrouter.HardKeys[index].top_ptr = current->next;
+                                               else
+                                               {
+                                                       keyrouter.HardKeys[index].top_ptr = NULL;
+                                                       keyrouter.HardKeys[index].top_tail = NULL;
+                                                       mode_count += TOP_GRAB_MODE;
+                                               }
+
+                                               if( current )
+                                                       free(current);
+                                               flags = 1;
+                                               break;
+                                       }
+
+                                       if( NULL == next_current )
+                                       {
+                                               break;
+                                       }
+
+                                       if( win == next_current->wid )
+                                       {
+                                               if( next_current->next )
+                                                       current->next = next_current->next;
+                                               else
+                                               {
+                                                       current->next = NULL;
+                                                       keyrouter.HardKeys[index].top_tail = current;
+                                               }
+
+                                               if( next_current )
+                                                       free(next_current);
+                                               flags = 1;
+                                               break;
+                                       }
+
+                                       current = next_current;
+                                       next_current = next_current->next;
+
+                               } while( NULL != next_current );
+
+                               if( flags )
+                               {
+                                       continue;
+                               }
+                       }
+
+null_top_ptr:
+                       //Check & Delete SHARED mode of grab
+                       if( NULL != keyrouter.HardKeys[index].shared_ptr )
+                       {
+                               int flags = 0;
+                               keylist_node* current = NULL;
+                               keylist_node* next_current = NULL;
+
+                               current = keyrouter.HardKeys[index].shared_ptr;
+                                if (current)
+                                  {
+                                     next_current = current->next;
+                                     do
+                                       {
+                                          if (win == keyrouter.HardKeys[index].shared_ptr->wid)
+                                            {
+                                               if (current->next)
+                                                 keyrouter.HardKeys[index].shared_ptr = current->next;
+                                               else
+                                                 {
+                                                    keyrouter.HardKeys[index].shared_ptr = NULL;
+                                                    mode_count += SHARED_GRAB_MODE;
+                                                 }
+
+                                               if (current)
+                                                 {
+                                                    free(current);
+                                                    current = NULL;
+                                                 }
+                                               flags = 1;
+                                               break;
+                                            }
+
+                                          if (NULL == next_current)
+                                            {
+                                               break;
+                                            }
+
+                                          if (win == next_current->wid)
+                                            {
+                                               if (next_current->next)
+                                                 current->next = next_current->next;
+                                               else
+                                                 current->next = NULL;
+
+                                               if (next_current)
+                                                 {
+                                                    free(next_current);
+                                                    next_current = NULL;
+                                                 }
+                                               flags = 1;
+                                               break;
+                                            }
+
+                                          current = next_current;
+                                          next_current = next_current->next;
+
+                                       } while (next_current);
+                                  }
+
+                               if( flags )
+                               {
+                                       continue;
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static void UnSetExclusiveGrabInfoToRootWindow(int keycode, int grab_mode)
+{
+       int i;
+       int cnt = 0;
+       unsigned int *key_list = NULL;
+       int *new_key_list = NULL;
+
+       Atom ret_type;
+       int ret_format;
+       unsigned long nr_item;
+       unsigned long sz_remains_data;
+       Window ex_grabwin;
+
+       if( grab_mode == EXCLUSIVE_GRAB )
+       {
+       if( keyrouter.atomGrabExclWin == None )
+               keyrouter.atomGrabExclWin = XInternAtom(keyrouter.disp, STR_ATOM_GRAB_EXCL_WIN, False);
+               ex_grabwin = keyrouter.atomGrabExclWin;
+       }
+       else if( grab_mode == OR_EXCLUSIVE_GRAB )
+       {
+               if( keyrouter.atomGrabORExclWin == None )
+                       keyrouter.atomGrabORExclWin = XInternAtom(keyrouter.disp, STR_ATOM_GRAB_OR_EXCL_WIN, False);
+               ex_grabwin = keyrouter.atomGrabORExclWin;
+       }
+       else
+               return;
+
+       if (XGetWindowProperty(keyrouter.disp, keyrouter.rootWin,
+               ex_grabwin, 0, 0x7fffffff, False, XA_CARDINAL,
+               &ret_type, &ret_format, &nr_item, &sz_remains_data, (unsigned char **)&key_list) != Success)
+       {
+               nr_item = 0;
+       }
+
+       if (nr_item == 0)
+       {
+               goto out;
+       }
+
+       for( i=0 ; i < nr_item ; i++ )
+       {
+               if( key_list[i] == keycode )//&& grab_mode == EXCLUSIVE_GRAB )
+               {
+                       continue;
+               }
+               cnt++;
+       }
+
+       if( 0 < cnt )
+       {
+               new_key_list = malloc(sizeof(int)*cnt);
+               cnt = 0;
+       }
+       else
+               new_key_list = NULL;
+
+       if( !new_key_list )
+       {
+               XDeleteProperty(keyrouter.disp, keyrouter.rootWin, ex_grabwin);
+               XSync(keyrouter.disp, False);
+               goto out;
+       }
+
+       for( i=0 ; i < nr_item ; i++ )
+       {
+               if( key_list[i] == keycode )//&& grab_mode == EXCLUSIVE_GRAB )
+               {
+                       continue;
+               }
+               else
+                       new_key_list[cnt++] = key_list[i];
+       }
+
+       XChangeProperty(keyrouter.disp, keyrouter.rootWin, ex_grabwin, XA_CARDINAL, 32,
+                       PropModeReplace, (unsigned char *)new_key_list, cnt);
+       XSync(keyrouter.disp, False);
+
+out:
+       if(new_key_list)
+               free(new_key_list);
+       if( key_list )
+               XFree(key_list);
+       return;
+}
+
+static int AddWindowToDeliveryList(Window win, int keycode, const int grab_mode, const int IsOnTop)
+{
+       int ret = 0;
+       int index = keycode;
+
+       if( index >= MAX_HARDKEYS )
+       {
+               SECURE_SLOGD("[keyrouter][%s] Error ! index of keyrouter.HardKeys must be smaller than %d (index=%d)!)\n", __FUNCTION__, MAX_HARDKEYS, index);
+               ret = -1;
+               goto out;
+       }
+
+       keylist_node* ptr = NULL;
+       keyrouter.HardKeys[index].keycode = keycode;
+       switch( grab_mode )
+       {
+               case EXCLUSIVE_GRAB:
+                       if( NULL != keyrouter.HardKeys[index].excl_ptr )
+                       {
+                               SECURE_SLOGD("[keyrouter][%s] keyrouter.HardKeys[%d].Keycode(%d) was EXCLUSIVELY grabbed already by window(0x%x) !\n", __FUNCTION__, index, keycode, (int)(keyrouter.HardKeys[index].excl_ptr->wid));
+                               ret = -1;
+                               goto out;
+                       }
+
+                       ptr = (keylist_node*)malloc(sizeof(keylist_node));
+                       if( !ptr )
+                       {
+                               SECURE_SLOGD("[keyrouter][%s] Failed to allocate memory for adding excl_ptr!\n", __FUNCTION__);
+                               ret = -1;
+                               goto out;
+                       }
+
+                       ptr->wid = win;
+                       ptr->next = NULL;
+                       keyrouter.HardKeys[index].excl_ptr = ptr;
+                       break;
+
+               case OR_EXCLUSIVE_GRAB:
+                       ptr = (keylist_node*)malloc(sizeof(keylist_node));
+                       if( !ptr )
+                       {
+                               SLOG(LOG_WARN, "KEYROUTER", "Failed to allocate memory for adding or_excl_ptr!\n");
+                               ret = -1;
+                               goto out;
+                       }
+
+                       ptr->wid = win;
+                       if( NULL != keyrouter.HardKeys[index].or_excl_ptr )
+                       {
+                               ptr->next = keyrouter.HardKeys[index].or_excl_ptr;
+                               keyrouter.HardKeys[index].or_excl_ptr = ptr;
+                       }
+                       else
+                       {
+                               ptr->next=NULL;
+                               keyrouter.HardKeys[index].or_excl_ptr=ptr;
+                       }
+                       break;
+
+               case TOP_POSITION_GRAB:
+                       ptr = (keylist_node*)malloc(sizeof(keylist_node));
+                       if( !ptr )
+                       {
+                               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to allocate memory for adding top_ptr!\n", __FUNCTION__);
+                               ret = -1;
+                               goto out;
+                       }
+
+                       ptr->wid = win;
+                       ptr->next = NULL;
+
+                       if( NULL == keyrouter.HardKeys[index].top_ptr )//µ¥ÀÌÅÍ ¾øÀ½
+                       {
+                               keyrouter.HardKeys[index].top_tail = keyrouter.HardKeys[index].top_ptr = ptr;
+                               break;
+                       }
+
+                       if( IsOnTop )
+                       {
+                               ptr->next = keyrouter.HardKeys[index].top_ptr;
+                               keyrouter.HardKeys[index].top_ptr = ptr;
+                       }
+                       else
+                       {
+                               keyrouter.HardKeys[index].top_tail->next = ptr;
+                               keyrouter.HardKeys[index].top_tail = ptr;
+                       }
+                       break;
+
+               case SHARED_GRAB:
+                       ptr = (keylist_node*)malloc(sizeof(keylist_node));
+                       if( !ptr )
+                       {
+                               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to allocate memory for adding shared_ptr!\n", __FUNCTION__);
+                               ret = -1;
+                               goto out;
+                       }
+
+                       ptr->wid = win;
+                       if( NULL != keyrouter.HardKeys[index].shared_ptr )//µ¥ÀÌÅÍ Á¸Àç
+                       {
+                               ptr->next = keyrouter.HardKeys[index].shared_ptr;
+                               keyrouter.HardKeys[index].shared_ptr = ptr;
+                       }
+                       else//µ¥ÀÌÅÍ ¾øÀ½
+                       {
+                               ptr->next = NULL;
+                               keyrouter.HardKeys[index].shared_ptr = ptr;
+                       }
+                       break;
+
+               default:
+                       SECURE_SLOGD("[keyrouter][%s] Unknown mode of grab ! (grab_mode=0x%X)\n", __FUNCTION__, grab_mode);
+                       ret = -1;
+                       break;
+       }
+
+out:
+
+       return ret;
+}
+
+static int AddWindowToPressedList(Window win, int keycode, const int grab_mode)
+{
+       keylist_node* ptr = NULL;
+       ptr = (keylist_node*)malloc(sizeof(keylist_node));
+       int ret = 1;
+       if(!ptr)
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter] Failed to allocate memory for adding pressed_win_ptr!\n");
+               ret = 0;
+               goto out;
+       }
+       ptr->wid = win;
+       keyrouter.HardKeys[keycode].lastmode = grab_mode;
+       if(NULL != keyrouter.HardKeys[keycode].pressed_win_ptr)
+       {
+               ptr->next = keyrouter.HardKeys[keycode].pressed_win_ptr;
+               keyrouter.HardKeys[keycode].pressed_win_ptr = ptr;
+       }
+       else
+       {
+               ptr->next = NULL;
+               keyrouter.HardKeys[keycode].pressed_win_ptr = ptr;
+       }
+out:
+       return ret;
+}
+
+
+static int AdjustTopPositionDeliveryList(Window win, int IsOnTop)
+{
+       Atom ret_type;
+       int ret_format;
+       unsigned long nr_item = 0;
+       unsigned long sz_remains_data;
+       unsigned int *key_list = NULL;
+
+       int i, result;
+       int grab_mode, keycode;
+
+       if (keyrouter.atomGrabKey == None) {
+               keyrouter.atomGrabKey = XInternAtom(keyrouter.disp, STR_ATOM_GRAB_KEY, False);
+       }
+
+       if ( Success != (result = XGetWindowProperty(keyrouter.disp, win, keyrouter.atomGrabKey, 0, 0x7fffffff, False, XA_CARDINAL,
+                               &ret_type, &ret_format, &nr_item,
+                               &sz_remains_data,(unsigned char **)&key_list) ) )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "[keyrouter][%s] Failed to get window property from %s ! (result = %d)\n", __FUNCTION__, STR_ATOM_GRAB_KEY, result);
+               RemoveWindowDeliveryList(win, 1, 0);
+               goto out;
+       }
+
+       if( 0 == nr_item )
+       {
+               RemoveWindowDeliveryList(win, 1, 0);
+               goto out;
+       }
+
+       RemoveWindowDeliveryList(win, 1, 0);
+
+       for( i=0 ; i < nr_item ; i++ )
+       {
+               grab_mode = key_list[i] & GRAB_MODE_MASK;
+
+               if( TOP_POSITION_GRAB != grab_mode )
+                       continue;
+
+               keycode = key_list[i] & (~GRAB_MODE_MASK);
+               _e_keyrouter_update_key_delivery_list(win, keycode, TOP_POSITION_GRAB, IsOnTop);
+       }
+
+out:
+       if( key_list )
+                       XFree(key_list);
+       return 0;
+}
+
+static int IsGrabbed(unsigned int keycode)
+{
+       int index = keycode;
+
+       if( keyrouter.HardKeys[index].keycode == 0 )//empty
+       {
+               goto out;
+       }
+
+       if( keyrouter.HardKeys[index].keycode != keycode )
+       {
+               SECURE_SLOGD("[keyrouter][%s] Error ! (keyrouter.HardKeys[%d].keycode must be equal to keycode(%d) !\n", __FUNCTION__, index, keycode);
+               goto out;
+       }
+
+       if( NULL != keyrouter.HardKeys[index].excl_ptr )
+       {
+               index |= EXCLUSIVE_GRAB;
+       }
+       else if( NULL != keyrouter.HardKeys[index].or_excl_ptr )
+       {
+               index |= OR_EXCLUSIVE_GRAB;
+       }
+       else if( NULL != keyrouter.HardKeys[index].top_ptr )
+       {
+               index |= TOP_POSITION_GRAB;
+       }
+       else if( NULL != keyrouter.HardKeys[index].shared_ptr )
+       {
+               index |= SHARED_GRAB;
+       }
+       else
+       {
+               index = -1;
+       }
+       return index;
+
+out:
+       return -1;
+}
+
+static E_Client *_e_keyrouter_find_client_by_window(Window win)
+{
+       const Eina_List *l, *ll;
+       E_Comp *c;
+       E_Client *ec = NULL;
+
+       EINA_LIST_FOREACH(e_comp_list(), l, c)
+               EINA_LIST_FOREACH(c->clients, ll, ec)
+               {
+                       if (ec)
+                       {
+                               if (e_client_util_win_get(ec) == win)
+                                       break;
+                       }
+               }
+       return ec;
+}
+
+static int IsWindowTopVisibleWithoutInputFocus(keylist_node* top_ptr, Window focus, Window * dest_window)
+{
+       Window root_win, parent_win;
+       unsigned int num_children;
+       Window *child_list = NULL;
+       keylist_node * ptr = NULL;
+
+       int i;
+       XWindowAttributes win_attributes;
+       E_Client *ec;
+
+       if( !XQueryTree(keyrouter.disp, keyrouter.rootWin, &root_win, &parent_win, &child_list, &num_children) )
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "\e[32m[keyrouter][%s] Failed to query window tree !\e[0m\n", __FUNCTION__);
+               return 0;
+       }
+
+       /* Make the wininfo list */
+       for (i = (int)num_children - 1; i >= 0; i--)
+       {
+               // 1. check map status of window
+               /* figure out whether the window is mapped or not */
+               XGetWindowAttributes(keyrouter.disp, child_list[i], &win_attributes);
+
+               // 2. return if map status is 0 or border's visible is 0
+               if( win_attributes.map_state == 0 )
+                       continue;
+
+               // 3. check window is border or not
+               // Event though Border is delete status, bd->client.shell_win and bd->win is still existed in server side.
+               // So focus window is bd->client.shell_win. In this case we will deliver key-event to the TOP_POSITION grab window. That is bug.
+               ec = _e_keyrouter_find_client_by_window(child_list[i]);
+
+               if ( ec )
+               {
+                   if (!ec->visible)
+                   {
+                       if( e_client_util_win_get(ec) == focus )
+                       {
+                           XFree(child_list);
+                           return 0;
+                       }
+                       else
+                           continue;
+                   }
+
+                   if( (ec->x >= ec->zone->w) || (ec->y >= ec->zone->h) )
+                       continue;
+
+                   if( ((ec->x + ec->w) <= 0) || ((ec->y + ec->h) <= 0) )
+                       continue;
+               }
+
+               for( ptr=top_ptr ; (NULL != ptr) ; ptr=ptr->next )
+               {
+                       if( ec )//child_list[i] is border
+                       {//if the window is client window, check hint
+                               if( e_client_util_win_get(ec) == ptr->wid )
+                               {
+                                       *dest_window = ptr->wid;
+                                       XFree(child_list);
+                                       return 1;
+                               }
+                       }
+                       else//child_list[i] is override-redirected window
+                       {//if the window is not client window, it will be a border window or a override-redirected window then check the equality of the windows
+                               if( child_list[i] == ptr->wid )
+                               {
+                                       *dest_window = ptr->wid;
+                                       XFree(child_list);
+                                       return 1;
+                               }
+                       }
+               }
+
+               if( ec )
+               {
+                      if( e_client_util_win_get(ec) == focus)
+                      {
+                           XFree(child_list);
+                           return 0;
+                       }
+               }
+               else if( child_list[i] == focus )
+               {
+                       XFree(child_list);
+                       return 0;
+               }
+       }
+       XFree(child_list);
+       return 0;
+}
+
+static void DeliverDeviceKeyEvents(XEvent *xev)
+{
+       int index;
+       int revert_to_return;
+       Window focus_window;
+       keylist_node* ptr = NULL;
+       Window dest_window = None;
+
+       index = IsGrabbed(xev->xkey.keycode);
+
+       if( index < 0 && keyrouter.HardKeys[xev->xkey.keycode].bind )
+       {
+               printf("[keyrouter][DeliverDeviceKeyEvents] key(keycode=%d, name=%s) was bound !\n",
+                       xev->xkey.keycode, keyrouter.HardKeys[xev->xkey.keycode].bind->key);
+               SECURE_SLOGD("[keyrouter][DeliverDeviceKeyEvents] key(keycode=%d, name=%s) was bound !\n",
+                       xev->xkey.keycode, keyrouter.HardKeys[xev->xkey.keycode].bind->key);
+               _e_keyrouter_do_bound_key_action(xev);
+               return;
+       }
+
+       XGetInputFocus(keyrouter.disp, &focus_window, &revert_to_return);
+
+       printf("keycode:%d, %s\n", xev->xkey.keycode, (index < 0)?"Not Grabbed":"Grabbed");
+       // Is Grabbed ?
+       if( index < 0 )//Code for non-grabbed key
+       {
+               //Deliver to focus window
+               xev->xkey.window = focus_window;
+               if(xev->type == KeyPress)
+               {
+                       //XTestFakeKeyEvent(xev->xany.display, xev->xkey.keycode, (xev->type==KeyPress) ? True : False, CurrentTime);
+                       AddWindowToPressedList(xev->xkey.window, xev->xkey.keycode, NONE_GRAB_MODE);
+                       XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+                       printf("\e[32m[keyrouter][%s] Non-grabbed key! Deliver %s (keycode:%d) to focus window (0x%x) !\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (int)focus_window);
+                       SECURE_SLOGD("\e[32m[keyrouter][%s] Non-grabbed key! Deliver %s (keycode:%d) to focus window (0x%x) !\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (int)focus_window);
+               }
+               else
+               {
+                       keylist_node *tmp_ptr;
+                       for( ptr=keyrouter.HardKeys[xev->xkey.keycode].pressed_win_ptr; (NULL != ptr) ; )
+                       {
+                               xev->xkey.window = ptr->wid;
+                               printf("\e[32m[keyrouter][%s] Deliver KeyRelease (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, xev->xkey.keycode, (int)xev->xkey.window);
+                               SECURE_SLOGD("\e[32m[keyrouter][%s] Deliver KeyRelease (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, xev->xkey.keycode, (int)xev->xkey.window);
+                               XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+                               tmp_ptr = ptr;
+                               ptr=ptr->next ;
+                               free(tmp_ptr);
+                       }
+                       keyrouter.HardKeys[xev->xkey.keycode].pressed_win_ptr = NULL;
+               }
+               printf("NOT GRABBED: (keycode:%d)\n", xev->xkey.keycode);
+               return;
+       }
+
+       int grab_mode = index & GRAB_MODE_MASK;
+       index &= ~GRAB_MODE_MASK;
+
+       if (xev->type == KeyPress)
+       {
+               printf("GRABBED - KeyPress\n");
+               switch( grab_mode )
+               {
+                       case EXCLUSIVE_GRAB:
+                               // Is Grab Mode equal to EXCLUSIVE ?
+                               xev->xkey.window = keyrouter.HardKeys[index].excl_ptr->wid;
+                               AddWindowToPressedList(xev->xkey.window, xev->xkey.keycode, EXCLUSIVE_GRAB);
+                               XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+                               printf("\e[32m[keyrouter][%s] EXCLUSIVE mode of grab ! Deliver %s (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (int)xev->xkey.window);
+                               SECURE_SLOGD("\e[32m[keyrouter][%s] EXCLUSIVE mode of grab ! Deliver %s (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (int)xev->xkey.window);
+                               break;
+
+                       case OR_EXCLUSIVE_GRAB:
+                               // Is Grab Mode equal to OR_EXCLUSIVE ?
+                               xev->xkey.window = keyrouter.HardKeys[index].or_excl_ptr->wid;
+                               AddWindowToPressedList(xev->xkey.window, xev->xkey.keycode, OR_EXCLUSIVE_GRAB);
+                               XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+                               printf("\e[32m[keyrouter][%s] OR_EXCLUSIVE mode of grab ! Deliver %s (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (int)xev->xkey.window);
+                               SECURE_SLOGD("\e[32m[keyrouter][%s] OR_EXCLUSIVE mode of grab ! Deliver %s (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (int)xev->xkey.window);
+                               break;
+
+                       case TOP_POSITION_GRAB:
+                               if( focus_window != keyrouter.HardKeys[index].top_ptr->wid )
+                               {
+                                      if( focus_window == 0 )
+                                      {
+                                       printf("\e[32m[keyrouter][%s] Focus_Window is NULL. Try it agin.  focus_window=(0x%x) !\e[0m\n", __FUNCTION__, focus_window);     
+                                          SECURE_SLOGD("\e[32m[keyrouter][%s] Focus_Window is NULL. Try it agin.  focus_window=(0x%x) !\e[0m\n", __FUNCTION__, focus_window);
+                                          XGetInputFocus(keyrouter.disp, &focus_window, &revert_to_return);
+                                      }
+
+                                       if( keyrouter.isWindowStackChanged || (keyrouter.prev_sent_keycode != xev->xkey.keycode) )
+                                               keyrouter.resTopVisibleCheck = IsWindowTopVisibleWithoutInputFocus(keyrouter.HardKeys[index].top_ptr, focus_window, &dest_window);
+
+                                       keyrouter.prev_sent_keycode = xev->xkey.keycode;
+
+                                       if( !keyrouter.resTopVisibleCheck )
+                                               goto shared_delivery;
+
+                                       if( keyrouter.isWindowStackChanged )
+                                               keyrouter.isWindowStackChanged = 0;
+                               }
+
+                               // Is Grab Mode equal to TOP_POSITION ?
+                               if( keyrouter.resTopVisibleCheck == 1 && dest_window != None)
+                                       xev->xkey.window = dest_window;
+                               else
+                                       xev->xkey.window = keyrouter.HardKeys[index].top_ptr->wid;
+                               AddWindowToPressedList(xev->xkey.window, xev->xkey.keycode, TOP_POSITION_GRAB);
+                               XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+                               printf("\e[32m[keyrouter][%s] TOP_POSITION mode of grab ! Deliver %s (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (int)xev->xkey.window);
+                               SECURE_SLOGD("\e[32m[keyrouter][%s] TOP_POSITION mode of grab ! Deliver %s (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (int)xev->xkey.window);
+                               break;
+
+                       case SHARED_GRAB:
+       shared_delivery:
+                               //Deliver to focus_window first
+                               xev->xkey.window = focus_window;
+                               //XTestFakeKeyEvent(xev->xany.display, xev->xkey.keycode, (xev->type==KeyPress) ? True : False, CurrentTime);
+                               AddWindowToPressedList(xev->xkey.window, xev->xkey.keycode, SHARED_GRAB);
+                               XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+                               printf("\e[32m[keyrouter][%s] Deliver %s (keycode:%d) to focus window (0x%x)!\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (unsigned int)xev->xkey.window);
+                               SECURE_SLOGD("\e[32m[keyrouter][%s] Deliver %s (keycode:%d) to focus window (0x%x)!\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (unsigned int)xev->xkey.window);
+
+                               //Deliver to shared grabbed window(s)
+                               for( ptr=keyrouter.HardKeys[index].shared_ptr ; (NULL != ptr) ; ptr=ptr->next )
+                               {
+                                       if( ptr->wid == focus_window )
+                                               continue;
+                                       xev->xkey.window = ptr->wid;
+                                       AddWindowToPressedList(xev->xkey.window, xev->xkey.keycode, SHARED_GRAB);
+                                       XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+                                       printf("\e[32m[keyrouter][%s] SHARED mode of grab ! Deliver %s (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (int)xev->xkey.window);
+                                       SECURE_SLOGD("\e[32m[keyrouter][%s] SHARED mode of grab ! Deliver %s (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, (xev->type == KeyPress) ? "KeyPress" : "KeyRelease", xev->xkey.keycode, (int)xev->xkey.window);
+                               }
+                               break;
+
+                       default:
+                               printf("\e[32m[keyrouter][%s] Unknown mode of grab (mode = %d, index = %d, keycode = %d)\e[0m\n", __FUNCTION__, grab_mode, index, xev->xkey.keycode);
+                               SECURE_SLOGD("\e[32m[keyrouter][%s] Unknown mode of grab (mode = %d, index = %d, keycode = %d)\e[0m\n", __FUNCTION__, grab_mode, index, xev->xkey.keycode);
+                               break;
+               }
+       }
+       else
+       {
+               printf("GRABBED - KeyRelease\n");
+               keylist_node *tmp_ptr;
+               for( ptr=keyrouter.HardKeys[index].pressed_win_ptr; (NULL != ptr) ; )
+               {
+                       xev->xkey.window = ptr->wid;
+                       printf("\e[32m[keyrouter][%s] Deliver KeyRelease (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, xev->xkey.keycode, (int)xev->xkey.window);
+                       SECURE_SLOGD("\e[32m[keyrouter][%s] Deliver KeyRelease (keycode:%d) to window (0x%x) !\e[0m\n", __FUNCTION__, xev->xkey.keycode, (int)xev->xkey.window);
+                       XSendEvent(keyrouter.disp, xev->xkey.window, False, KeyPressMask | KeyReleaseMask, xev);
+                       tmp_ptr = ptr;
+                       ptr=ptr->next ;
+                       free(tmp_ptr);
+               }
+               keyrouter.HardKeys[index].pressed_win_ptr = NULL;
+       }
+}
+
+static void _e_keyrouter_do_hardkey_emulation(const char *label, unsigned int key_event, unsigned int on_release, int keycode, int cancel)
+{
+       XEvent xev;
+
+       if( !label )
+               goto normal_hardkey_handler;
+       else
+               goto out;
+
+normal_hardkey_handler:
+       memset(&xev, 0, sizeof(XEvent));
+       xev.xkey.display = keyrouter.disp;
+       xev.xkey.root = keyrouter.rootWin;
+       xev.xkey.keycode = keycode;
+       xev.xkey.time = CurrentTime;
+       xev.xkey.type = key_event;
+
+       if( cancel )
+       {
+               _e_keyrouter_cancel_key(&xev, keycode);
+               SECURE_SLOGD("[keyrouter][do_hardkey_emulation] HWKeyEmulation Done !\n");
+               SECURE_SLOGD("...( Cancel KeyPress + KeyRelease(keycode:%d) + Cancel KeyRelease )\n", xev.xkey.keycode);
+       }
+       else
+       {
+               DeliverDeviceKeyEvents(&xev);
+               SECURE_SLOGD("[keyrouter][do_hardkey_emulation] HWKeyEmulation Done !\n");
+               SECURE_SLOGD("...( %s(keycode=%d )\n", (xev.xkey.type==KeyPress) ? "KeyPress" : "KeyRelease", xev.xkey.keycode);
+       }
+
+       return;
+
+out:
+       return;
+}
+
+static void Device_Status(unsigned int val)
+{
+       SLOG(LOG_DEBUG, "KEYROUTER", "\n[keyrouter] - Device Status = Start =====================\n");
+
+       if( keyrouter.device_list )
+       {
+               Eina_List* l;
+               E_Keyrouter_Device_Info *data;
+
+               EINA_LIST_FOREACH(keyrouter.device_list, l, data)
+               {
+                       if( data )
+                       {
+                               SLOG(LOG_DEBUG, "KEYROUTER", "Device id : %d Name : %s\n", data->id, data->name);
+                               switch( data->type )
+                               {
+                                       case E_KEYROUTER_HWKEY:
+                                               SLOG(LOG_DEBUG, "KEYROUTER", "¦¦Device type : H/W Key Device\n");
+                                               break;
+
+                                       case E_KEYROUTER_HOTPLUGGED:
+                                               SLOG(LOG_DEBUG, "KEYROUTER", "¦¦Device type : Hotplugged Key Device\n");
+                                               break;
+
+                                       case E_KEYROUTER_KEYBOARD:
+                                               SLOG(LOG_DEBUG, "KEYROUTER", "¦¦Device type : Hotplugged Keyboard Device\n");
+                                               break;
+
+                                       default:
+                                               SLOG(LOG_DEBUG, "KEYROUTER", "¦¦Device type : Unknown\n");
+                               }
+                       }
+               }
+       }
+       else
+       {
+               SLOG(LOG_DEBUG, "KEYROUTER", "No input devices...\n");
+       }
+
+       SLOG(LOG_DEBUG, "KEYROUTER", "\n[keyrouter] - Device Status = End =====================\n");
+}
+
+static void Keygrab_Status(unsigned int val)
+{
+       SECURE_SLOGD("\n[keyrouter] - Grab Status = Start =====================\n");
+       PrintKeyDeliveryList();
+       SECURE_SLOGD("\n[keyrouter] - Grab Status = End =====================\n");
+}
+
+static void InitModKeys()
+{
+       int i = 0;
+
+       if(!keyrouter.modkey)
+               return;
+
+       keyrouter.modkey[i].keys[0].keysym = XStringToKeysym(KEY_POWER);
+       keyrouter.modkey[i].keys[0].keycode = XKeysymToKeycode(keyrouter.disp, keyrouter.modkey[i].keys[0].keysym);
+       keyrouter.modkey[i].keys[1].keysym = XStringToKeysym(KEY_HOME);
+       keyrouter.modkey[i].keys[1].keycode = XKeysymToKeycode(keyrouter.disp, keyrouter.modkey[i].keys[1].keysym);
+       keyrouter.modkey[i].press_only = EINA_TRUE;
+
+       keyrouter.cancel_key.keysym = XStringToKeysym(KEY_CANCEL);
+       keyrouter.cancel_key.keycode = XKeysymToKeycode(keyrouter.disp, keyrouter.cancel_key.keysym);
+
+       SECURE_SLOGD("[keyrouter][%s][%d] Modifier Key=%s (keycode:%d)\n", __FUNCTION__, i, KEY_POWER, keyrouter.modkey[i].keys[0].keycode);
+       SECURE_SLOGD("[keyrouter][%s][%d] Composited Key=%s (keycode:%d)\n", __FUNCTION__, i, KEY_HOME, keyrouter.modkey[i].keys[1].keycode);
+       SECURE_SLOGD("[keyrouter][%s][%d] Cancel Key=%s (keycode:%d)\n", __FUNCTION__, i, KEY_CANCEL, keyrouter.cancel_key.keycode);
+
+/*
+       i++;
+       keyrouter.modkey[i].keys[0].keysym = XStringToKeysym(KEY_VOLUMEUP);
+       keyrouter.modkey[i].keys[0].keycode = XKeysymToKeycode(keyrouter.disp, keyrouter.modkey[i].keys[0].keysym);
+       keyrouter.modkey[i].keys[1].keysym = XStringToKeysym(KEY_VOLUMEDOWN);
+       keyrouter.modkey[i].keys[1].keycode = XKeysymToKeycode(keyrouter.disp, keyrouter.modkey[i].keys[1].keysym);
+       keyrouter.modkey[i].press_only = EINA_FALSE;
+       SECURE_SLOGD("[keyrouter][%s][%d] Modifier Key=%s (keycode:%d)\n", __FUNCTION__, i, KEY_VOLUMEUP, keyrouter.modkey[i].keys[0].keycode);
+       SECURE_SLOGD("[keyrouter][%s][%d] Composited Key=%s (keycode:%d)\n", __FUNCTION__, i, KEY_VOLUMEDOWN, keyrouter.modkey[i].keys[1].keycode);
+       SECURE_SLOGD("[keyrouter][%s][%d] Cancel Key=%s (keycode:%d)\n", __FUNCTION__, i, KEY_CANCEL, keyrouter.cancel_key.keycode);
+*/
+}
+
+static void ResetModKeyInfo()
+{
+       int i;
+
+       for(i=0 ; i < NUM_KEY_COMPOSITION_ACTIONS ; i++)
+       {
+               keyrouter.modkey[i].set = keyrouter.modkey[i].composited = keyrouter.modkey[i].time = keyrouter.modkey[i].idx_mod = keyrouter.modkey[i].idx_comp = 0;
+       }
+
+       keyrouter.modkey_set = 0;
+       SECURE_SLOGD("[keyrouter][%s][%d] modkey_set=%d\n", __FUNCTION__, i, keyrouter.modkey_set);
+}
+
+static int IsModKey(XEvent *ev, int index)
+{
+       int i, j = index;
+
+       for( i = 0 ; i < NUM_COMPOSITION_KEY ; i++ )
+               if( ev->xkey.keycode == keyrouter.modkey[j].keys[i].keycode )
+                       return (i+1);
+
+       return 0;
+}
+
+static int IsCompKey(XEvent *ev, int index)
+{
+       int i = index;
+
+       if( ev->xkey.keycode == keyrouter.modkey[i].keys[keyrouter.modkey[i].idx_mod%NUM_COMPOSITION_KEY].keycode )
+               return 4;
+
+       return 0;
+}
+
+static int IsKeyComposited(XEvent *ev, int index)
+{
+       int i = index;
+
+       if( (ev->xkey.keycode == keyrouter.modkey[i].keys[keyrouter.modkey[i].idx_mod%NUM_COMPOSITION_KEY].keycode)
+               && (ev->xkey.time <= (keyrouter.modkey[i].time + KEY_COMPOSITION_TIME)) )
+               return 3;
+
+       return 0;
+}
+
+static void DoKeyCompositionAction(int index, int press)
+{
+       XEvent xev;
+       Atom xkey_composition_atom = None;
+
+       int i = index;
+
+       xkey_composition_atom = XInternAtom (keyrouter.disp, STR_ATOM_XKEY_COMPOSITION, False);
+
+       xev.xclient.window = keyrouter.rootWin;
+       xev.xclient.type = ClientMessage;
+       xev.xclient.message_type = xkey_composition_atom;
+       xev.xclient.format = 32;
+       xev.xclient.data.l[0] = keyrouter.modkey[i].keys[0].keycode;
+       xev.xclient.data.l[1] = keyrouter.modkey[i].keys[1].keycode;
+       xev.xclient.data.l[2] = press;
+       xev.xclient.data.l[3] = 0;
+       xev.xclient.data.l[4] = 0;
+
+       XSendEvent(keyrouter.disp, keyrouter.rootWin, False, StructureNotifyMask | SubstructureNotifyMask, &xev);
+
+       xev.xclient.window = keyrouter.noti_window;
+       xev.xclient.type = ClientMessage;
+       xev.xclient.message_type = xkey_composition_atom;
+       xev.xclient.format = 32;
+       xev.xclient.data.l[0] = keyrouter.modkey[i].keys[0].keycode;
+       xev.xclient.data.l[1] = keyrouter.modkey[i].keys[1].keycode;
+       xev.xclient.data.l[2] = press;
+       xev.xclient.data.l[3] = 0;
+       xev.xclient.data.l[4] = 0;
+
+       XSendEvent(keyrouter.disp, keyrouter.noti_window, False, StructureNotifyMask | SubstructureNotifyMask, &xev);
+
+       XSync(keyrouter.disp, False);
+
+       SECURE_SLOGD("\n[keyrouter][%s][%d] Do Key Composition Action : ClientMessage to RootWindow(0x%x)!: %s\n", __FUNCTION__, i, keyrouter.rootWin, press ? "Press" : "Release");
+       SECURE_SLOGD("\n[keyrouter][%s][%d] Do Key Composition Action : ClientMessage to Keyrouter NotiWindow (0x%x)!: %s\n", __FUNCTION__, i, keyrouter.noti_window, press ? "Press" : "Release");
+}
diff --git a/src/e_mod_main.h b/src/e_mod_main.h
new file mode 100644 (file)
index 0000000..cb7c989
--- /dev/null
@@ -0,0 +1,339 @@
+#ifndef E_MOD_MAIN_H
+#define E_MOD_MAIN_H
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XInput.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/extensions/XI2.h>
+#include <X11/extensions/XIproto.h>
+#include <X11/extensions/XTest.h>
+#include <X11/extensions/Xrandr.h>
+#include <utilX.h>
+
+/*** 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);
+
+//maximum number of hardkeys
+#define MIN_KEYCODE            8
+#define MAX_HARDKEYS   255
+
+//grab modes
+#define NONE_GRAB_MODE 0
+#define OR_EXCL_GRAB_MODE      1
+#define EXCL_GRAB_MODE         2
+#define TOP_GRAB_MODE          3
+#define SHARED_GRAB_MODE       4
+#define ALL_GRAB_MODE          10
+
+#define STR_ATOM_DEVICE_STATUS         "_DEVICE_STATUS"
+#define STR_ATOM_GRAB_STATUS                   "_GRAB_STATUS"
+#define PROP_HWKEY_EMULATION                   "_HWKEY_EMULATION"
+#define STR_ATOM_KEY_MENU_LONGPRESS    "KEY_MENU_LONGPRESS"
+#define STR_ATOM_KEY_BACK_LONGPRESS    "KEY_BACK_LONGPRESS"
+#define STR_ATOM_LONG_PRESS_ENABLE     "_LONG_PRESS_ENABLE_"
+
+//key composition for screen capture
+#define NUM_KEY_COMPOSITION_ACTIONS    1
+#define NUM_COMPOSITION_KEY    2
+#define KEY_COMPOSITION_TIME 200
+#define STR_ATOM_XKEY_COMPOSITION      "_XKEY_COMPOSITION"
+#define STR_ATOM_KEYROUTER_NOTIWINDOW "_KEYROUTER_NOTIWINDOW"
+
+#define KEYROUTER_LOG_FILE             "/opt/var/log/keygrab_status.txt"
+
+typedef struct _keylist_node
+{
+       Window wid;
+       struct _keylist_node* next;
+} keylist_node;
+
+typedef struct
+{
+       int keycode;
+       char* keyname;
+       Eina_Bool longpress;
+       E_Binding_Key *bind;
+       keylist_node* pressed_win_ptr;
+       int lastmode;
+       keylist_node* or_excl_ptr;
+       keylist_node* excl_ptr;
+       keylist_node* top_ptr;
+       keylist_node* top_tail;
+       keylist_node* shared_ptr;
+       Window *shared_wins;
+       int num_shared_wins;
+} GrabbedKey;
+
+//Enumeration for getting KeyClass
+enum
+{
+       INPUTEVENT_KEY_PRESS,
+       INPUTEVENT_KEY_RELEASE,
+       INPUTEVENT_MAX
+};
+
+typedef struct _kinfo
+{
+       KeySym keysym;
+       unsigned int keycode;
+} kinfo;
+
+typedef struct _key_event_info
+{
+       int ev_type;
+       int keycode;
+       int modkey_index;
+} key_event_info;
+
+typedef struct _ModifierKey
+{
+       int set;
+       int composited;
+       int idx_mod;
+       int idx_comp;
+       Time time;
+       Eina_Bool press_only;
+       //key_comp_action action;
+       kinfo keys[NUM_COMPOSITION_KEY];
+} ModifierKey;
+typedef struct ModifierKey *ModifierKeyPtr;
+
+#define NUM_HWKEYS             37
+const char *HWKeys[] = {
+       KEY_VOLUMEUP,
+       KEY_VOLUMEDOWN,
+       KEY_CAMERA,
+       KEY_CONFIG,
+       KEY_POWER,
+       KEY_PAUSE,
+       KEY_CANCEL,
+       KEY_SEND,
+       KEY_SELECT,
+       KEY_END,
+       KEY_MEDIA,
+       KEY_PLAYCD,
+       KEY_STOPCD,
+       KEY_PAUSECD,
+       KEY_NEXTSONG,
+       KEY_PREVIOUSSONG,
+       KEY_REWIND,
+       KEY_FASTFORWARD,
+       KEY_PLAYPAUSE,
+       KEY_MUTE,
+       KEY_HOMEPAGE,
+       KEY_WEBPAGE,
+       KEY_MAIL,
+       KEY_SCREENSAVER,
+       KEY_BRIGHTNESSUP,
+       KEY_BRIGHTNESSDOWN,
+       KEY_SOFTKBD,
+       KEY_QUICKPANEL,
+       KEY_TASKSWITCH,
+       KEY_APPS,
+       KEY_SEARCH,
+       KEY_VOICE,
+       KEY_LANGUAGE,
+       "1",
+       "2",
+       "3",
+       "4",
+       "5",
+       "6",
+       "7",
+       "8",
+       "9",
+       /*KEY_1,
+       KEY_2,
+       KEY_3,
+       KEY_4,
+       KEY_5,
+       KEY_6,
+       KEY_UP,
+       KEY_DOWN,
+       KEY_LEFT,
+       KEY_RIGHT,*/
+       /*KEY_CONNECT,
+       KEY_GAMEPLAY,
+       KEY_VOICEWAKEUP_LPSD,
+       KEY_VOICEWAKEUP*/
+};
+
+typedef enum
+{
+       E_KEYROUTER_HWKEY= 1,
+       E_KEYROUTER_HOTPLUGGED,
+       E_KEYROUTER_KEYBOARD,
+       E_KEYROUTER_NONE
+} KeyrouterDeviceType;
+
+typedef struct _E_Keyrouter_Device_Info E_Keyrouter_Device_Info;
+
+struct _E_Keyrouter_Device_Info
+{
+       int id;
+       const char *name;
+       KeyrouterDeviceType type;
+};
+
+typedef struct _hwkeymap_info
+{
+       EINA_INLIST;
+       const char* key_name;
+       KeySym key_sym;
+       int num_keycodes;
+       int *keycodes;
+} hwkeymap_info;
+
+typedef struct _longpress_info
+{
+       int keycode;
+       int longpress_timeout;
+       Ecore_X_Window longpress_window;
+       Time evtime;
+} longpress_info;
+
+//global variables will be the member variables of keyrouter structure
+typedef struct _tag_keyrouter
+{
+       Ecore_X_Display* disp;
+       Ecore_X_Window rootWin;
+       Ecore_X_Window input_window;
+       Ecore_X_Window noti_window;
+
+       //screen capture related variables
+       kinfo cancel_key;
+       int modkey_set;
+       ModifierKey *modkey;
+
+       E_Zone *zone;
+
+       // for recognize long press or short press
+       int timer_flag;
+       int short_press_flag;
+       int first_press_flag;
+       int longpress_enabled;
+
+       //number of connected pointer and keyboard devices
+       int num_hwkey_devices;
+
+       Eina_List *device_list;
+       Eina_List *ignored_key_list;
+       Eina_List *waiting_key_list;
+       Eina_List *longpress_list;
+       longpress_info *pressinfo;
+       Eina_Inlist *hwkeymap_info_list;
+
+       //XInput extension 1 related variables
+       int DeviceKeyPress;
+       int DeviceKeyRelease;
+       int nInputEvent[INPUTEVENT_MAX];
+
+       //XInput extension 2 related variables
+       int xi2_opcode;
+       XIEventMask eventmask;
+
+       GrabbedKey HardKeys[MAX_HARDKEYS];
+       int isWindowStackChanged;
+       int resTopVisibleCheck;
+       int prev_sent_keycode;
+
+       //atoms
+       Atom atomHWKeyEmulation;
+       Atom atomGrabKey;
+       Atom atomGrabStatus;
+       Atom atomDeviceStatus;
+       Atom atomGrabExclWin;
+       Atom atomGrabORExclWin;
+       Atom atomMenuLongPress;
+       Atom atomBackLongPress;
+       Atom atomLongPressEnable;
+       Atom atomNotiWindow;
+
+       //event handlers
+       Ecore_Event_Handler *e_client_message_handler;
+       Ecore_Event_Handler *e_window_property_handler;
+       Ecore_Event_Handler *e_client_stack_handler;
+       Ecore_Event_Handler *e_client_remove_handler;
+       Ecore_Event_Handler *e_window_create_handler;
+       Ecore_Event_Handler *e_window_destroy_handler;
+       Ecore_Event_Handler *e_window_configure_handler;
+       Ecore_Event_Handler *e_window_stack_handler;
+       Ecore_Event_Handler *e_event_generic_handler;
+       Ecore_Event_Handler *e_event_any_handler;
+       Ecore_Timer             *e_longpress_timer;
+} KeyRouter;
+
+static int _e_keyrouter_init();
+static void _e_keyrouter_fini();
+static void _e_keyrouter_structure_init();
+static void _e_keyrouter_bindings_init();
+static void _e_keyrouter_x_input_init(void);
+static void _e_keyrouter_grab_hwkeys(int devid);
+static void _e_keyrouter_set_key_repeat(int key, int auto_repeat_mode);
+static void _e_keyrouter_hwkey_event_handler(XEvent *ev);
+static void _e_keyrouter_cancel_key(XEvent *xev, int keycode);
+
+//event handlers
+static int _e_keyrouter_cb_event_generic(void *data, int ev_type, void *event);
+static int _e_keyrouter_cb_event_any(void *data, int ev_type, void *ev);
+static int _e_keyrouter_cb_window_property(void *data, int ev_type, void *ev);
+static int _e_keyrouter_cb_e_client_stack(void *data, int ev_type, void *ev);
+static int _e_keyrouter_cb_e_client_remove(void *data, int ev_type, void *ev);
+static int _e_keyrouter_cb_window_create(void *data, int ev_type, void *ev);
+static int _e_keyrouter_cb_window_destroy(void *data, int ev_type, void *ev);
+static int _e_keyrouter_cb_window_configure(void *data, int ev_type, void *ev);
+static int _e_keyrouter_cb_window_stack(void *data, int ev_type, void *ev);
+static int _e_keyrouter_cb_client_message (void* data, int type, void* event);
+static void _e_keyrouter_xi2_device_hierarchy_handler(XIHierarchyEvent *event);
+static Eina_Bool _e_keyrouter_is_waiting_key_list_empty(XEvent *ev);
+static Eina_Bool _e_keyrouter_is_key_in_ignored_list(XEvent *ev);
+static void _e_keyrouter_device_add(int id, int type);
+static void _e_keyrouter_device_remove(int id, int type);
+static void _e_keyrouter_update_key_delivery_list(Ecore_X_Window win, int keycode, const int grab_mode, const int IsOnTop);
+
+//e17 bindings functions and action callbacks
+static int _e_keyrouter_modifiers(E_Binding_Modifier modifiers);
+static void _e_keyrouter_do_bound_key_action(XEvent *xev);
+
+static void DeliverDeviceKeyEvents(XEvent *xev);
+static void InitGrabKeyDevices();
+static int GrabKeyDevices(Window win);
+static void UngrabKeyDevices();
+
+//functions related to mouse rbutton popup
+static E_Zone* _e_keyrouter_get_zone();
+static void _e_keyrouter_do_hardkey_emulation(const char *label, unsigned int key_event, unsigned int on_release, int keycode, int cancel);
+
+//functions related to key composition for screen capture
+static void InitModKeys();
+static void ResetModKeyInfo();
+static int IsModKey(XEvent *ev, int index);
+static int IsCompKey(XEvent *ev, int index);
+static int IsKeyComposited(XEvent *ev, int index);
+static void DoKeyCompositionAction(int index, int press);
+
+static void UnSetExclusiveGrabInfoToRootWindow(int keycode, int grab_mode);
+static int AdjustTopPositionDeliveryList(Window win, int IsOnTop);
+static int AddWindowToDeliveryList(Window win, int keycode, const int grab_mode, const int IsOnTop);
+static int RemoveWindowDeliveryList(Window win, int isTopPositionMode, int UnSetExclusiveProperty);
+static int GetItemFromWindow(Window win, const char* atom_name, unsigned int **key_list);
+
+static int IsGrabbed(unsigned int keycode);
+static void detachSlave(int DeviceID);
+static void reattachSlave(int slave, int master);
+static void Keygrab_Status(unsigned int val);
+static void Device_Status(unsigned int val);
+static void PrintKeyDeliveryList();
+static void BuildKeyGrabList(Window root);
+static int GrabKeyDevice(Window win, const char* DeviceName, const int DeviceID);
+
+static int LongPressRecognize(int keycode);
+static Eina_Bool LongPressEventDeliver(void *data);
+static Eina_Bool ShortPressEventDeliver(longpress_info *kevinfo);
+
+#endif