From: jeon Date: Mon, 3 Feb 2020 12:32:47 +0000 (+0900) Subject: e_keyrouter: add longpress and composition key functions X-Git-Tag: submit/tizen/20200210.084753~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e8c985f143c7796574284d3bd723e5ad3fa204d2;p=platform%2Fupstream%2Fenlightenment.git e_keyrouter: add longpress and composition key functions Change-Id: I9f104c5e45cbee9fc752ea0329708d60fdb18c47 --- diff --git a/src/bin/e_keyrouter.c b/src/bin/e_keyrouter.c index b231a72843..1e922fb19e 100644 --- a/src/bin/e_keyrouter.c +++ b/src/bin/e_keyrouter.c @@ -16,6 +16,10 @@ int _keyrouter_log_dom = -1; E_API E_Keyrouter_Info e_keyrouter; E_KeyrouterPtr krt; +E_API int E_KEYROUTER_EVENT_KEY_LONG = 0; +E_API int E_KEYROUTER_EVENT_KEY_COMPOSITION_PRESS = 0; +E_API int E_KEYROUTER_EVENT_KEY_COMPOSITION_RELEASE = 0; + E_API E_Keyrouter_Intercept_Hook * e_keyrouter_intercept_hook_add(E_Keyrouter_Intercept_Hook_Point hookpoint, E_Keyrouter_Intercept_Hook_Cb func, const void *data) { @@ -439,6 +443,135 @@ _e_keyrouter_max_keycode_get(void) return krt->max_tizen_hwkeys; } +E_API int +e_keyrouter_longkey_add(int keycode, double time) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(krt, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(keycode <= krt->max_tizen_hwkeys, EINA_FALSE); + + if (krt->HardKeys[keycode].longkey.enabled == EINA_TRUE) + { + KLWRN("The %d keycode'long press is already enabled by time: %lf\n", keycode, krt->HardKeys[keycode].longkey.time); + return EINA_FALSE; + } + + krt->HardKeys[keycode].longkey.enabled = EINA_TRUE; + krt->HardKeys[keycode].longkey.time = time; + + KLINF("To enable %d key's longkey function. (time: %lf)\n", keycode, time); + + return EINA_TRUE; +} + +E_API void +e_keyrouter_longkey_del(int keycode) +{ + /* FIXME: If del request is came, during checking long press, + How control this behavior? + Cancel current long press or not + */ + + krt->HardKeys[keycode].longkey.enabled = EINA_FALSE; + krt->HardKeys[keycode].longkey.time = 0.0; + + KLINF("To disable %d key's longkey function.\n", keycode); +} + +E_API int +e_keyrouter_composition_key_add(int *keys, int count) +{ + Eina_List *l; + int *data, *data2; + + EINA_SAFETY_ON_NULL_RETURN_VAL(krt, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(keys[0] <= krt->max_tizen_hwkeys, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(keys[1] <= krt->max_tizen_hwkeys, EINA_FALSE); + + if (count != 2) + { + KLWRN("Currently only two key composition is allowed. (%d)\n", count); + return EINA_FALSE; + } + + EINA_LIST_FOREACH(krt->HardKeys[keys[0]].composition_key_list, l, data) + { + if (*data == keys[1]) + { + KLWRN("%d and %d key's key composition is already requested.\n", keys[0], keys[1]); + return EINA_FALSE; + } + } + EINA_LIST_FOREACH(krt->HardKeys[keys[1]].composition_key_list, l, data) + { + if (*data == keys[0]) + { + KLERR("%d and %d key's key composition is already requested. (list currupted)\n", keys[0], keys[1]); + return EINA_FALSE; + } + } + + data = E_NEW(int, 1); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + + data2 = E_NEW(int, 1); + EINA_SAFETY_ON_NULL_GOTO(data2, failed); + + *data = keys[0]; + *data2 = keys[1]; + + krt->HardKeys[keys[0]].composition_key_list = eina_list_append(krt->HardKeys[keys[0]].composition_key_list, data2); + krt->HardKeys[keys[1]].composition_key_list = eina_list_append(krt->HardKeys[keys[1]].composition_key_list, data); + + KLINF("Add %d and %d key composition.\n", keys[0], keys[1]); + + return EINA_TRUE; + +failed: + if (data) E_FREE(data); + + return EINA_FALSE; +} + +E_API void +e_keyrouter_composition_key_del(int *keys, int count) +{ + /* FIXME: If del request is came, during checking composition key about key press, + How control this behavior? + Cancel current composition key or not + */ + Eina_List *l, *l_next; + int *data; + + if (count != 2) + { + KLWRN("Currently only two key composition is allowed. (%d)\n", count); + return; + } + + EINA_LIST_FOREACH_SAFE(krt->HardKeys[keys[0]].composition_key_list, l, l_next, data) + { + if (*data == keys[1]) + { + krt->HardKeys[keys[0]].composition_key_list = eina_list_remove_list(krt->HardKeys[keys[0]].composition_key_list, l); + E_FREE(data); + break; + } + } + + EINA_LIST_FOREACH_SAFE(krt->HardKeys[keys[1]].composition_key_list, l, l_next, data) + { + if (*data == keys[0]) + { + krt->HardKeys[keys[1]].composition_key_list = eina_list_remove_list(krt->HardKeys[keys[1]].composition_key_list, l); + E_FREE(data); + break; + } + } + + KLINF("Delete %d and %d key composition.\n", keys[0], keys[1]); +} + + E_API int e_keyrouter_init(void) { @@ -464,6 +597,8 @@ e_keyrouter_init(void) krt->conf = kconfig; krt->pictureoff_disabled = !!kconfig->conf->pictureoff_disabled; + krt->composition_key.waiting_time = kconfig->conf->composition_key_wait_time; + res = e_keyrouter_wl_init(); EINA_SAFETY_ON_FALSE_GOTO(res, err); @@ -479,6 +614,13 @@ e_keyrouter_init(void) e_keyrouter.keygrab_list_get = _e_keyrouter_keygrab_list_get; e_keyrouter.max_keycode_get = _e_keyrouter_max_keycode_get; + if (!E_KEYROUTER_EVENT_KEY_LONG) + E_KEYROUTER_EVENT_KEY_LONG = ecore_event_type_new(); + if (!E_KEYROUTER_EVENT_KEY_COMPOSITION_PRESS) + E_KEYROUTER_EVENT_KEY_COMPOSITION_PRESS = ecore_event_type_new(); + if (!E_KEYROUTER_EVENT_KEY_COMPOSITION_RELEASE) + E_KEYROUTER_EVENT_KEY_COMPOSITION_RELEASE = ecore_event_type_new(); + TRACE_INPUT_END(); return EINA_TRUE; @@ -514,12 +656,33 @@ e_keyrouter_shutdown(void) { if (krt->HardKeys[i].keyname) eina_stringshare_del(krt->HardKeys[i].keyname); + EINA_LIST_FREE(krt->HardKeys[i].composition_key_list, keycode_data) + E_FREE(keycode_data); } E_FREE(krt->HardKeys); EINA_LIST_FREE(krt->ignore_list, keycode_data) E_FREE(keycode_data); + ecore_event_type_flush(E_KEYROUTER_EVENT_KEY_LONG, + E_KEYROUTER_EVENT_KEY_COMPOSITION_PRESS, + E_KEYROUTER_EVENT_KEY_COMPOSITION_RELEASE); + + E_KEYROUTER_EVENT_KEY_LONG = 0; + E_KEYROUTER_EVENT_KEY_COMPOSITION_PRESS = 0; + E_KEYROUTER_EVENT_KEY_COMPOSITION_RELEASE = 0; + + if (krt->composition_key.waiting_timer) + { + ecore_timer_del(krt->composition_key.waiting_timer); + krt->composition_key.waiting_timer = NULL; + } + if (krt->longkey.timer) + { + ecore_timer_del(krt->longkey.timer); + krt->longkey.timer = NULL; + } + e_keyrouter_wl_shutdown(); E_FREE(krt); diff --git a/src/bin/e_keyrouter.h b/src/bin/e_keyrouter.h index d8b30c5e7b..c6b2a4ff6a 100644 --- a/src/bin/e_keyrouter.h +++ b/src/bin/e_keyrouter.h @@ -9,6 +9,9 @@ typedef struct _E_Keyrouter_Grabbed_Key E_Keyrouter_Grabbed_Key; typedef struct _E_Keyrouter_Registered_Window_Info E_Keyrouter_Registered_Window_Info; typedef struct _E_Keyrouter_Event_Data E_Keyrouter_Event_Data; +typedef struct _E_Keyrouter_Event_Key_Long E_Keyrouter_Event_Key_Long; +typedef struct _E_Keyrouter_Event_Key_Composition E_Keyrouter_Event_Key_Composition; + typedef enum _E_Keyrouter_Intercept_Hook_Point { E_KEYROUTER_INTERCEPT_HOOK_BEFORE_KEYROUTING, @@ -31,6 +34,10 @@ typedef Eina_Bool (*E_Keyrouter_Intercept_Hook_Cb) (void *data, int type, Ecore_ extern E_API E_Keyrouter_Info e_keyrouter; +extern E_API int E_KEYROUTER_EVENT_KEY_LONG; +extern E_API int E_KEYROUTER_EVENT_KEY_COMPOSITION_PRESS; +extern E_API int E_KEYROUTER_EVENT_KEY_COMPOSITION_RELEASE; + struct _E_Keyrouter_Intercept_Hook { EINA_INLIST; @@ -75,6 +82,14 @@ struct _E_Keyrouter_Grabbed_Key Eina_Bool no_privcheck; Eina_Bool repeat; + struct + { + Eina_Bool enabled; + double time; + } longkey; + + Eina_List *composition_key_list; + Eina_List *excl_ptr; Eina_List *or_excl_ptr; Eina_List *top_ptr; @@ -95,6 +110,21 @@ struct _E_Keyrouter_Event_Data void *data; }; +struct _E_Keyrouter_Event_Key_Long +{ + int keycode; + + void *data; +}; + +struct _E_Keyrouter_Event_Key_Composition +{ + int keys[2]; + unsigned int timestamp; + + void *data; +}; + E_API E_Keyrouter_Intercept_Hook *e_keyrouter_intercept_hook_add(E_Keyrouter_Intercept_Hook_Point hookpoint, E_Keyrouter_Intercept_Hook_Cb func, const void *data); E_API void e_keyrouter_intercept_hook_del(E_Keyrouter_Intercept_Hook *ch); E_API Eina_Bool e_keyrouter_intercept_hook_call(E_Keyrouter_Intercept_Hook_Point hookpoint, int type, Ecore_Event_Key *event); @@ -102,6 +132,10 @@ E_API Eina_Bool e_keyrouter_intercept_hook_call(E_Keyrouter_Intercept_Hook_Point E_API int e_keyrouter_init(void); E_API int e_keyrouter_shutdown(void); +E_API int e_keyrouter_longkey_add(int keycode, double time); +E_API void e_keyrouter_longkey_del(int keycode); +E_API int e_keyrouter_composition_key_add(int *keys, int count); +E_API void e_keyrouter_composition_key_del(int *keys, int count); #endif #endif diff --git a/src/bin/e_keyrouter_conf.c b/src/bin/e_keyrouter_conf.c index 4de89dae60..8e4b7be4a8 100644 --- a/src/bin/e_keyrouter_conf.c +++ b/src/bin/e_keyrouter_conf.c @@ -22,6 +22,7 @@ e_keyrouter_conf_init(E_Keyrouter_Config_Data *kconfig) E_CONFIG_VAL(D, T, num_keycode, INT); E_CONFIG_VAL(D, T, max_keycode, INT); E_CONFIG_VAL(D, T, pictureoff_disabled, INT); + E_CONFIG_VAL(D, T, composition_key_wait_time, DOUBLE); E_CONFIG_LIST(D, T, KeyList, kconfig->conf_hwkeys_edd); #undef T @@ -30,7 +31,11 @@ e_keyrouter_conf_init(E_Keyrouter_Config_Data *kconfig) if (!kconfig->conf) { - KLDBG("Failed to find module.keyrouter config file."); + KLWRN("Failed to find module.keyrouter config file."); + } + else if (!kconfig->conf->composition_key_wait_time) + { + kconfig->conf->composition_key_wait_time = 0.3; } } diff --git a/src/bin/e_keyrouter_events.c b/src/bin/e_keyrouter_events.c index 65b8f6f340..28afc57eda 100644 --- a/src/bin/e_keyrouter_events.c +++ b/src/bin/e_keyrouter_events.c @@ -69,6 +69,330 @@ _e_keyrouter_event_routed_key_check(Ecore_Event_Key *ev, int type) return EINA_TRUE; } +static void +_e_keyrouter_key_free(Ecore_Event_Key *ev) +{ + if (!ev) return; + + eina_stringshare_del(ev->keyname); + eina_stringshare_del(ev->key); + eina_stringshare_del(ev->string); + eina_stringshare_del(ev->compose); + + if (ev->data) E_FREE(ev->data); + if (ev->dev) ecore_device_unref(ev->dev); + + E_FREE(ev); +} + +static Ecore_Event_Key * +_e_keyrouter_key_create(char *keyname) +{ + Ecore_Event_Key *ev_key; + E_Keyrouter_Event_Data *key_data; + int keycode; + + EINA_SAFETY_ON_NULL_RETURN_VAL(keyname, NULL); + + ev_key = E_NEW(Ecore_Event_Key, 1); + EINA_SAFETY_ON_NULL_RETURN_VAL(ev_key, NULL); + + key_data = E_NEW(E_Keyrouter_Event_Data, 1); + EINA_SAFETY_ON_NULL_GOTO(key_data, failed); + + keycode = e_keyrouter_util_keycode_get_from_string(keyname); + EINA_SAFETY_ON_FALSE_GOTO((0 < keycode && keycode <= krt->max_tizen_hwkeys), failed); + + ev_key->key = (char *)eina_stringshare_add(keyname); + ev_key->keyname = (char *)eina_stringshare_add(ev_key->key); + ev_key->compose = (char *)eina_stringshare_add(ev_key->key); + ev_key->timestamp = (int)(ecore_time_get()*1000); + ev_key->same_screen = 1; + + ev_key->window = e_comp->ee_win; + ev_key->event_window = e_comp->ee_win; + ev_key->root_window = e_comp->ee_win; + ev_key->keycode = keycode; + ev_key->data = key_data; + + return ev_key; + +failed: + if (ev_key) E_FREE(ev_key); + if (key_data) E_FREE(key_data); + return NULL; +} + +static void +_e_keyrouter_key_send(int type, Ecore_Event_Key *ev, E_Keyrouter_Key_List_NodePtr key_node) +{ + Eina_Bool res_hook = EINA_TRUE; + E_Keyrouter_Event_Data *key_data = NULL; + + if (key_node->focused) + { + res_hook = e_keyrouter_intercept_hook_call(E_KEYROUTER_INTERCEPT_HOOK_DELIVER_FOCUS, type, ev); + key_data = (E_Keyrouter_Event_Data *)ev->data; + + if (!res_hook || key_data->ignored) + { + KLINF("This hook is called to notify a current key is cancel. Please check why hook returns FALSE or ignored.\n"); + } + } + e_keyrouter_wl_key_send(ev, (type == ECORE_EVENT_KEY_DOWN)?EINA_TRUE:EINA_FALSE, + key_node->wc, key_node->surface, key_node->focused); +} + +static void +_e_keyrouter_key_cancel(int keycode) +{ + Ecore_Event_Key *key_cancel, *key_release; + Eina_List *l; + char *keyname; + E_Keyrouter_Key_List_NodePtr key_node_data; + int pid = 0; + char *pname = NULL, *cmd = NULL; + + key_cancel = _e_keyrouter_key_create("Cancel"); + EINA_SAFETY_ON_NULL_RETURN(key_cancel); + + keyname = e_keyrouter_util_keyname_get_from_keycode(keycode); + key_release = _e_keyrouter_key_create(keyname); + EINA_SAFETY_ON_NULL_GOTO(key_release, failed); + + EINA_LIST_FOREACH(krt->HardKeys[keycode].press_ptr, l, key_node_data) + { + _e_keyrouter_key_send(ECORE_EVENT_KEY_DOWN, key_cancel, key_node_data); + _e_keyrouter_key_send(ECORE_EVENT_KEY_UP, key_release, key_node_data); + _e_keyrouter_key_send(ECORE_EVENT_KEY_UP, key_cancel, key_node_data); + + pid = e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface); + cmd = e_keyrouter_util_cmd_get_from_pid(pid); + pname = e_keyrouter_util_process_name_get_from_cmd(cmd); + KLINF("CANCEL : => wl_surface (%p) wl_client (%p) (pid: %d) (pname: %s)", + key_node_data->surface, key_node_data->wc, pid, pname ?: "Unknown"); + if(pname) E_FREE(pname); + if(cmd) E_FREE(cmd); + } + + _e_keyrouter_key_free(key_cancel); + _e_keyrouter_key_free(key_release); + + return; + +failed: + if (key_cancel) _e_keyrouter_key_free(key_cancel); +} + + +static Eina_Bool +_e_keyrouter_long_timer(void *data) +{ + E_Keyrouter_Event_Key_Long *ev; + + ev = E_NEW(E_Keyrouter_Event_Key_Long, 1); + if (!ev) + { + krt->longkey.timer = NULL; + krt->longkey.key = 0; + + return ECORE_CALLBACK_CANCEL; + } + + ev->keycode = krt->longkey.key; + + _e_keyrouter_key_cancel(krt->longkey.key); + ecore_event_add(E_KEYROUTER_EVENT_KEY_LONG, ev, NULL, NULL); + + KLINF("LONGKEY : %s(%d) long press event is generated.\n", + e_keyrouter_util_keyname_get_from_keycode(krt->longkey.key), krt->longkey.key); + + krt->longkey.timer = NULL; + + /* Cancel a longkey to prevent irregal operation */ + if (krt->composition_key.waiting_timer) + { + ecore_timer_del(krt->composition_key.waiting_timer); + krt->composition_key.waiting_timer = NULL; + krt->composition_key.key[0] = 0; + krt->composition_key.key[1] = 0; + } + + return ECORE_CALLBACK_CANCEL; +} + +static Eina_Bool +_e_keyrouter_long_check(int type, Ecore_Event_Key *ev) +{ + if (type == ECORE_EVENT_KEY_DOWN) + { + if (krt->longkey.timer || krt->longkey.key) + { + KLDBG("Already long pressed key(%d) is exist\n", krt->longkey.key); + } + else if (krt->HardKeys[ev->keycode].longkey.enabled) + { + krt->longkey.timer = ecore_timer_add(krt->HardKeys[ev->keycode].longkey.time, _e_keyrouter_long_timer, NULL); + krt->longkey.key = ev->keycode; + } + } + else + { + if (!krt->longkey.timer) + { + /* Already process a long press key. So ignore a long pressed key's release event */ + if (krt->longkey.key && krt->longkey.key == ev->keycode) + { + krt->longkey.key = 0; + return ECORE_CALLBACK_DONE; + } + /* just a short press key event */ + return ECORE_CALLBACK_PASS_ON; + } + + /* Current key event is a short press, so cancel a long press timer. */ + if (krt->longkey.key == ev->keycode) + { + ecore_timer_del(krt->longkey.timer); + krt->longkey.timer = NULL; + krt->longkey.key = 0; + } + } + + return ECORE_CALLBACK_PASS_ON; +} + +static void +_e_keyrouter_composition_key_event(Eina_Bool pressed) +{ + E_Keyrouter_Event_Key_Composition *ev = NULL; + + ev = E_NEW(E_Keyrouter_Event_Key_Composition, 1); + EINA_SAFETY_ON_NULL_RETURN(ev); + + ev->keys[0] = krt->composition_key.key[0]; + ev->keys[1] = krt->composition_key.key[1]; + + ev->timestamp = (unsigned int)(ecore_time_get()*1000); + + KLINF("COMPOSITION_KEY : %s(%d) and %s(%d) composition key %s event is generated (time: %d).\n", + e_keyrouter_util_keyname_get_from_keycode(ev->keys[0]), ev->keys[0], + e_keyrouter_util_keyname_get_from_keycode(ev->keys[1]), ev->keys[1], + pressed?"press":"release", ev->timestamp); + + if (pressed) + ecore_event_add(E_KEYROUTER_EVENT_KEY_COMPOSITION_PRESS, ev, NULL, NULL); + else + ecore_event_add(E_KEYROUTER_EVENT_KEY_COMPOSITION_RELEASE, ev, NULL, NULL); +} + +static Eina_Bool +_e_keyrouter_composition_key_timer(void *data) +{ + krt->composition_key.key[0] = 0; + krt->composition_key.key[1] = 0; + + krt->composition_key.waiting_timer = NULL; + + return ECORE_CALLBACK_CANCEL; +} + +static Eina_Bool +_e_keyrouter_composition_key_check(int type, Ecore_Event_Key *ev) +{ + Eina_List *l; + int *wait_key_data; + + if (type == ECORE_EVENT_KEY_DOWN) + { + if (krt->composition_key.waiting_timer) + { + /* Find modkey */ + EINA_LIST_FOREACH(krt->HardKeys[krt->composition_key.key[0]].composition_key_list, l, wait_key_data) + { + if (*wait_key_data == ev->keycode) + { + krt->composition_key.key[1] = ev->keycode; + + ecore_timer_del(krt->composition_key.waiting_timer); + krt->composition_key.waiting_timer = NULL; + + /* Cancel a longkey to prevent irregal operation */ + if (krt->longkey.timer) + { + ecore_timer_del(krt->longkey.timer); + krt->longkey.timer = NULL; + krt->longkey.key = 0; + } + + _e_keyrouter_key_cancel(krt->composition_key.key[0]); + _e_keyrouter_composition_key_event(EINA_TRUE); + + return ECORE_CALLBACK_DONE; + } + } + + /* Not modkey is pressed, cancel current modkey process */ + if (krt->composition_key.waiting_timer) + { + ecore_timer_del(krt->composition_key.waiting_timer); + krt->composition_key.waiting_timer = NULL; + krt->composition_key.key[0] = 0; + krt->composition_key.key[1] = 0; + } + } + else if (!krt->composition_key.key[0] && !krt->composition_key.key[1]) + { + if (eina_list_count(krt->HardKeys[ev->keycode].composition_key_list) > 0) + { + krt->composition_key.key[0] = ev->keycode; + krt->composition_key.waiting_timer = ecore_timer_add(krt->composition_key.waiting_time, _e_keyrouter_composition_key_timer, NULL); + } + } + } + else + { + if (!krt->composition_key.waiting_timer) + { + /* Already send modkey press and modkey release event is came. */ + if ((krt->composition_key.key[0] == ev->keycode) || + (krt->composition_key.key[1] == ev->keycode)) + { + /* send modkey release event */ + if (krt->composition_key.key[0] && krt->composition_key.key[1]) + { + _e_keyrouter_composition_key_event(EINA_FALSE); + } + + if (krt->composition_key.key[0] == ev->keycode) + { + krt->composition_key.key[0] = 0; + } + else + { + krt->composition_key.key[1] = 0; + } + return ECORE_CALLBACK_DONE; + } + /* Modkey is not yet pressed */ + return ECORE_CALLBACK_PASS_ON; + } + + /* Not modkey, just key short press */ + if (krt->composition_key.key[0] == ev->keycode) + { + ecore_timer_del(krt->composition_key.waiting_timer); + krt->composition_key.waiting_timer = NULL; + krt->composition_key.key[0] = 0; + + return ECORE_CALLBACK_PASS_ON; + } + } + + return ECORE_CALLBACK_PASS_ON; +} + + /* Function for checking the existing grab for a key and sending key event(s) */ Eina_Bool e_keyrouter_event_process(void *event, int type) @@ -130,11 +454,53 @@ finish: static void _e_keyrouter_send_key_events(int type, Ecore_Event_Key *ev) { + int pid = 0, keycode = 0; + char *pname = NULL, *cmd = NULL; + E_Keyrouter_Key_List_NodePtr key_node_data; + Eina_List *l = NULL; + + keycode = ev->keycode; + + if (krt->isPictureOffEnabled == 1) + { + EINA_LIST_FOREACH(krt->HardKeys[keycode].pic_off_ptr, l, key_node_data) + { + if (key_node_data) + { + _e_keyrouter_send_key_event(type, key_node_data->surface, key_node_data->wc, ev, key_node_data->focused, TIZEN_KEYROUTER_MODE_SHARED); + + pid = e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface); + cmd = e_keyrouter_util_cmd_get_from_pid(pid); + pname = e_keyrouter_util_process_name_get_from_cmd(cmd); + KLINF("PICTURE OFF : %s(%d) => wl_surface (%p) wl_client (%p) (pid: %d) (pname: %s)", + ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keycode, key_node_data->surface, key_node_data->wc, pid, pname ?: "Unknown"); + + if(pname) E_FREE(pname); + if(cmd) E_FREE(cmd); + } + } + return; + } + + if (!_e_keyrouter_composition_key_check(type, ev)) + { + KLINF("Ignore %s(%d) key %s. This key is already processed for composition key.\n", ev->keyname, ev->keycode, ((ECORE_EVENT_KEY_DOWN == type) ? "down" : "up")); + return; + } + + if (!_e_keyrouter_long_check(type, ev)) + { + if (type == ECORE_EVENT_KEY_UP) + KLINF("Ignore %s(%d) key up. This key is already processed for long press.\n", ev->keyname, ev->keycode); + return; + } + + if (ECORE_EVENT_KEY_DOWN == type) { _e_keyrouter_send_key_events_press(type, ev); } - else + else { _e_keyrouter_send_key_events_release(type, ev); } @@ -234,25 +600,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); - if (krt->isPictureOffEnabled == 1) - { - EINA_LIST_FOREACH(krt->HardKeys[keycode].pic_off_ptr, l, key_node_data) - { - if (key_node_data) - { - _e_keyrouter_send_key_event(type, key_node_data->surface, key_node_data->wc, ev, key_node_data->focused, TIZEN_KEYROUTER_MODE_SHARED); - - pid = e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface); - cmd = e_keyrouter_util_cmd_get_from_pid(pid); - pname = e_keyrouter_util_process_name_get_from_cmd(cmd); - KLINF("PICTURE OFF : %s(%d) => wl_surface (%p) wl_client (%p) (pid: %d) (pname: %s)", - ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keycode, key_node_data->surface, key_node_data->wc, pid, pname ?: "Unknown"); - if(pname) E_FREE(pname); - if(cmd) E_FREE(cmd); - } - } - return; - } if (!_e_keyrouter_is_key_grabbed(ev->keycode)) { _e_keyrouter_send_key_events_focus(type, surface_focus, ev, &delivered_surface); diff --git a/src/bin/e_keyrouter_private.h b/src/bin/e_keyrouter_private.h index 179af59822..0cb0e162f1 100644 --- a/src/bin/e_keyrouter_private.h +++ b/src/bin/e_keyrouter_private.h @@ -35,10 +35,11 @@ extern E_KeyrouterPtr krt; struct _E_Keyrouter_Conf_Edd { - int num_keycode; // The numbers of keyrouted keycodes defined by xkb-tizen-data - int max_keycode; // The max value of keycodes - int pictureoff_disabled; // To disable picture_off feature. - Eina_List *KeyList; // The list of routed key data: E_Keyrouter_Tizen_HWKey + int num_keycode; // The numbers of keyrouted keycodes defined by xkb-tizen-data + int max_keycode; // The max value of keycodes + int pictureoff_disabled; // To disable picture_off feature. + double composition_key_wait_time; // The time of waiting to composition key's press events + Eina_List *KeyList; // The list of routed key data: E_Keyrouter_Tizen_HWKey }; struct _E_Keyrouter_Config_Data @@ -70,6 +71,19 @@ struct _E_Keyrouter #endif int isPictureOffEnabled; Eina_Bool pictureoff_disabled; + + struct + { + Ecore_Timer *waiting_timer; + double waiting_time; + + int key[2]; + } composition_key; + struct + { + Ecore_Timer *timer; + int key; + } longkey; }; struct _E_Keyrouter_Grab_Request {