Add some features to support tv profile. 93/71993/3 submit/tizen/20160614.021500
authorJengHyun Kang <jhyuni.kang@samsung.com>
Mon, 30 May 2016 06:26:27 +0000 (15:26 +0900)
committerJeongHyun Kang <jhyuni.kang@samsung.com>
Fri, 10 Jun 2016 05:33:12 +0000 (14:33 +0900)
 - Modify key register logic
 - Add register grab / pass interface
 - Add none register mode
 - Add monitor key mode
 - Add picturoff mode
 - Add key combination mode
 - Add get register delivery status

Change-Id: Idf015c62b1740a3655c2ba114a0caed53ef3414d

config/key_combinations.ini [new file with mode: 0644]
configure.ac
packaging/e-mod-tizen-keyrouter.spec
src/Makefile.am
src/e_mod_keyrouter_combination.c [new file with mode: 0644]
src/e_mod_keyrouter_events.c
src/e_mod_keyrouter_list.c
src/e_mod_main_wl.c
src/e_mod_main_wl.h
src/ini.c [new file with mode: 0644]
src/ini.h [new file with mode: 0644]

diff --git a/config/key_combinations.ini b/config/key_combinations.ini
new file mode 100644 (file)
index 0000000..d4c0dd7
--- /dev/null
@@ -0,0 +1,396 @@
+; Rules for this config file.
+;ANY NEW ADDITION HERE SHOULD MATCH A CORRESPONDING ADDITION TO THE ENUM "__key_comb_enum" DEFINED IN keyEvent.h IN libslp-UtilX MODULE,SUCH THAT THE COMBINATION
+;NUMBER HERE IS EQUAL TO ENUM VALUE OF THE COMBINATION ADDED IN KeyEvent.h
+; Add a new combination like[CombinationN] where N is next count from the last combination added. THIS IS IMPORTANT!
+;keys are added like:
+;1=74
+;2=90
+;3=97 here in 1=74, '1' is the 'index' :first key index in combination and '74' is the keycode expected at the 1st index among incoming keys.
+; here index has to be in sequence. THIS IS IMPORTANT!
+; KEYSYM=Keycodes mapping:
+;mute=74;exit=182;power=124;info=196;menu=133;return=9;enter=36;source=72;VolUp=76;VolDown=75;ChannelUp=96;ChannelDown=95;
+;blue key=70;RED key=67;green key=68;yellow key=69;tools key=135;FF=216;RW=176;play=208;stop=174
+;1=10;2=11;3=12;4=13;5=14;6=15;7=16;8=17;9=18;0=19;
+
+;Mute + 1 + 8 + 2 + Power
+[Combination1];
+1=74
+2=10
+3=17
+4=11
+5=124
+;Info + Menu + Mute + Power
+[Combination2]
+1=196
+2=133
+3=74
+4=124
+;Mute + Enter + Mute + Enter
+[Combination3]
+1=74
+2=36
+3=74
+4=36
+;Mute + 9 + 4 + 8 + Exit
+[Combination4]
+1=74
+2=18
+3=13
+4=17
+5=182
+;Mute + 3 + 6 + 9 + Exit
+[Combination5]
+1=74
+2=12
+3=15
+4=18
+5=182
+;Mute + 2 + 5 + 8 + Exit
+[Combination6]
+1=74
+2=11
+3=14
+4=17
+5=182
+;Info + Factory
+[Combination7]
+1=196
+2=0
+;Source + Exit + Power
+[Combination8]
+1=72
+2=182
+3=124
+;Mute + 1 + 8 + 6 + Exit
+[Combination9]
+1=74
+2=10
+3=17
+4=15
+5=182
+;Mute + 7 + 8 + 2 + Exit
+[Combination10]
+1=74
+2=16
+3=17
+4=11
+5=182
+;Mute + 7 + 8 + 3 + Exit
+[Combination11]
+1=74
+2=16
+3=17
+4=12
+5=182
+;Mute + 7 + 3 + 7 + Enter
+[Combination12]
+1=74
+2=16
+3=12
+4=16
+5=36
+;Mute + 4 + 3 + 7 + Exit
+[Combination13]
+1=74
+2=13
+3=12
+4=16
+5=182
+;Mute + 1 + 1 + 9 + Enter
+[Combination14]
+1=74
+2=10
+3=10
+4=18
+5=36
+;Mute + 5 + 6 + 7 + Exit
+[Combination15]
+1=74
+2=14
+3=15
+4=16
+5=182
+;Mute + 1 + 4 + 7 + Mute
+[Combination16]
+1=74
+2=10
+3=13
+4=16
+5=74
+;Mute + 3 + 6 + 9 + Mute
+[Combination17]
+1=74
+2=12
+3=15
+4=18
+5=74
+;Info + Mute
+[Combination18]
+1=196
+2=74
+;Mute + 2 + 2 + 7 + Exit
+[Combination19]
+1=74
+2=11
+3=11
+4=16
+5=182
+;Info + Source
+[Combination20]
+1=196
+2=72
+;Mute + RSS
+[Combination21]
+1=74
+2=0
+;Mute + 2 + 4 + 7 + Exit
+[Combination22]
+1=74
+2=11
+3=13
+4=16
+5=182
+;Mute + 2 + 0 + 7 + Exit
+[Combination23]
+1=74
+2=11
+3=19
+4=16
+5=182
+;Mute + 2 + 0 + 9 + Exit
+[Combination24]
+1=74
+2=11
+3=19
+4=18
+5=182
+;Mute + 0 + Mute + 0
+[Combination25]
+1=74
+2=19
+3=74
+4=19
+;Mute + 5 + 6 + 4 + Exit
+[Combination26]
+1=74
+2=14
+3=15
+4=13
+5=182
+;Mute + 1 + 8 + 4 + Exit
+[Combination27]
+1=74
+2=10
+3=17
+4=13
+5=182
+;'>>'(FF) + 2 + 8 + 7 + '<<'(RW)
+[Combination28]
+1=216
+2=11
+3=17
+4=16
+5=176
+;Mute + 8 + 2 + 4 + Power
+[Combination29]
+1=74
+2=17
+3=11
+4=13
+5=124
+;Mute + Vol Up + Return + Vol Down + Return + Vol Up + Return (smartctrl)
+[Combination30]
+1=74
+2=76
+3=9
+4=75
+5=9
+6=76
+7=9
+;Mute + 5 + 7 + 9 + Exit
+[Combination31]
+1=74
+2=14
+3=16
+4=18
+5=182
+;FF+2+8+9+RW 
+[Combination32]
+1=216
+2=11
+3=17
+4=18
+5=176
+;FF+2+8+9+1
+[Combination33]
+1=216
+2=11
+3=17
+4=18
+5=10
+;Mute+5+6+9+Exit
+[Combination34]
+1=74
+2=14
+3=15
+4=18
+5=182
+;Info+Menu+Mute+Menu+Exit
+[Combination35]
+1=196
+2=133
+3=74
+4=133
+5=182
+;Mute + 7 + 4 + 7 + Exit
+[Combination36]
+1=74
+2=16
+3=13
+4=16
+5=182
+;Mute + 7 + 8 + 7 + Exit
+[Combination37]
+1=74
+2=16
+3=17
+4=16
+5=182
+;FF+2+8+9+2
+[Combination38]
+1=216
+2=11
+3=17
+4=18
+5=11
+;FF+1+8+2+REW
+[Combination39]
+1=216
+2=10
+3=17
+4=11
+5=176
+;Mute+9+8+7+Exit "start key recording"
+[Combination40]
+1=74
+2=18
+3=17
+4=16
+5=182
+;Mute+Mute+Exit+Exit+Exit "stop key recording"
+[Combination41]
+1=74
+2=74
+3=182
+4=182
+5=182
+;Mute+Play+Play+Play+Exit "start playing recorded keys"
+[Combination42]
+1=74
+2=208
+3=208
+4=208
+5=182
+;Mute+Stop+Stop+Stop+Exit "stop playing recorded keys"
+[Combination43]
+1=74
+2=174
+3=174
+4=174
+5=182
+;Mute+Return+VolUp+ChannelUp+Mute 
+[Combination44]
+1=74
+2=9
+3=76
+4=96
+5=74
+;Info+Stop 
+[Combination45]
+1=196
+2=174
+;mute + 9 + 9 + 0 + 0 + exit
+[Combination46]
+1=74
+2=18
+3=18
+4=19
+5=19
+6=182
+;mute + 3 + mute +3
+[Combination47]
+1=74
+2=12
+3=74
+4=12
+;mute + 7 + mute + 7 
+[Combination48]
+1=74
+2=16
+3=74
+4=16
+;info + exit + mute
+[Combination49]
+1=196
+2=182
+3=74
+;KEY_SOURCE + 2 + 5 + 8 + 9 + KEY_PRECH
+[Combination50]
+1=72
+2=11
+3=14
+4=17
+5=18
+6=190
+;FF + 2 + 0 + 0 + 6 + 2 + 0 + 1 + 4 + 0 + 9
+[Combination51]
+1=216
+2=11
+3=19
+4=19
+5=15
+6=11
+7=19
+8=10
+9=13
+10=19
+11=18
+;FF + 2 + 0 + 0 + 6 + 2 + 0 + 1 + 4 + 0 + 8
+[Combination52]
+1=216
+2=11
+3=19
+4=19
+5=15
+6=11
+7=19
+8=10
+9=13
+10=19
+11=17
+;FF + 2 + 0 + 0 + 6 + 2 + 0 + 1 + 5 + 0 + 9
+[Combination53]
+1=216
+2=11
+3=19
+4=19
+5=15
+6=11
+7=19
+8=10
+9=14
+10=19
+11=18
+;Mute+VolUp+ChannelUp+Mute
+[Combination54]
+1=74
+2=76
+3=96
+4=74
+;Mute+0+0+7+Exit
+[Combination55]
+1=74
+2=19
+3=19
+4=16
+5=182
index f0e9f2a..5b77c2f 100644 (file)
@@ -40,6 +40,8 @@ dnl ========================================================================
 #AC_HEADER_STDC
 AC_CHECK_HEADERS([math.h fcntl.h stdlib.h string.h unistd.h])
 
+COMBINATION_FILE_PATH="$TZ_SYS_RO_APP/keyrouter/key_combinations.ini"
+AC_DEFINE_UNQUOTED(COMBINATION_FILE_PATH, "$COMBINATION_FILE_PATH", [Path to Key Combination File])
 dnl ========================================================================
 # checks for typedefs, structures, and compiler characteristics
 AC_C_CONST
@@ -59,8 +61,7 @@ PKG_PROG_PKG_CONFIG
 dnl ========================================================================
 # checks for pkg-config
 dnl ========================================================================
-PKG_CHECK_MODULES(ENLIGHTENMENT, [enlightenment,
-                                  dlog])
+PKG_CHECK_MODULES(ENLIGHTENMENT, [enlightenment])
 ENLIGHTENMENT_CFLAGS="${ENLIGHTENMENT_CFLAGS} -D_GNU_SOURCE "
 AC_SUBST(ENLIGHTENMENT_CFLAGS)
 AC_SUBST(ENLIGHTENMENT_LIBS)
@@ -113,7 +114,7 @@ dnl ========================================================================
 # checks for wayland only argument
 dnl ========================================================================
 if test "x${have_wayland_only}" = "xyes"; then
-  PKG_CHECK_MODULES(WAYLAND, [wayland-server, tizen-extension-server])
+  PKG_CHECK_MODULES(WAYLAND, [wayland-server, tizen-extension-server, capi-system-device])
 fi
 
 release=$(pkg-config --variable=release enlightenment)
index 9ab47bf..552d713 100644 (file)
@@ -16,8 +16,10 @@ BuildRequires:  pkgconfig(wayland-server)
 BuildRequires:  pkgconfig(tizen-extension-server)
 BuildRequires:  pkgconfig(cynara-client)
 BuildRequires:  pkgconfig(cynara-creds-socket)
+BuildRequires:  pkgconfig(capi-system-device)
 %endif
-BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(dbus-glib-1)
+BuildRequires:  pkgconfig(libtzplatform-config)
 %if "%{?profile}" == "common"
 %else
 BuildRequires:  xkb-tizen-data
@@ -41,7 +43,8 @@ export LDFLAGS+=" -Wl,--hash-style=both -Wl,--as-needed -Wl,--rpath=/usr/lib"
 %if %{with wayland}
 %configure --prefix=/usr \
            --enable-wayland-only \
-           --enable-cynara
+           --enable-cynara \
+           TZ_SYS_RO_APP=%{TZ_SYS_RO_APP}
 %endif
 
 make
@@ -53,6 +56,9 @@ rm -rf %{buildroot}
 mkdir -p %{buildroot}/%{TZ_SYS_RO_SHARE}/license
 cp -a %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/%{TZ_SYS_RO_SHARE}/license/%{name}
 
+# for install combination key's configuration
+mkdir -p %{buildroot}%{TZ_SYS_RO_APP}/keyrouter
+cp -af config/key_combinations.ini %{buildroot}%{TZ_SYS_RO_APP}/keyrouter/
 
 # install
 make install DESTDIR=%{buildroot}
@@ -64,3 +70,4 @@ find  %{buildroot}%{_libdir}/enlightenment/modules/%{name} -name *.la | xargs rm
 %defattr(-,root,root,-)
 %{_libdir}/enlightenment/modules/e-mod-tizen-keyrouter
 %{TZ_SYS_RO_SHARE}/license/%{name}
+%attr(754, app, root) %{TZ_SYS_RO_APP}/keyrouter
index d014c6d..ec6354c 100644 (file)
@@ -10,7 +10,10 @@ module_la_SOURCES      = e_mod_main_wl.c \
                          e_mod_main_wl.h \
                          e_mod_keyrouter_list.c \
                          e_mod_keyrouter_events.c \
-                         e_mod_keyrouter_conf.c
+                         e_mod_keyrouter_conf.c \
+                         e_mod_keyrouter_combination.c \
+                         ini.c \
+                         ini.h
 module_la_CFLAGS       = @ENLIGHTENMENT_CFLAGS@ @WAYLAND_CFLAGS@ -DHAVE_WAYLAND_ONLY @CYNARA_CFLAGS@ @TTRACE_CFLAGS@
 module_la_LDFLAGS      = -module -avoid-version @WAYLAND_LIBS@ @ENLIGHTENMENT_LIBS@ @CYNARA_LIBS@ @TTRACE_LIBS@
 endif
diff --git a/src/e_mod_keyrouter_combination.c b/src/e_mod_keyrouter_combination.c
new file mode 100644 (file)
index 0000000..4111e22
--- /dev/null
@@ -0,0 +1,422 @@
+/*\r
+ *   @file     e_mod_keyrouter_combination.c\r
+ *   @brief    Implementation of e_mod_keyrouter_combination.c\r
+ *   @author   Shubham Shrivastav shubham.sh@samsung.com\r
+ *   @date     25th Feb 2016\r
+ *   Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#define E_COMP_WL\r
+#include "e.h"\r
+#include "e_mod_main_wl.h"\r
+#include <dbus/dbus-glib.h>\r
+#include <dbus/dbus.h>\r
+#include "ini.h"\r
+\r
+#define MAX_LEN 64\r
+#define DBUS_PATH "/com/burtonini/dbus/ping"\r
+#define DBUS_IFACE "keyrouter.dbus.Signal"\r
+#define DBUS_MSG_NAME "KEY_COMBINATION"\r
+#define COMBINATION_TIME_OUT 4000\r
+#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0\r
+\r
+typedef unsigned long Time;\r
+typedef struct _DbusConf\r
+{\r
+    char path[MAX_LEN];\r
+    char interface[MAX_LEN];\r
+    char msg[MAX_LEN];\r
+} DbusConf;\r
+typedef struct _KeyCombination\r
+{\r
+    DBusConnection * keyrouter_dbus_conn;\r
+    DbusConf dbusconf;\r
+    DBusError DBus_error;\r
+    char combinationFilePath[MAX_LEN];\r
+    GArray* _master_combinations;\r
+    GArray* _current_matched_combinations;\r
+    Time combination_timeout;\r
+} KeyCombination;\r
+\r
+static int keyCombinationInitialize = 0;\r
+KeyCombination g_key_combination;\r
+\r
+static void _e_keyrouter_dbus_connection_init();\r
+static int _e_keyrouter_search_key_combination(int keycode, Time timestamp);\r
+static int _e_keyrouter_send_dbus_message(DBusConnection *bus, int Input);\r
+static char * _e_keyrouter_substring(char *string, int position);\r
+static int _e_keyrouter_parse_ini_config(void* user, const char* section, const char* name, const char* value);\r
+\r
+static void\r
+_e_keyrouter_dbus_connection_init()\r
+{\r
+   DBusError dBus_error;\r
+\r
+   KLINF("_e_keyrouter_dbus_connection_init() \n");\r
+\r
+   dbus_error_init(&dBus_error);\r
+   g_key_combination.keyrouter_dbus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dBus_error);\r
+\r
+   if (dbus_error_is_set(&dBus_error))\r
+     {\r
+        KLWRN("[DBUS-ERROR] %s \n",dBus_error.message);\r
+        dbus_error_free(&dBus_error);\r
+     }\r
+\r
+   if (!g_key_combination.keyrouter_dbus_conn)\r
+     {\r
+        KLWRN("[DBUS-CONNECTION-FAIL] DBUS connection is failed \n");\r
+     }\r
+}\r
+\r
+void\r
+e_keyrouter_key_combination_init()\r
+{\r
+   memset(&g_key_combination, 0, sizeof(g_key_combination));\r
+   g_key_combination.keyrouter_dbus_conn = NULL;\r
+   snprintf(g_key_combination.dbusconf.path, strlen(DBUS_PATH)+1, DBUS_PATH);\r
+   snprintf(g_key_combination.dbusconf.interface, strlen(DBUS_IFACE)+1, DBUS_IFACE);\r
+   snprintf(g_key_combination.dbusconf.msg, strlen(DBUS_MSG_NAME)+1, DBUS_MSG_NAME);\r
+   snprintf(g_key_combination.combinationFilePath, strlen(COMBINATION_FILE_PATH)+1, COMBINATION_FILE_PATH);\r
+\r
+   g_key_combination._master_combinations = g_array_new(FALSE, FALSE, sizeof(GArray*));\r
+   if (ini_parse((const char *) g_key_combination.combinationFilePath, _e_keyrouter_parse_ini_config, g_key_combination._master_combinations) < 0)\r
+     {\r
+        KLWRN("Can't load %s file\n", g_key_combination.combinationFilePath);\r
+     }\r
+\r
+   g_key_combination.combination_timeout = COMBINATION_TIME_OUT;\r
+   _e_keyrouter_dbus_connection_init();\r
+   keyCombinationInitialize = 1;\r
+}\r
+\r
+static char *\r
+_e_keyrouter_substring(char *string, int position)\r
+{\r
+   char *pointer;\r
+   int c;\r
+\r
+   for (c = 0; c < position - 1; c++)\r
+     string++;\r
+\r
+   pointer = malloc(strlen(string) + 1);\r
+   if (pointer == NULL)\r
+     {\r
+        KLWRN("Unable to allocate memory.\n");\r
+        return NULL;\r
+     }\r
+\r
+   for (c = 0; *string != '\0'; c++)\r
+     {\r
+        *(pointer + c) = *string;\r
+        string++;\r
+     }\r
+   *(pointer + c) = '\0';\r
+\r
+   return pointer;\r
+}\r
+\r
+static int\r
+_e_keyrouter_parse_ini_config(void* user, const char* section, const char* name, const char* value)\r
+{\r
+   int section_number, val;\r
+   size_t needed;\r
+   char *local_section, *c_num;\r
+   GArray *masterArray, *childArray;\r
+\r
+   c_num = _e_keyrouter_substring(strdup(section), 12/*"Combination"*/);\r
+   if (c_num == NULL)\r
+     {\r
+        KLWRN("\n Unable to read config. substring is null. \n");\r
+        return -1;\r
+     }\r
+\r
+   section_number = atoi(c_num);\r
+   free(c_num);\r
+   if (section_number == 0)\r
+     {\r
+        KLWRN("\n^[[36m Unable to read config. section_number is 0. ^[[0m\n");\r
+        return -1;\r
+     }\r
+   section_number--;\r
+\r
+   masterArray = (GArray*) user;\r
+   if (masterArray->len <= (unsigned int) section_number)\r
+     {\r
+        childArray = g_array_new(FALSE, FALSE, sizeof(int));\r
+        g_array_insert_val(masterArray, section_number, childArray);\r
+     }\r
+\r
+   needed = snprintf(NULL, 0, "%s%d", "Combination", section_number + 1);\r
+   local_section = malloc(needed + 1);\r
+   if (local_section == NULL)\r
+     {\r
+        KLWRN("\n^[[36m Failed to allocate memory for local_section ^[[0m\n");\r
+        return -1;\r
+     }\r
+   snprintf(local_section, needed + 1, "%s%d", "Combination", section_number + 1);\r
+\r
+   if (MATCH(local_section, "1"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 0, val);\r
+     }\r
+   else if (MATCH(local_section, "2"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 1, val);\r
+     }\r
+   else if (MATCH(local_section, "3"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 2, val);\r
+     }\r
+   else if (MATCH(local_section, "4"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 3, val);\r
+     }\r
+   else if (MATCH(local_section, "5"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 4, val);\r
+     }\r
+   else if (MATCH(local_section, "6"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 5, val);\r
+     }\r
+   else if (MATCH(local_section, "7"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 6, val);\r
+     }\r
+   else if (MATCH(local_section, "8"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 7, val);\r
+     }\r
+   else if (MATCH(local_section, "9"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 8, val);\r
+     }\r
+   else if (MATCH(local_section, "10"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 9, val);\r
+     }\r
+   else if (MATCH(local_section, "11"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 10, val);\r
+     }\r
+   else if (MATCH(local_section, "12"))\r
+     {\r
+        val = atoi(value);\r
+        childArray = g_array_index(masterArray,GArray*,section_number);\r
+        g_array_insert_val(childArray, 11, val);\r
+     }\r
+   else\r
+     {\r
+        free(local_section);\r
+        return 0; /* unknown section/name, error */\r
+     }\r
+    free(local_section);\r
+    return 1;\r
+}\r
+\r
+void\r
+e_keyrouter_process_key_combination(Time cur_time, int keycode, int state)\r
+{\r
+   int ret;\r
+\r
+   if (!keyCombinationInitialize)\r
+     {\r
+        KLWRN("KeyCombinatioin support is not initiazlied yet \n");\r
+        return ;\r
+     }\r
+   if (g_key_combination._master_combinations == NULL)\r
+     {\r
+        KLDBG(" Not searching key combination as Master combination is NULL \n");\r
+     }\r
+   if (state == ECORE_EVENT_KEY_UP)\r
+     {\r
+        ret = _e_keyrouter_search_key_combination(keycode, cur_time);\r
+\r
+        if(ret > 0)\r
+          {\r
+             _e_keyrouter_send_dbus_message(g_key_combination.keyrouter_dbus_conn, ret);\r
+          }\r
+     }\r
+}\r
+\r
+static int\r
+_e_keyrouter_send_dbus_message(DBusConnection *bus, int Input)\r
+{\r
+   DBusMessage *message = NULL;\r
+\r
+   message = dbus_message_new_signal(g_key_combination.dbusconf.path, g_key_combination.dbusconf.interface, g_key_combination.dbusconf.msg);\r
+   dbus_message_append_args(message, DBUS_TYPE_INT32, &Input, DBUS_TYPE_INVALID);\r
+\r
+   if (!dbus_connection_send(bus, message, NULL))\r
+     KLWRN( "DBUS sending MSG  FAILED!!\n");\r
+\r
+   dbus_message_unref(message);\r
+   return 1;\r
+}\r
+\r
+static int\r
+_e_keyrouter_search_key_combination(int keycode, Time timestamp)\r
+{\r
+   static Time t = 0;\r
+   unsigned int i, j = 0;\r
+   int matchedIdx = 0, foundAt = 0;\r
+   static int keyIdx = 0;\r
+   static GArray *_source_Search_Array = NULL;\r
+   GArray *childArray, *matched;\r
+\r
+   if (timestamp - t >= g_key_combination.combination_timeout && keyIdx != 0)\r
+     {\r
+        t = timestamp;\r
+        keyIdx = 0;\r
+        g_array_free(_source_Search_Array, FALSE);\r
+\r
+          {\r
+             g_key_combination._current_matched_combinations = g_array_new(FALSE, FALSE, sizeof(GArray*));\r
+             _source_Search_Array = g_key_combination._master_combinations;/*now update _current_matched_combinations assuming last key that invalidated as first key*/\r
+             matchedIdx = 0;\r
+             for (i = 0; i < _source_Search_Array->len; i++)\r
+               {\r
+                  GArray * childArray = g_array_index(_source_Search_Array,GArray*,i);\r
+                  if (keycode == g_array_index(childArray,int,0))\r
+                    {\r
+                       g_array_insert_val(g_key_combination._current_matched_combinations, matchedIdx, childArray);\r
+                       matchedIdx++;\r
+                    }\r
+               }\r
+\r
+             if (g_key_combination._current_matched_combinations->len > 0)\r
+               {\r
+                  keyIdx = 1;/*assumed that first key is the last key that invalidated the combinaton.*/\r
+                  _source_Search_Array = g_key_combination._current_matched_combinations;/*start next key combination matching from this assumed _current_matched_combinations*/\r
+                  t = timestamp;\r
+               }\r
+             else /* the key that invalidated is unavailable in any master_combinations as first element*/\r
+               {\r
+                  keyIdx = 0;\r
+                  t = timestamp;\r
+                  g_array_free(g_key_combination._current_matched_combinations, FALSE);\r
+               }\r
+          }\r
+        return -1;\r
+     }\r
+\r
+   g_key_combination._current_matched_combinations = g_array_new(FALSE, FALSE, sizeof(GArray*));\r
+   if (keyIdx == 0) _source_Search_Array = g_key_combination._master_combinations;\r
+\r
+   for (i = 0; i < _source_Search_Array->len; i++)\r
+     {\r
+        childArray = g_array_index(_source_Search_Array,GArray*,i);\r
+        if (keycode == g_array_index(childArray,int,keyIdx))\r
+          {\r
+             g_array_insert_val(g_key_combination._current_matched_combinations, matchedIdx, childArray);\r
+             matchedIdx++;\r
+          }\r
+     }\r
+\r
+   if (keyIdx > 0)/* this needs to be freed for count > 0 as for keyIdx== 0 it will point to master_combinations!*/\r
+     {\r
+        g_array_free(_source_Search_Array, FALSE);/* this actually frees "last" current_matched_combinations*/\r
+     }\r
+   if (g_key_combination._current_matched_combinations->len < 1)/* the incoming key has invalidated the combination sequence*/\r
+     {\r
+        _source_Search_Array = g_key_combination._master_combinations;/*now update _current_matched_combinations assuming last key that invalidated as first key*/\r
+        matchedIdx = 0;\r
+\r
+        for (i = 0; i < _source_Search_Array->len; i++)\r
+          {\r
+             childArray = g_array_index(_source_Search_Array,GArray*,i);\r
+             if (keycode == g_array_index(childArray,int,0))\r
+               {\r
+                  g_array_insert_val(g_key_combination._current_matched_combinations, matchedIdx, childArray);\r
+                  matchedIdx++;\r
+               }\r
+          }\r
+\r
+        if (g_key_combination._current_matched_combinations->len > 0)\r
+          {\r
+             keyIdx = 1;/*assumed that first key is the last key that invalidated the combinaton.*/\r
+             _source_Search_Array = g_key_combination._current_matched_combinations;/*start next key combination matching from this assumed _current_matched_combinations*/\r
+             t = timestamp;\r
+          }\r
+        else/* the key that invalidated is unavailable in any master_combinations as first element*/\r
+          {\r
+             keyIdx = 0;\r
+             t = timestamp;\r
+             g_array_free(g_key_combination._current_matched_combinations, FALSE);\r
+          }\r
+     }\r
+   else\r
+     {\r
+        if (g_key_combination._current_matched_combinations->len == 1 && (unsigned int)(keyIdx+1) == g_array_index(g_key_combination._current_matched_combinations,GArray*,0)->len)\r
+          {\r
+             keyIdx = 0;\r
+             t = timestamp;\r
+             matched = g_array_index(g_key_combination._current_matched_combinations,GArray*,0);\r
+\r
+             for (i = 0; i < matched->len; i++)\r
+               KLDBG("[32m Matched Combination:|%d| [0m\n", g_array_index(matched,int,i));\r
+             foundAt = 0;\r
+\r
+             for (i = 0; i < g_key_combination._master_combinations->len; i++)\r
+               {\r
+                  childArray=g_array_index(g_key_combination._master_combinations,GArray*,i);\r
+                  for (j = 0; j < childArray->len; j++)\r
+                    {\r
+                       if (childArray->len == matched->len && g_array_index(childArray,int,j) == g_array_index(matched,int,j))\r
+                         {\r
+                            foundAt = i + 1;\r
+                         }\r
+                       else\r
+                         {\r
+                            foundAt = FALSE;\r
+                            break;\r
+                         }\r
+                    }\r
+                  if (foundAt)\r
+                    {\r
+                       KLDBG("[32m COMBINATION FOUND AT : %d  [0m\n", foundAt);\r
+                       break;\r
+                    }\r
+               }\r
+             g_array_free(g_key_combination._current_matched_combinations, FALSE);/* we free this as combination is found and we need to start fresh for next key.*/\r
+             return foundAt;\r
+          }\r
+        else/*continue search for next key*/\r
+          {\r
+             t = timestamp;\r
+             keyIdx++;\r
+             _source_Search_Array = g_key_combination._current_matched_combinations;\r
+          }\r
+     }\r
+\r
+   return -1;\r
+}\r
index 6072e3c..4682f78 100644 (file)
@@ -7,7 +7,8 @@ static Eina_Bool _e_keyrouter_send_key_events_press(int type, Ecore_Event_Key *e
 static Eina_Bool _e_keyrouter_send_key_events_release(int type, Ecore_Event_Key *ev);
 static Eina_Bool _e_keyrouter_send_key_event(int type, struct wl_resource *surface, struct wl_client *wc, Ecore_Event_Key *ev, Eina_Bool focused, unsigned int mode);
 
-static Eina_Bool _e_keyrouter_send_key_events_register(int type, Ecore_Event_Key *ev);
+static Eina_Bool _e_keyrouter_send_key_events_focus(int type, struct wl_resource *surface, Ecore_Event_Key *ev, struct wl_resource **delivered_surface);
+static void _e_keyrouter_event_generate_key(Ecore_Event_Key *ev, int type, struct wl_client *send_surface);
 
 static Eina_Bool _e_keyrouter_is_key_grabbed(int key);
 static Eina_Bool _e_keyrouter_check_top_visible_window(E_Client *ec_focus, int arr_idx);
@@ -22,8 +23,7 @@ _e_keyrouter_is_key_grabbed(int key)
    if (krt->HardKeys[key].excl_ptr ||
         krt->HardKeys[key].or_excl_ptr ||
         krt->HardKeys[key].top_ptr ||
-        krt->HardKeys[key].shared_ptr ||
-        krt->HardKeys[key].registered_ptr)
+        krt->HardKeys[key].shared_ptr)
      {
         return EINA_TRUE;
      }
@@ -31,12 +31,32 @@ _e_keyrouter_is_key_grabbed(int key)
    return EINA_FALSE;
 }
 
+static void
+_e_keyrouter_event_generate_key(Ecore_Event_Key *ev, int type, struct wl_client *send_surface)
+{
+   Ecore_Event_Key *ev_cpy;
+   int len;
+
+   KLDBG("Generate new key event! wc_send: %p(%d)\n", send_surface, e_keyrouter_util_get_pid(send_surface, NULL));
+
+   len = sizeof(Ecore_Event_Key) + strlen(ev->key) + strlen(ev->keyname) + ((ev->compose) ? strlen(ev->compose) : 0) + 3;
+   ev_cpy = calloc(1, len);
+   memcpy(ev_cpy, ev, len);
+   ev_cpy->data = send_surface;
+
+   if (ECORE_EVENT_KEY_DOWN == type)
+     ecore_event_add(ECORE_EVENT_KEY_DOWN, ev_cpy, NULL, NULL);
+   else
+     ecore_event_add(ECORE_EVENT_KEY_UP, ev_cpy, NULL, NULL);
+}
+
 /* Function for checking the existing grab for a key and sending key event(s) */
 Eina_Bool
 e_keyrouter_process_key_event(void *event, int type)
 {
    Eina_Bool res = EINA_TRUE;
    Ecore_Event_Key *ev = event;
+   struct wl_client *wc;
 
    if (!ev) goto finish;
 
@@ -47,6 +67,15 @@ e_keyrouter_process_key_event(void *event, int type)
         KLDBG("data is exist send to compositor: %p\n", ev->data);
         goto finish;
      }
+   if (krt->playback_daemon_surface)
+     {
+       wc = wl_resource_get_client(krt->playback_daemon_surface);
+       if (wc)
+         {
+            _e_keyrouter_event_generate_key(ev, type, wc);
+            KLDBG("Sent key to playback-daemon\n");
+         }
+     }
 
    if (krt->max_tizen_hwkeys < ev->keycode)
      {
@@ -54,7 +83,7 @@ e_keyrouter_process_key_event(void *event, int type)
         goto finish;
      }
 
-   if ((ECORE_EVENT_KEY_DOWN == type) && (!_e_keyrouter_is_key_grabbed(ev->keycode)))
+   if ((ECORE_EVENT_KEY_DOWN == type) && !krt->HardKeys[ev->keycode].keycode)
      {
         KLDBG("The press key(%d) isn't a grabbable key or has not been grabbed yet !\n", ev->keycode);
         goto finish;
@@ -67,9 +96,11 @@ e_keyrouter_process_key_event(void *event, int type)
      }
 
    //KLDBG("The key(%d) is going to be sent to the proper wl client(s) !\n", ev->keycode);
-
-  if (_e_keyrouter_send_key_events(type, ev))
-    res = EINA_FALSE;
+   /* Call process key combination to lookup for any particular combinaton */
+   e_keyrouter_process_key_combination(ev->timestamp, ev->keycode, type);
+   KLDBG("[%s] keyname: %s, key: %s, keycode: %d\n", (type == ECORE_EVENT_KEY_DOWN) ? "KEY_PRESS" : "KEY_RELEASE", ev->keyname, ev->key, ev->keycode);
+   if (_e_keyrouter_send_key_events(type, ev))
+     res = EINA_FALSE;
 
 finish:
    return res;
@@ -112,6 +143,7 @@ _e_keyrouter_send_key_events_release(int type, Ecore_Event_Key *ev)
           }
      }
    krt->HardKeys[ev->keycode].press_ptr = NULL;
+   krt->isRegisterDelivery = EINA_FALSE;
 
    return ret;
 }
@@ -122,11 +154,34 @@ _e_keyrouter_send_key_events_press(int type, Ecore_Event_Key *ev)
    unsigned int keycode = ev->keycode;
    struct wl_resource *surface_focus = NULL;
    E_Client *ec_focus = NULL;
+   struct wl_resource *delivered_surface = NULL;
    Eina_Bool res = EINA_TRUE;
 
    E_Keyrouter_Key_List_NodePtr key_node_data;
    Eina_List *l = NULL;
 
+   ec_focus = e_client_focused_get();
+   surface_focus = e_keyrouter_util_get_surface_from_eclient(ec_focus);
+
+   if (krt->isPictureOffEnabled == 1)
+     {
+       EINA_LIST_FOREACH(krt->HardKeys[keycode].pic_off_ptr, l, key_node_data)
+          {
+            if (key_node_data)
+                {
+                 res = _e_keyrouter_send_key_event(type, key_node_data->surface, key_node_data->wc, ev, key_node_data->focused, TIZEN_KEYROUTER_MODE_REGISTERED);
+                 KLINF("PICTURE OFF Mode : Key %s(%d) ===> Surface (%p) WL_Client (%p)\n",
+                       ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keycode, key_node_data->surface, key_node_data->wc);
+                }
+          }
+       return res;
+     }
+   if (!_e_keyrouter_is_key_grabbed(ev->keycode))
+     {
+       res = _e_keyrouter_send_key_events_focus(type, surface_focus, ev, &delivered_surface);
+       return res;
+     }
+
    EINA_LIST_FOREACH(krt->HardKeys[keycode].excl_ptr, l, key_node_data)
      {
         if (key_node_data)
@@ -155,9 +210,6 @@ _e_keyrouter_send_key_events_press(int type, Ecore_Event_Key *ev)
           }
      }
 
-   ec_focus = e_client_focused_get();
-   surface_focus = e_keyrouter_util_get_surface_from_eclient(ec_focus);
-
    // Top position grab must need a focus surface.
    if (surface_focus)
      {
@@ -190,79 +242,166 @@ _e_keyrouter_send_key_events_press(int type, Ecore_Event_Key *ev)
                   break;
                }
           }
+       goto need_shared;
      }
 
    if (krt->HardKeys[keycode].shared_ptr)
      {
-        res = _e_keyrouter_send_key_event(type, surface_focus, NULL, ev, EINA_TRUE, TIZEN_KEYROUTER_MODE_SHARED);
-        KLINF("SHARED [Focus client] : Key %s (%s:%d) ===> Surface (%p) (pid: %d)\n",
-                 ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up "), ev->keyname, ev->keycode,
-                 surface_focus, e_keyrouter_util_get_pid(NULL, surface_focus));
-        e_keyrouter_add_surface_destroy_listener(surface_focus);
-
+need_shared:
+        //res = _e_keyrouter_send_key_event(type, surface_focus, NULL, ev, EINA_TRUE, TIZEN_KEYROUTER_MODE_SHARED);
+        res = _e_keyrouter_send_key_events_focus(type, surface_focus, ev, &delivered_surface);
         EINA_LIST_FOREACH(krt->HardKeys[keycode].shared_ptr, l, key_node_data)
           {
              if (key_node_data)
                {
-                  if (key_node_data->surface)
+                  if (delivered_surface && key_node_data->surface == delivered_surface)
                     {
-                       if (key_node_data->surface != surface_focus)
-                         {
-                            _e_keyrouter_send_key_event(type, key_node_data->surface,
-                                                        key_node_data->wc, ev, EINA_FALSE,
-                                                        TIZEN_KEYROUTER_MODE_SHARED);
-                            KLINF("SHARED Mode : Key %s(%s:%d) ===> Surface (%p) WL_Client (%p) (pid: %d)\n",
-                                     ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
-                                     key_node_data->surface, key_node_data->wc, e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface));
-                         }
+                       // Check for already delivered surface
+                       // do not deliver double events in this case.
+                       continue;
                     }
                   else
                     {
-                       if (((surface_focus) && (key_node_data->wc != wl_resource_get_client(surface_focus))) ||
-                           (!surface_focus))
-                         {
-                            _e_keyrouter_send_key_event(type, key_node_data->surface,
-                                                        key_node_data->wc, ev, EINA_FALSE,
-                                                        TIZEN_KEYROUTER_MODE_SHARED);
-                            KLINF("SHARED Mode : Key %s(%s:%d) ===> Surface (%p) WL_Client (%p) (pid: %d)\n",
-                                     ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
-                                     key_node_data->surface, key_node_data->wc, e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface));
-                         }
+                       _e_keyrouter_send_key_event(type, key_node_data->surface, key_node_data->wc, ev, key_node_data->focused, TIZEN_KEYROUTER_MODE_SHARED);
+                       KLINF("SHARED Mode : Key %s(%s:%d) ===> Surface (%p) WL_Client (%p) (pid: %d)\n",
+                             ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
+                             key_node_data->surface, key_node_data->wc, e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface));
                     }
                }
           }
-
         return res;
      }
 
-   if (_e_keyrouter_send_key_events_register(type, ev))
-     {
-        return EINA_TRUE;
-     }
-
    return EINA_FALSE;
 }
 
 static Eina_Bool
-_e_keyrouter_send_key_events_register(int type, Ecore_Event_Key *ev)
+_e_keyrouter_send_key_events_focus(int type, struct wl_resource *surface_focus,  Ecore_Event_Key *ev, struct wl_resource **delivered_surface)
 {
-   unsigned int keycode = ev->keycode;
+   E_Client *ec_top = NULL, *ec_focus = NULL;
+   Eina_Bool below_focus = EINA_FALSE;
+   struct wl_resource *surface = NULL;
+   Eina_List* key_list = NULL;
+   int *key_data = NULL;
+   Eina_List *ll = NULL;
+   int deliver_invisible = 0;
    Eina_Bool res = EINA_TRUE;
 
-   if (!krt->HardKeys[keycode].registered_ptr)
+   ec_top = e_client_top_get();
+   ec_focus = e_client_focused_get();
+
+   // loop over to next window from top of window stack
+   for (; ec_top != NULL; ec_top = e_client_below_get(ec_top))
      {
-        KLDBG("This keycode is not registered\n");
-        return EINA_FALSE;
-     }
+        surface = e_keyrouter_util_get_surface_from_eclient(ec_top);
+        if(surface == NULL)
+          {
+             // Not a valid surface.
+             continue;
+          }
 
-   res = _e_keyrouter_send_key_event(type, krt->HardKeys[keycode].registered_ptr->surface,
-                                     NULL, ev, krt->HardKeys[keycode].registered_ptr->focused,
-                                     TIZEN_KEYROUTER_MODE_REGISTERED);
-   KLINF("REGISTER Mode : Key %s(%s:%d) ===> Surface (%p) (pid: %d)\n",
-            ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
-            krt->HardKeys[keycode].registered_ptr->surface, e_keyrouter_util_get_pid(NULL, krt->HardKeys[keycode].registered_ptr->surface));
+        // Check if window stack reaches to focus window
+        if (ec_top == ec_focus)
+          {
+             KLINF("%p is focus client & surface_focus %p. ==> %p\n", ec_top, surface_focus, surface);
+             below_focus = EINA_TRUE;
+          }
 
-   return res;
+        // Check for FORCE DELIVER to INVISIBLE WINDOW
+        if (deliver_invisible && IsInvisibleGetWindow(surface))
+          {
+             res = _e_keyrouter_send_key_event(type, surface, NULL, ev, EINA_TRUE, TIZEN_KEYROUTER_MODE_REGISTERED);
+             KLINF("FORCE DELIVER : Key %s(%s:%d) ===> Surface (%p) (pid: %d)\n",
+                   ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
+                   surface, e_keyrouter_util_get_pid(NULL, surface));
+             *delivered_surface = surface;
+             return res;
+          }
+
+        // Check for visible window first <Consider VISIBILITY>
+        // return if not visible
+        if (ec_top->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED || ec_top->visibility.obscured == E_VISIBILITY_UNKNOWN)
+          {
+             continue;
+          }
+
+        // Set key Event Delivery for INVISIBLE WINDOW
+        if (IsInvisibleSetWindow(surface))
+          {
+             deliver_invisible = 1;
+          }
+
+        if (IsNoneKeyRegisterWindow(surface))
+          {
+             // Registered None property is set for this surface
+             // No event will be delivered to this surface.
+             KLINF("Surface(%p) is a none register window.\n", surface);
+             continue;
+          }
+
+        if (e_keyrouter_is_registered_window(surface))
+          {
+             // get the key list and deliver events if it has registered for that key
+             // Write a function to get the key list for register window.
+             key_list = _e_keyrouter_registered_window_key_list(surface);
+             if (key_list)
+               {
+                  EINA_LIST_FOREACH(key_list, ll, key_data)
+                    {
+                       if(!key_data) continue;
+
+                       if(*key_data == ev->keycode)
+                         {
+                            res = _e_keyrouter_send_key_event(type, surface, NULL, ev, EINA_TRUE, TIZEN_KEYROUTER_MODE_REGISTERED);
+                            KLINF("REGISTER Mode : Key %s(%s:%d) ===> Surface (%p) (pid: %d)\n",
+                                  ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
+                                  surface, e_keyrouter_util_get_pid(NULL, surface));
+                            *delivered_surface = surface;
+                            krt->isRegisterDelivery = EINA_TRUE;
+                            return res;
+                         }
+                    }
+               }
+             else
+               {
+                  KLDBG("Key_list is Null for registered surface %p\n", surface);
+               }
+          }
+
+        if (surface != surface_focus)
+          {
+             if (below_focus == EINA_FALSE) continue;
+
+             // Deliver to below Non Registered window
+             else if (!e_keyrouter_is_registered_window(surface))
+               {
+                  res = _e_keyrouter_send_key_event(type, surface, NULL, ev, EINA_TRUE, TIZEN_KEYROUTER_MODE_SHARED);
+                  KLINF("NOT REGISTER : Key %s(%s:%d) ===> Surface (%p) (pid: %d)\n",
+                        ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
+                        surface, e_keyrouter_util_get_pid(NULL, surface));
+                  *delivered_surface = surface;
+                  return res;
+               }
+             else continue;
+          }
+        else
+          {
+             // Deliver to Focus if Non Registered window
+             if (!e_keyrouter_is_registered_window(surface))
+               {
+                  res = _e_keyrouter_send_key_event(type, surface, NULL,ev, EINA_TRUE, TIZEN_KEYROUTER_MODE_SHARED);
+                  KLINF("FOCUS : Key %s(%s:%d) ===> Surface (%p) (pid: %d)\n",
+                        ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
+                        surface, e_keyrouter_util_get_pid(NULL, surface));
+                  *delivered_surface = surface;
+                  return res;
+               }
+             else continue;
+          }
+    }
+
+    KLINF("Couldnt Deliver key:(%s:%d) to any window. Focused Surface: %p\n", ev->keyname, ev->keycode, surface_focus);
+    return res;
 }
 
 static Eina_Bool
@@ -314,8 +453,6 @@ static Eina_Bool
 _e_keyrouter_send_key_event(int type, struct wl_resource *surface, struct wl_client *wc, Ecore_Event_Key *ev, Eina_Bool focused, unsigned int mode)
 {
    struct wl_client *wc_send;
-   Ecore_Event_Key *ev_cpy;
-   int len;
 
    if (surface == NULL)
      {
@@ -356,17 +493,7 @@ _e_keyrouter_send_key_event(int type, struct wl_resource *surface, struct wl_cli
 
    if (focused == EINA_TRUE) return EINA_FALSE;
 
-   KLDBG("Generate new key event! wc_send: %p(%d)\n", wc_send, e_keyrouter_util_get_pid(wc_send, NULL));
-
-   len = sizeof(Ecore_Event_Key) + strlen(ev->key) + strlen(ev->keyname) + ((ev->compose) ? strlen(ev->compose) : 0) + 3;
-   ev_cpy = calloc(1, len);
-   memcpy(ev_cpy, ev, len);
-   ev_cpy->data = wc_send;
-
-   if (ECORE_EVENT_KEY_DOWN == type)
-     ecore_event_add(ECORE_EVENT_KEY_DOWN, ev_cpy, NULL, NULL);
-   else
-     ecore_event_add(ECORE_EVENT_KEY_UP, ev_cpy, NULL, NULL);
+   _e_keyrouter_event_generate_key(ev, type, wc_send);
 
    return EINA_TRUE;
 }
index fe68890..4c38454 100644 (file)
@@ -86,7 +86,9 @@ _e_keyrouter_find_duplicated_client(struct wl_resource *surface, struct wl_clien
       case TIZEN_KEYROUTER_MODE_PRESSED:
          keylist_ptr = krt->HardKeys[key].press_ptr;
          break;
-
+     case TIZEN_KEYROUTER_MODE_PICTURE_OFF:
+         keylist_ptr = krt->HardKeys[key].pic_off_ptr;
+         break;
       default:
          KLWRN("Unknown key(%d) and grab mode(%d)\n", key, mode);
          return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
@@ -185,7 +187,9 @@ e_keyrouter_prepend_to_keylist(struct wl_resource *surface, struct wl_client *wc
       case TIZEN_KEYROUTER_MODE_PRESSED:
          krt->HardKeys[key].press_ptr = eina_list_prepend(krt->HardKeys[key].press_ptr, new_keyptr);
          break;
-
+     case TIZEN_KEYROUTER_MODE_PICTURE_OFF:
+         krt->HardKeys[key].pic_off_ptr = eina_list_prepend(krt->HardKeys[key].pic_off_ptr, new_keyptr);
+         break;
       default:
          KLWRN("Unknown key(%d) and grab mode(%d)\n", key, mode);
          E_FREE(new_keyptr);
@@ -361,14 +365,55 @@ e_keyrouter_remove_client_from_list(struct wl_resource *surface, struct wl_clien
                   KLINF("Remove a Pressed key(%d) by wc(%p)\n", i, wc);
                }
           }
+        EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].pic_off_ptr, l, l_next, key_node_data)
+          {
+             if (!key_node_data) continue;
+             if (surface)
+               {
+                  krt->HardKeys[i].pic_off_ptr = eina_list_remove_list(krt->HardKeys[i].pic_off_ptr, l);
+                  E_FREE(key_node_data);
+               }
+             else if ( wc == key_node_data->wc)
+               {
+                  krt->HardKeys[i].pic_off_ptr = eina_list_remove_list(krt->HardKeys[i].pic_off_ptr, l);
+                  E_FREE(key_node_data);
+               }
+          }
      }
 
    _e_keyrouter_remove_registered_surface_in_list(surface);
 }
 
+Eina_Bool
+e_keyrouter_find_key_in_register_list(uint32_t key)
+{
+   E_Keyrouter_Registered_Window_Info* rwin_info = NULL;
+   int *key_data = NULL;
+   Eina_List *l = NULL, *ll = NULL;
+
+   EINA_LIST_FOREACH(krt->registered_window_list, l, rwin_info)
+     {
+        if (!rwin_info) continue;
+        EINA_LIST_FOREACH(rwin_info->keys, ll, key_data)
+          {
+             if(*key_data == key)
+               {
+                  KLDBG("Find %d key by register surface %p\n", key, rwin_info->surface);
+                  return EINA_TRUE;
+               }
+          }
+     }
+
+   return EINA_FALSE;
+}
+
 int
 e_keyrouter_find_key_in_list(struct wl_resource *surface, struct wl_client *wc, uint32_t key)
 {
+   E_Keyrouter_Registered_Window_Info* rwin_info = NULL;
+   int *key_data = NULL;       
+   Eina_List *l = NULL, *ll = NULL;
+
    int mode = TIZEN_KEYROUTER_MODE_NONE;
    Eina_Bool found = EINA_FALSE;
 
@@ -388,6 +433,22 @@ e_keyrouter_find_key_in_list(struct wl_resource *surface, struct wl_client *wc,
    found = _e_keyrouter_find_key_in_list(surface, wc, key, mode);
    if (found) goto finish;
 
+   EINA_LIST_FOREACH(krt->registered_window_list, l, rwin_info)
+     {
+        if (rwin_info->surface == surface)
+          {
+             EINA_LIST_FOREACH(rwin_info->keys, ll, key_data)
+               {
+                  if(*key_data == key)
+                    {
+                       KLDBG("Find %d key grabbed by (surface: %p, in %s mode\n", key, surface, "TIZEN_KEYROUTER_MODE_REGISTERED");
+                       return TIZEN_KEYROUTER_MODE_REGISTERED;
+                    }
+               }
+          }
+     }
+
+   KLDBG("%d key is not grabbed by (surface: %p, wl_client: %p)\n", key, surface, wc);
    return TIZEN_KEYROUTER_MODE_NONE;
 
 finish:
@@ -511,6 +572,7 @@ e_keyrouter_unset_keyregister(struct wl_resource *surface, struct wl_client *cli
    Eina_List *l, *ll, *ll_next;
    E_Keyrouter_Registered_Window_Info *data;
    int *ddata;
+   Eina_List *key_list = NULL;
 
    _e_keyrouter_clean_register_list();
 
@@ -533,6 +595,15 @@ e_keyrouter_unset_keyregister(struct wl_resource *surface, struct wl_client *cli
           }
      }
 
+   // Remove the surface from Registry list if  all registered keys were removed.
+   key_list = _e_keyrouter_registered_window_key_list(surface);
+
+   if (!key_list)
+     {
+        KLDBG("Removing %p surface from register list, as NULL key list \n", surface);
+        _e_keyrouter_remove_registered_surface_in_list(surface);
+     }
+
    _e_keyrouter_build_register_list();
 
    KLDBG("Succeed to set keyregister info surface: %p, client: %p key: %d\n",
@@ -640,6 +711,23 @@ e_keyrouter_is_registered_window(struct wl_resource *surface)
    return EINA_FALSE;
 }
 
+Eina_List*
+_e_keyrouter_registered_window_key_list(struct wl_resource *surface)
+{
+   Eina_List *l = NULL;
+   E_Keyrouter_Registered_Window_Info *data = NULL;
+
+   EINA_LIST_FOREACH(krt->registered_window_list, l, data)
+     {
+        if (data->surface == surface)
+          {
+             return data->keys;
+          }
+     }
+   return NULL;
+}
+
+
 void
 e_keyrouter_clear_registered_window(void)
 {
index 3df7f11..3e41088 100644 (file)
@@ -1,6 +1,11 @@
 #define E_COMP_WL
 #include "e_mod_main_wl.h"
 #include <string.h>
+#include <device/power.h>
+#include <device/callback.h>
+#include <device/display.h>
+
+#define KRT_IPD_INPUT_CONFIG          444
 
 E_KeyrouterPtr krt = NULL;
 E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Keyrouter Module of Window Manager" };
@@ -19,7 +24,8 @@ static void _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data
 
 static int _e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface, uint32_t key, uint32_t mode);
 static int _e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface, uint32_t key);
-
+static Eina_Bool _e_keyrouter_cb_idler(void *data);
+static void _e_keyrouter_cb_power_change(device_callback_e type, void* value, void* user_data);
 #ifdef ENABLE_CYNARA
 static void _e_keyrouter_util_cynara_log(const char *func_name, int err);
 static Eina_Bool _e_keyrouter_util_do_privilege_check(struct wl_client *client, int socket_fd, uint32_t mode, uint32_t keycode);
@@ -52,9 +58,10 @@ _e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface,
    if (!surface)
      {
         /* Regarding topmost mode, a client must request to grab a key with a valid surface. */
-        if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
+        if (mode == TIZEN_KEYROUTER_MODE_TOPMOST ||
+            mode == TIZEN_KEYROUTER_MODE_REGISTERED)
           {
-             KLWRN("Invalid surface for TOPMOST grab mode ! (key=%d, mode=%d)\n", key, mode);
+             KLWRN("Invalid surface for %d grab mode ! (key=%d)\n", mode, key);
 
              return TIZEN_KEYROUTER_ERROR_INVALID_SURFACE;
           }
@@ -198,9 +205,12 @@ _e_keyrouter_cb_keygrab_set_list(struct wl_client *client, struct wl_resource *r
         /* FIX ME: Which way is effectively to notify invalid pair to client */
         KLWRN("Invalid keycode and grab mode pair. Check arguments in a list\n");
         grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Result));
-        grab_result->request_data.key = 0;
-        grab_result->request_data.mode = 0;
-        grab_result->err = TIZEN_KEYROUTER_ERROR_INVALID_ARRAY;
+        if (grab_result)
+          {
+             grab_result->request_data.key = 0;
+             grab_result->request_data.mode = 0;
+             grab_result->err = TIZEN_KEYROUTER_ERROR_INVALID_ARRAY;
+          }
         goto send_notify;
      }
 
@@ -253,6 +263,252 @@ _e_keyrouter_cb_keygrab_unset_list(struct wl_client *client, struct wl_resource
    wl_array_release(&grab_result_list);
 }
 
+static void
+_e_keyrouter_cb_get_keyregister_status(struct wl_client *client, struct wl_resource *resource, uint32_t key)
+{
+   (void) client;
+   (void) key;
+
+   Eina_Bool res = EINA_FALSE;
+
+   if (krt->isRegisterDelivery)
+     {
+        res = EINA_TRUE;
+     }
+
+   tizen_keyrouter_send_keyregister_notify(resource, (int)res);
+}
+
+static void
+_e_keyrouter_cb_set_input_config(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t config_mode, uint32_t value)
+{
+   Eina_Bool res = EINA_TRUE;
+   KLINF("Given Surface(%p) for mode %d with value = %d \n", surface, config_mode, value);
+
+   if (surface == NULL && config_mode != TIZEN_KEYROUTER_CONFIG_MODE_PICTURE_OFF)
+     {
+        KLWRN("Error Surface is NULL \n");
+        res = EINA_FALSE;
+        goto send_input_config_notify;
+     }
+
+   switch (config_mode)
+     {
+        case TIZEN_KEYROUTER_CONFIG_MODE_INVISIBLE_SET:
+           if (value)
+             {
+                krt->invisible_set_window_list= eina_list_append(krt->invisible_set_window_list, surface);
+             }
+           else
+             {
+                krt->invisible_set_window_list= eina_list_remove(krt->invisible_set_window_list, surface);
+             }
+           break;
+
+        case KRT_IPD_INPUT_CONFIG:
+           krt->playback_daemon_surface = surface;
+           KLINF("Registered playback daemon surface: %p",surface);
+           break;
+
+        case TIZEN_KEYROUTER_CONFIG_MODE_INVISIBLE_GET:
+           if (value)
+             {
+                krt->invisible_get_window_list= eina_list_append(krt->invisible_get_window_list, surface);
+             }
+           else
+             {
+                krt->invisible_get_window_list= eina_list_remove(krt->invisible_get_window_list, surface);
+             }
+           break;
+
+        case TIZEN_KEYROUTER_CONFIG_MODE_NUM_KEY_FOCUS:
+            // to do ;
+            break;
+
+        case TIZEN_KEYROUTER_CONFIG_MODE_PICTURE_OFF:
+            res = e_keyrouter_prepend_to_keylist(surface, surface ? NULL : client, value, TIZEN_KEYROUTER_MODE_PICTURE_OFF, EINA_FALSE);
+            /* As surface/client destroy listener got added in e_keyrouter_prepend_to_keylist() function already */
+            value = 0;
+            break;
+
+        default:
+            KLWRN("Wrong mode requested: %d \n", config_mode);
+            res= EINA_FALSE;
+            goto send_input_config_notify;
+     }
+
+   if (value)
+     {
+        KLDBG("Add a surface(%p) destory listener\n", surface);
+        e_keyrouter_add_surface_destroy_listener(surface);
+     }
+send_input_config_notify:
+   tizen_keyrouter_send_set_input_config_notify(resource, (int)res);
+}
+
+/* tizen_keyrouter check if given surface in register none key list */
+Eina_Bool
+IsNoneKeyRegisterWindow(struct wl_resource *surface)
+{
+   struct wl_resource *surface_ldata = NULL;
+   Eina_List *l = NULL, *l_next = NULL;
+
+   EINA_LIST_FOREACH_SAFE (krt->registered_none_key_window_list, l, l_next, surface_ldata)
+     {
+        if (surface_ldata == surface)
+          {
+             KLDBG("Given surface(%p) is in NoneKeyRegisterWindow \n", surface);
+             return EINA_TRUE;
+          }
+     }
+   return EINA_FALSE;
+}
+
+/* tizen_keyrouter check if given surface in register invisible set list */
+Eina_Bool
+IsInvisibleSetWindow(struct wl_resource *surface)
+{
+   struct wl_resource *surface_ldata = NULL;
+   Eina_List *l = NULL, *l_next = NULL;
+
+   EINA_LIST_FOREACH_SAFE(krt->invisible_set_window_list, l, l_next, surface_ldata)
+     {
+        if (surface_ldata == surface)
+          {
+             return EINA_TRUE;
+          }
+     }
+   return EINA_FALSE;
+}
+
+/* tizen_keyrouter check if given surface in register invisible get list */
+Eina_Bool
+IsInvisibleGetWindow(struct wl_resource *surface)
+{
+   struct wl_resource *surface_ldata = NULL;
+   Eina_List *l = NULL, *l_next = NULL;
+
+   EINA_LIST_FOREACH_SAFE(krt->invisible_get_window_list, l, l_next, surface_ldata)
+     {
+        if (surface_ldata == surface)
+          {
+             return EINA_TRUE;
+          }
+     }
+   return EINA_FALSE;
+}
+
+static void
+_e_keyrouter_cb_set_register_none_key(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t data)
+{
+   (void) client;
+
+   // Register None key set/get
+   krt->register_none_key = data;
+   if (krt->register_none_key)
+     {
+        krt->registered_none_key_window_list = eina_list_append(krt->registered_none_key_window_list, surface);
+        if (surface)
+          {
+             e_keyrouter_add_surface_destroy_listener(surface);
+             /* TODO: if failed add surface_destory_listener, remove keygrabs */
+          }
+     }
+   else
+     {
+        krt->registered_none_key_window_list = eina_list_remove(krt->registered_none_key_window_list, surface);
+     }
+
+   KLDBG("Set Registered None Key called on surface (%p) with data (%d)\n", surface, krt->register_none_key);
+   tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, krt->register_none_key);
+}
+
+static void
+_e_keyrouter_cb_keygrab_get_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface)
+{
+   E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
+   struct wl_array grab_result_list = {0,};
+   E_Keyrouter_Grab_Result *grab_result = NULL;
+   E_Keyrouter_Registered_Window_Info *rwin_info = NULL;
+   Eina_List *l = NULL, *ll = NULL, *l_next = NULL;
+   int *key_data;
+   int i;
+
+   wl_array_init(&grab_result_list);
+
+   for (i = 0; i < krt->max_tizen_hwkeys; i++)
+     {
+        if (0 == krt->HardKeys[i].keycode) continue;
+
+        EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].excl_ptr, l, l_next, key_node_data)
+          {
+             if (surface == key_node_data->surface)
+               {
+                  grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Result));
+                  if (grab_result)
+                    {
+                       grab_result->request_data.key = i;
+                       grab_result->request_data.mode = TIZEN_KEYROUTER_MODE_EXCLUSIVE;
+                    }
+               }
+          }
+        EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].or_excl_ptr, l, l_next, key_node_data)
+          {
+             if (surface == key_node_data->surface)
+               {
+                  grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Result));
+                  if (grab_result)
+                    {
+                       grab_result->request_data.key = i;
+                       grab_result->request_data.mode = TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE;
+                    }
+               }
+          }
+        EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].top_ptr, l, l_next, key_node_data)
+          {
+             if (surface == key_node_data->surface)
+               {
+                  grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Result));
+                  if (grab_result)
+                    {
+                       grab_result->request_data.key = i;
+                       grab_result->request_data.mode = TIZEN_KEYROUTER_MODE_TOPMOST;
+                    }
+               }
+          }
+        EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].shared_ptr, l, l_next, key_node_data)
+          {
+             if (surface == key_node_data->surface)
+               {
+                  grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Result));
+                  if (grab_result)
+                    {
+                       grab_result->request_data.key = i;
+                       grab_result->request_data.mode = TIZEN_KEYROUTER_MODE_SHARED;
+                    }
+               }
+          }
+     }
+   // handle register mode here
+   EINA_LIST_FOREACH(krt->registered_window_list, l, rwin_info)
+     {
+        if (rwin_info->surface == surface)
+          {
+             EINA_LIST_FOREACH(rwin_info->keys, ll, key_data)
+               {
+                  grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Result));
+                  if (grab_result)
+                    {
+                       grab_result->request_data.key = *key_data;
+                       grab_result->request_data.mode = TIZEN_KEYROUTER_MODE_REGISTERED;
+                    }
+               }
+          }
+     }
+
+   tizen_keyrouter_send_getgrab_notify_list(resource, surface, &grab_result_list);
+   wl_array_release(&grab_result_list);
+}
 
 /* Function for registering wl_client destroy listener */
 int
@@ -332,7 +588,11 @@ static const struct tizen_keyrouter_interface _e_keyrouter_implementation = {
    _e_keyrouter_cb_keygrab_unset,
    _e_keyrouter_cb_get_keygrab_status,
    _e_keyrouter_cb_keygrab_set_list,
-   _e_keyrouter_cb_keygrab_unset_list
+   _e_keyrouter_cb_keygrab_unset_list,
+   _e_keyrouter_cb_keygrab_get_list,
+   _e_keyrouter_cb_set_register_none_key,
+   _e_keyrouter_cb_get_keyregister_status,
+   _e_keyrouter_cb_set_input_config
 };
 
 /* tizen_keyrouter global object destroy function */
@@ -373,12 +633,57 @@ _event_filter(void *data, void *loop_data EINA_UNUSED, int type, void *event)
    /* Filter only for key down/up event */
    if (ECORE_EVENT_KEY_DOWN == type || ECORE_EVENT_KEY_UP == type)
      {
+        if (ECORE_EVENT_KEY_DOWN == type)
+          {
+             TRACE_INPUT_BEGIN(event_filter:KEY_PRESS);
+             TRACE_INPUT_END();
+          }
+        else if (ECORE_EVENT_KEY_UP == type)
+          {
+             TRACE_INPUT_BEGIN(event_filter:KEY_RELEASE);
+             TRACE_INPUT_END();
+          }
         return e_keyrouter_process_key_event(event, type);
      }
 
    return EINA_TRUE;
 }
 
+static void
+_e_keyrouter_cb_power_change(device_callback_e type, void* value, void* user_data)
+{
+   if (type != DEVICE_CALLBACK_DISPLAY_STATE)
+     {
+        KLWRN("type is not DISPLAY_STATE");
+        return;
+     }
+
+   display_state_e state = (display_state_e)value;
+   switch (state)
+     {
+        case DISPLAY_STATE_SCREEN_OFF:
+           krt->isPictureOffEnabled = 1;
+           break;
+        case DISPLAY_STATE_NORMAL:
+           krt->isPictureOffEnabled = 0;
+           break;
+        case DISPLAY_STATE_SCREEN_DIM:
+           krt->isPictureOffEnabled = 0;
+           break;
+        default:
+           krt->isPictureOffEnabled = 0;
+           break;
+     }
+   KLDBG("Picture off flag changed to %d \n", krt->isPictureOffEnabled);
+}
+
+static Eina_Bool _e_keyrouter_cb_idler(void *data)
+{
+    device_add_callback(DEVICE_CALLBACK_DISPLAY_STATE,_e_keyrouter_cb_power_change,NULL);
+    return ECORE_CALLBACK_CANCEL;
+}
+
+
 static E_Keyrouter_Config_Data *
 _e_keyrouter_init(E_Module *m)
 {
@@ -411,12 +716,16 @@ _e_keyrouter_init(E_Module *m)
    EINA_SAFETY_ON_NULL_GOTO(kconfig->conf, err);
    krt->conf = kconfig;
 
+   e_keyrouter_key_combination_init();
+
    /* Get keyname and keycode pair from Tizen Key Layout file */
    res = _e_keyrouter_query_tizen_key_table();
    EINA_SAFETY_ON_FALSE_GOTO(res, err);
 
    /* Add filtering mechanism */
    krt->ef_handler = ecore_event_filter_add(NULL, _event_filter, NULL, NULL);
+   //ecore handler add for power callback registration
+   ecore_idle_enterer_add(_e_keyrouter_cb_idler, NULL);
    _e_keyrouter_init_handlers();
 
    krt->global = wl_global_create(e_comp_wl->wl.disp, &tizen_keyrouter_interface, 1, krt, _e_keyrouter_cb_bind);
@@ -633,7 +942,7 @@ _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
 static void
 _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
 {
-   struct wl_resource *surface = data;
+   struct wl_resource *surface = (struct wl_resource *)data;
 
    KLDBG("Listener(%p) called: surface: %p is died\n", l, surface);
    e_keyrouter_remove_client_from_list(surface, NULL);
@@ -642,6 +951,14 @@ _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
    l = NULL;
 
    krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, surface);
+   krt->registered_none_key_window_list = eina_list_remove(krt->registered_none_key_window_list, surface);
+   krt->invisible_set_window_list= eina_list_remove(krt->invisible_set_window_list, surface);
+   krt->invisible_get_window_list= eina_list_remove(krt->invisible_get_window_list, surface);
+   if (surface == krt->playback_daemon_surface)
+     {
+        krt->playback_daemon_surface = NULL;
+        KLDBG("playback daemon surface destroyed!");
+     }
 }
 
 #ifdef ENABLE_CYNARA
index 3f252ed..c5de001 100644 (file)
@@ -52,6 +52,9 @@ typedef struct _E_Keyrouter_Conf_Edd E_Keyrouter_Conf_Edd;
 typedef struct _E_Keyrouter_Config_Data E_Keyrouter_Config_Data;
 
 #define TIZEN_KEYROUTER_MODE_PRESSED        TIZEN_KEYROUTER_MODE_REGISTERED+1
+#define TIZEN_KEYROUTER_MODE_PICTURE_OFF        TIZEN_KEYROUTER_MODE_REGISTERED+2
+
+typedef unsigned long Time;
 
 extern E_KeyrouterPtr krt;
 
@@ -104,6 +107,7 @@ struct _E_Keyrouter_Grabbed_Key
    Eina_List *shared_ptr;
    Eina_List *press_ptr;
    E_Keyrouter_Key_List_Node *registered_ptr;
+   Eina_List *pic_off_ptr;
 };
 
 struct _E_Keyrouter
@@ -123,9 +127,16 @@ struct _E_Keyrouter
    Eina_Bool isWindowStackChanged;
    int numTizenHWKeys;
    int max_tizen_hwkeys;
+   int register_none_key;
+   Eina_List *registered_none_key_window_list;
+   Eina_List *invisible_set_window_list;
+   Eina_List *invisible_get_window_list;
+   struct wl_resource * playback_daemon_surface;
 #ifdef ENABLE_CYNARA
    cynara *p_cynara;
 #endif
+   int isPictureOffEnabled;
+   Eina_Bool isRegisterDelivery;
 };
 
 struct _E_Keyrouter_Grab_Request {
@@ -150,6 +161,7 @@ int e_keyrouter_prepend_to_keylist(struct wl_resource *surface, struct wl_client
 void e_keyrouter_find_and_remove_client_from_list(struct wl_resource *surface, struct wl_client *wc, uint32_t key, uint32_t mode);
 void e_keyrouter_remove_client_from_list(struct wl_resource *surface, struct wl_client *wc);
 int e_keyrouter_find_key_in_list(struct wl_resource *surface, struct wl_client *wc, uint32_t key);
+Eina_Bool e_keyrouter_find_key_in_register_list(uint32_t key);
 
 int e_keyrouter_add_client_destroy_listener(struct wl_client *client);
 int e_keyrouter_add_surface_destroy_listener(struct wl_resource *surface);
@@ -160,11 +172,18 @@ int e_keyrouter_set_keyregister(struct wl_client *client, struct wl_resource *su
 int e_keyrouter_unset_keyregister(struct wl_resource *surface, struct wl_client *client, uint32_t key);
 Eina_Bool e_keyrouter_is_registered_window(struct wl_resource *surface);
 void e_keyrouter_clear_registered_window(void);
+Eina_List* _e_keyrouter_registered_window_key_list(struct wl_resource *surface);
+Eina_Bool IsNoneKeyRegisterWindow(struct wl_resource *surface);
+Eina_Bool IsInvisibleSetWindow(struct wl_resource *surface);
+Eina_Bool IsInvisibleGetWindow(struct wl_resource *surface);
+
 
 struct wl_resource *e_keyrouter_util_get_surface_from_eclient(E_Client *client);
 int e_keyrouter_util_get_pid(struct wl_client *client, struct wl_resource *surface);
 
 void e_keyrouter_conf_init(E_Keyrouter_Config_Data *kconfig);
 void e_keyrouter_conf_deinit(E_Keyrouter_Config_Data *kconfig);
-
+void e_keyrouter_key_combination_init();
+void e_keyrouter_process_key_combination(Time cur_time, int keycode, int state);
+int e_keyrouter_cb_picture_off(const int option, void *data);
 #endif
diff --git a/src/ini.c b/src/ini.c
new file mode 100644 (file)
index 0000000..a4e79c3
--- /dev/null
+++ b/src/ini.c
@@ -0,0 +1,185 @@
+/* inih -- simple .INI file parser
+
+inih is released under the New BSD license (see LICENSE.txt). Go to the project
+home page for more info:
+
+
+*/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "ini.h"
+#include "errno.h"
+
+#if !INI_USE_STACK
+#include <stdlib.h>
+#endif
+
+#define MAX_SECTION 50
+#define MAX_NAME 50
+
+static char *
+rstrip(char* s)
+{
+   char* p = s + strlen(s);
+   while (p > s && isspace((unsigned char)(*--p)))
+     *p = '\0';
+   return s;
+}
+
+static char *
+lskip(char* s)
+{
+   while (*s && isspace((unsigned char)(*s)))
+     s++;
+   return (char*)s;
+}
+
+static char *
+find_char_or_comment(char* s, char c)
+{
+   int was_whitespace = 0;
+   while (*s && *s != c && !(was_whitespace && *s == ';'))
+     {
+        was_whitespace = isspace((unsigned char)(*s));
+        s++;
+     }
+   return (char*)s;
+}
+
+static char *
+strncpy0(char* dest, const char* src, size_t size)
+{
+   strncpy(dest, src, size);
+   dest[size - 1] = '\0';
+   return dest;
+}
+
+int
+ini_parse_file(FILE* file,
+               int (*handler)(void*, const char*, const char*, const char*),
+               void* user)
+{
+#if INI_USE_STACK
+   char line[INI_MAX_LINE];
+#else
+   char* line;
+#endif
+   char section[MAX_SECTION] = "";
+   char prev_name[MAX_NAME] = "";
+
+   char* start;
+   char* end;
+   char* name;
+   char* value;
+   int lineno = 0;
+   int error = 0;
+
+#if !INI_USE_STACK
+   line = (char*)malloc(INI_MAX_LINE);
+   if (!line)
+     {
+        return -2;
+     }
+#endif
+
+   while (fgets(line, INI_MAX_LINE, file) != NULL)
+     {
+        lineno++;
+
+        start = line;
+#if INI_ALLOW_BOM
+        if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
+           (unsigned char)start[1] == 0xBB &&
+           (unsigned char)start[2] == 0xBF)
+          {
+             start += 3;
+          }
+#endif
+        start = lskip(rstrip(start));
+
+        if (*start == ';' || *start == '#')
+          {
+             ;
+          }
+#if INI_ALLOW_MULTILINE
+        else if (*prev_name && *start && start > line)
+          {
+             if (!handler(user, section, prev_name, start) && !error)
+               error = lineno;
+          }
+#endif
+        else if (*start == '[')
+          {
+             end = find_char_or_comment(start + 1, ']');
+             if (*end == ']')
+               {
+                  *end = '\0';
+                  strncpy0(section, start + 1, sizeof(section));
+                  *prev_name = '\0';
+               }
+             else if (!error)
+               {
+                  error = lineno;
+               }
+          }
+        else if (*start && *start != ';')
+          {
+             end = find_char_or_comment(start, '=');
+             if (*end != '=')
+               {
+                  end = find_char_or_comment(start, ':');
+               }
+             if (*end == '=' || *end == ':')
+               {
+                  *end = '\0';
+                  name = rstrip(start);
+                  value = lskip(end + 1);
+                  end = find_char_or_comment(value, '\0');
+
+                  if (*end == ';')
+                    *end = '\0';
+                  rstrip(value);
+
+                  strncpy0(prev_name, name, sizeof(prev_name));
+
+                  if (!handler(user, section, name, value) && !error)
+                    error = lineno;
+               }
+             else if (!error)
+               {
+                  error = lineno;
+               }
+          }
+
+#if INI_STOP_ON_FIRST_ERROR
+        if (error)
+          break;
+#endif
+     }
+
+#if !INI_USE_STACK
+   free(line);
+#endif
+
+   return error;
+}
+
+
+int
+ini_parse(const char* filename,
+          int (*handler)(void*, const char*, const char*, const char*),
+          void* user)
+{
+   FILE* file;
+   int error;
+
+   file = fopen(filename, "r");
+   if (!file)
+     return -1;
+   error = ini_parse_file(file, handler, user);
+   fclose(file);
+   return error;
+}
diff --git a/src/ini.h b/src/ini.h
new file mode 100644 (file)
index 0000000..0411663
--- /dev/null
+++ b/src/ini.h
@@ -0,0 +1,52 @@
+/* inih -- simple .INI file parser
+
+inih is released under the New BSD license (see LICENSE.txt). Go to the project
+home page for more info:
+
+
+*/
+
+#ifndef __INI_H__
+#define __INI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+
+int ini_parse(const char* filename,
+              int (*handler)(void* user, const char* section,
+                             const char* name, const char* value),
+              void* user);
+
+int ini_parse_file(FILE* file,
+                   int (*handler)(void* user, const char* section,
+                                  const char* name, const char* value),
+                   void* user);
+
+#ifndef INI_ALLOW_MULTILINE
+#define INI_ALLOW_MULTILINE 1
+#endif
+
+#ifndef INI_ALLOW_BOM
+#define INI_ALLOW_BOM 1
+#endif
+
+#ifndef INI_USE_STACK
+#define INI_USE_STACK 1
+#endif
+
+#ifndef INI_STOP_ON_FIRST_ERROR
+#define INI_STOP_ON_FIRST_ERROR 0
+#endif
+
+#ifndef INI_MAX_LINE
+#define INI_MAX_LINE 200
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INI_H__ */