src/bin/e_privilege.h \
src/bin/e_security.h \
src/bin/e_keyrouter.h \
+src/bin/e_keyrouter_private.h \
src/bin/e_gesture.h \
src/bin/e_input.h
src/bin/e_process.c \
src/bin/e_privilege.c \
src/bin/e_security.c \
+src/bin/e_keyrouter_events.c \
+src/bin/e_keyrouter_list.c \
+src/bin/e_keyrouter_conf.c \
+src/bin/e_keyrouter_wl.c \
src/bin/e_keyrouter.c \
src/bin/e_gesture.c \
src/bin/e_input_private.h \
;
}
-static Eina_Bool
-_e_comp_cb_key_down(void *data EINA_UNUSED, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
-{
- e_screensaver_notidle();
- return !e_comp_wl_key_down(ev);
-}
-
-static Eina_Bool
-_e_comp_cb_key_up(void *data EINA_UNUSED, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
-{
- e_screensaver_notidle();
- return !e_comp_wl_key_up(ev);
-}
-
////////////////////////////////////
static Eina_Bool
E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_ADD, _e_comp_cb_zone_change, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DEL, _e_comp_cb_zone_change, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMPOSITOR_ENABLE, _e_comp_cb_compositor_enabled, NULL);
- E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_KEY_DOWN, _e_comp_cb_key_down, NULL);
- E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_KEY_UP, _e_comp_cb_key_up, NULL);
ecore_evas_callback_pre_render_set(e_comp->ee, _e_comp_canvas_prerender);
ecore_evas_callback_resize_set(e_comp->ee, _e_comp_canvas_resize);
static int _e_comp_wl_hooks_delete = 0;
static int _e_comp_wl_hooks_walking = 0;
-static Eina_Hash *_last_keydev_hash = NULL;
-
static Eina_Inlist *_e_comp_wl_hooks[] =
{
[E_COMP_WL_HOOK_SHELL_SURFACE_READY] = NULL,
e_comp_wl->wl.gl = NULL;
}
-static void
-_e_comp_wl_client_cb_destroy(struct wl_listener *l, void *data)
-{
- struct wl_client *client = (struct wl_client *)data;
-
- eina_hash_del_by_key(_last_keydev_hash, client);
-
- wl_list_remove(&l->link);
- E_FREE(l);
-}
-
-static void
-_e_comp_wl_client_destroy_listener_add(struct wl_client *client)
-{
- struct wl_listener *destroy_listener;
-
- EINA_SAFETY_ON_NULL_RETURN(client);
- destroy_listener = wl_client_get_destroy_listener(client, _e_comp_wl_client_cb_destroy);
- if (destroy_listener) return;
-
- destroy_listener = E_NEW(struct wl_listener, 1);
- EINA_SAFETY_ON_NULL_RETURN(destroy_listener);
-
- destroy_listener->notify = _e_comp_wl_client_cb_destroy;
- wl_client_add_destroy_listener(client, destroy_listener);
-}
-
-static Eina_Bool
-_e_comp_wl_keydev_hash_free(const Eina_Hash *hash, const void *key, void *data, void *fdata)
-{
- struct wl_listener *destroy_listener;
- struct wl_client *wc;
-
- wc = (struct wl_client *)key;
-
- destroy_listener = wl_client_get_destroy_listener(wc, _e_comp_wl_client_cb_destroy);
-
- if (destroy_listener)
- {
- wl_list_remove(&destroy_listener->link);
- E_FREE(destroy_listener);
- }
-
- return EINA_TRUE;
-}
-
/* public functions */
/**
E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_UNICONIFY, _e_comp_wl_client_cb_uniconify, NULL);
E_EVENT_WAYLAND_GLOBAL_ADD = ecore_event_type_new();
- _last_keydev_hash = eina_hash_pointer_new(NULL);
TRACE_DS_END();
return EINA_TRUE;
#endif
e_comp_wl_remote_surface_shutdown();
- eina_hash_foreach(_last_keydev_hash, _e_comp_wl_keydev_hash_free, NULL);
- eina_hash_free(_last_keydev_hash);
-
e_pixmap_shutdown();
e_comp_wl_shell_shutdown();
}
static void
-_e_comp_wl_key_send(Ecore_Event_Key *ev, enum wl_keyboard_key_state state, Eina_List *key_list, Eina_Bool focused)
+_e_comp_wl_key_send(Ecore_Event_Key *ev, enum wl_keyboard_key_state state, Eina_List *key_list, E_Client *ec)
{
struct wl_resource *res;
Eina_List *l;
uint32_t serial, keycode;
- struct wl_client *wc;
- Ecore_Device *last_dev;
+ struct wl_client *wc = NULL;
E_Comp_Config *comp_conf = NULL;
keycode = (ev->keycode - 8);
comp_conf = e_comp_config_get();
+ if (ec && ec->comp_data && ec->comp_data->surface)
+ wc = wl_resource_get_client(ec->comp_data->surface);
+
EINA_LIST_FOREACH(key_list, l, res)
{
- wc = wl_resource_get_client(res);
- if (!focused && wc != ev->data) continue;
+ if (wl_resource_get_client(res) != wc) continue;
+
TRACE_INPUT_BEGIN(_e_comp_wl_key_send);
- last_dev = eina_hash_find(_last_keydev_hash, wc);
- if (!last_dev)
- {
- _e_comp_wl_client_destroy_listener_add(wc);
- eina_hash_direct_add(_last_keydev_hash, wc, ev->dev);
- _e_comp_wl_send_event_device(ev->data, ev->timestamp, ev->dev, serial);
- }
- else if (last_dev != ev->dev)
- {
- eina_hash_modify(_last_keydev_hash, wc, ev->dev);
- _e_comp_wl_send_event_device(ev->data, ev->timestamp, ev->dev, serial);
- }
+ _e_comp_wl_send_event_device(ev->data, ev->timestamp, ev->dev, serial);
if (comp_conf && comp_conf->input_log_enable)
INF("[Server] Key %s (time: %d)\n", (state ? "Down" : "Up"), ev->timestamp);
e_comp_wl_key_down(Ecore_Event_Key *ev)
{
E_Client *ec = NULL;
- struct wl_client *wc = NULL;
uint32_t keycode;
E_Comp_Wl_Key_Data *end, *k;
}
#endif
- ec = e_client_focused_get();
- if (ec && ec->comp_data && ec->comp_data->surface)
- wc = wl_resource_get_client(ec->comp_data->surface);
-
- if (ev->data)
- {
- if ((wc != ev->data) && (ev->data != (void *)0x1))
- {
- _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_PRESSED, e_comp_wl->kbd.resources, EINA_FALSE);
- }
- else
- {
- ec = NULL;
- end = (E_Comp_Wl_Key_Data *)e_comp_wl->kbd.routed_keys.data + (e_comp_wl->kbd.routed_keys.size / sizeof(*k));
-
- for (k = e_comp_wl->kbd.routed_keys.data; k < end; k++)
- {
- /* ignore server-generated key repeats */
- if (k->key == keycode)
- {
- return EINA_FALSE;
- }
- }
-
- if (ev->data == (void *)0x1) return EINA_FALSE;
-
- if ((!e_client_action_get()) && (!e_comp->input_key_grabs))
- {
- ec = e_client_focused_get();
- if (ec && ec->comp_data && ec->comp_data->surface && e_comp_wl->kbd.focused)
- {
- _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_PRESSED, e_comp_wl->kbd.focused, EINA_TRUE);
-
- /* A key only sent to clients is added to the list */
- e_comp_wl->kbd.routed_keys.size = (const char *)end - (const char *)e_comp_wl->kbd.routed_keys.data;
- if (!(k = wl_array_add(&e_comp_wl->kbd.routed_keys, sizeof(*k))))
- {
- DBG("wl_array_add: Out of memory\n");
- return EINA_FALSE;
- }
- k->key = keycode;
- k->dev = ev->dev;
- }
- }
-
- /* update modifier state */
- e_comp_wl_input_keyboard_state_update(keycode, EINA_TRUE);
- }
-
- return !!ec;
- }
-
- ec = NULL;
-
end = (E_Comp_Wl_Key_Data *)e_comp_wl->kbd.keys.data + (e_comp_wl->kbd.keys.size / sizeof(*k));
for (k = e_comp_wl->kbd.keys.data; k < end; k++)
ec = e_client_focused_get();
if (ec && ec->comp_data && ec->comp_data->surface && e_comp_wl->kbd.focused)
{
- ev->data = wc;
- _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_PRESSED, e_comp_wl->kbd.focused, EINA_TRUE);
+ _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_PRESSED, e_comp_wl->kbd.focused, ec);
/* A key only sent to clients is added to the list */
e_comp_wl->kbd.keys.size = (const char *)end - (const char *)e_comp_wl->kbd.keys.data;
e_comp_wl_key_up(Ecore_Event_Key *ev)
{
E_Client *ec = NULL;
- struct wl_client *wc = NULL;
uint32_t keycode, delivered_key;
E_Comp_Wl_Key_Data *end, *k;
return EINA_FALSE;
}
- ec = e_client_focused_get();
-
- if (ec && ec->comp_data && ec->comp_data->surface)
- wc = wl_resource_get_client(ec->comp_data->surface);
-
- if (ev->data)
- {
- end = (E_Comp_Wl_Key_Data *)e_comp_wl->kbd.routed_keys.data + (e_comp_wl->kbd.routed_keys.size / sizeof(*k));
- for (k = e_comp_wl->kbd.routed_keys.data; k < end; k++)
- {
- if (k->key == keycode)
- {
- *k = *--end;
- delivered_key = 1;
- }
- }
- e_comp_wl->kbd.routed_keys.size =
- (const char *)end - (const char *)e_comp_wl->kbd.routed_keys.data;
-
- if (wc != ev->data)
- {
- _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_RELEASED, e_comp_wl->kbd.resources, EINA_FALSE);
- }
- else
- {
- ec = NULL;
-
- if ((delivered_key) ||
- ((!e_client_action_get()) && (!e_comp->input_key_grabs)))
- {
- ec = e_client_focused_get();
-
- if (e_comp_wl->kbd.focused)
- {
- _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_RELEASED, e_comp_wl->kbd.focused, EINA_FALSE);
- }
- }
-
- /* update modifier state */
- e_comp_wl_input_keyboard_state_update(keycode, EINA_FALSE);
- }
- return !!ec;
- }
-
- ec = NULL;
-
end = (E_Comp_Wl_Key_Data *)e_comp_wl->kbd.keys.data + (e_comp_wl->kbd.keys.size / sizeof(*k));
for (k = e_comp_wl->kbd.keys.data; k < end; k++)
{
if (e_comp_wl->kbd.focused)
{
- ev->data = wc;
- _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_RELEASED, e_comp_wl->kbd.focused, EINA_TRUE);
+ _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_RELEASED, e_comp_wl->kbd.focused, ec);
}
}
}
E_API Eina_Bool
+e_comp_wl_key_process(Ecore_Event_Key *ev, int type)
+{
+ Eina_Bool res = EINA_FALSE;
+
+ if (type == ECORE_EVENT_KEY_DOWN)
+ {
+ res = e_comp_wl_key_down(ev);
+ }
+ else if (type == ECORE_EVENT_KEY_UP)
+ {
+ res = e_comp_wl_key_up(ev);
+ }
+
+ return res;
+}
+
+E_API Eina_Bool
e_comp_wl_evas_handle_mouse_button(E_Client *ec, uint32_t timestamp, uint32_t button_id, uint32_t state)
{
Eina_List *l;
EINTERN Eina_Bool e_comp_wl_mouse_out_send(E_Client *ec, Ecore_Device *dev, uint32_t time);
EINTERN void e_comp_wl_mouse_in_renew(E_Client *ec, int buttons, int x, int y, void *data, Evas_Modifier *modifiers, Evas_Lock *locks, unsigned int timestamp, Evas_Event_Flags event_flags, Evas_Device *dev, Evas_Object *event_src);
EINTERN void e_comp_wl_mouse_out_renew(E_Client *ec, int buttons, int x, int y, void *data, Evas_Modifier *modifiers, Evas_Lock *locks, unsigned int timestamp, Evas_Event_Flags event_flags, Evas_Device *dev, Evas_Object *event_src);
+E_API Eina_Bool e_comp_wl_key_process(Ecore_Event_Key *ev, int type);
EINTERN Eina_Bool e_comp_wl_cursor_hide(E_Client *ec);
#include "e.h"
#include "e_keyrouter.h"
+#include "e_keyrouter_private.h"
static int _e_keyrouter_intercept_hooks_delete = 0;
static int _e_keyrouter_intercept_hooks_walking = 0;
[E_KEYROUTER_INTERCEPT_HOOK_DELIVER_FOCUS] = NULL,
};
+int _keyrouter_log_dom = -1;
+
E_API E_Keyrouter_Info e_keyrouter;
+E_KeyrouterPtr krt;
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)
return res;
}
+
+static void
+_e_keyrouter_keygrab_status_print(FILE *log_fl, Eina_List *list)
+{
+ Eina_List *l;
+ E_Keyrouter_Key_List_NodePtr kdata;
+ int pid;
+ char *cmd;
+
+ EINA_LIST_FOREACH(list, l, kdata)
+ {
+ pid = e_keyrouter_util_get_pid(kdata->wc, kdata->surface);
+ cmd = e_keyrouter_util_cmd_get_from_pid(pid);
+ fprintf(log_fl, " [surface: %p, client: %p, pid: %d(%s)]\n", kdata->surface, kdata->wc, pid, cmd ?: "Unknown");
+ if(cmd) E_FREE(cmd);
+ if (kdata->surface)
+ {
+ fprintf(log_fl, " -- Surface Information --\n");
+ fprintf(log_fl, " = client: %p\n", wl_resource_get_client(kdata->surface));
+ fprintf(log_fl, " = resource: %s(%d)\n", wl_resource_get_class(kdata->surface), wl_resource_get_id(kdata->surface));
+ }
+ else
+ {
+ fprintf(log_fl, " -- Client Information --\n");
+ fprintf(log_fl, " = connected fd: %d\n", wl_client_get_fd(kdata->wc));
+ }
+ }
+}
+
+static void
+_e_keyrouter_info_print(void *data, const char *log_path)
+{
+ char *keyname;
+ int i;
+ FILE *log_fl;
+
+ log_fl = fopen(log_path, "a");
+ if (!log_fl)
+ {
+ KLERR("failed: open file(%s)", log_path);
+ return;
+ }
+
+ setvbuf(log_fl, NULL, _IOLBF, 512);
+
+ fprintf(log_fl, "\n===== Keyrouter Information =====\n");
+ fprintf(log_fl, " ----- Grabbable Keys -----\n");
+ for (i = 8; i <= krt->max_tizen_hwkeys; i++)
+ {
+ if (!krt->HardKeys[i].keycode) continue;
+
+ keyname = e_keyrouter_util_keyname_get_from_keycode(i);
+
+ fprintf(log_fl, " Key [%3d], Keyname: %s\n", i, keyname);
+
+ free(keyname);
+ keyname = NULL;
+ }
+ fprintf(log_fl, " ----- End -----\n\n");
+
+ fclose(log_fl);
+ log_fl = NULL;
+}
+
+static void
+_e_keyrouter_keygrab_print(void *data, const char *log_path)
+{
+ Eina_List *l;
+ E_Keyrouter_Key_List_NodePtr kdata;
+ E_Client *ec_focus;
+ struct wl_resource *surface_focus;
+ struct wl_client *wc_focus;
+ int pid_focus, pid, i;
+ char *cmd_focus, *cmd, *keyname;
+ FILE *log_fl;
+
+ (void) data;
+
+ log_fl = fopen(log_path, "a");
+ if (!log_fl)
+ {
+ KLERR("failed: open file(%s)", log_path);
+ return;
+ }
+
+ setvbuf(log_fl, NULL, _IOLBF, 512);
+
+ fprintf(log_fl, "\n===== Keygrab Status =====\n");
+
+ ec_focus = e_client_focused_get();
+ fprintf(log_fl, " ----- Focus Window Info -----\n");
+ if (ec_focus)
+ {
+ surface_focus = e_keyrouter_util_get_surface_from_eclient(ec_focus);
+ wc_focus = wl_resource_get_client(surface_focus);
+ pid_focus = e_keyrouter_util_get_pid(NULL, surface_focus);
+ cmd_focus = e_keyrouter_util_cmd_get_from_pid(pid_focus);
+
+ fprintf(log_fl, " Focus Client: E_Client: %p\n", ec_focus);
+ fprintf(log_fl, " Surface: %p, Client: %p\n", surface_focus, wc_focus);
+ fprintf(log_fl, " pid: %d, cmd: %s\n", pid_focus, cmd_focus ?: "Unknown");
+ if(cmd_focus) E_FREE(cmd_focus);
+ }
+ else
+ {
+ fprintf(log_fl, " No Focus Client\n");
+ }
+ fprintf(log_fl, " ----- End -----\n\n");
+
+ fprintf(log_fl, " ----- Grabbed keys Info -----\n\n");
+ for (i = 8; i <= krt->max_tizen_hwkeys; i++)
+ {
+ if (!krt->HardKeys[i].keycode) continue;
+ if (!krt->HardKeys[i].excl_ptr &&
+ !krt->HardKeys[i].or_excl_ptr &&
+ !krt->HardKeys[i].top_ptr &&
+ !krt->HardKeys[i].shared_ptr)
+ continue;
+
+ keyname = e_keyrouter_util_keyname_get_from_keycode(i);
+
+ fprintf(log_fl, " [ Keycode: %d, Keyname: %s ]\n", i, keyname);
+
+ free(keyname);
+ keyname = NULL;
+
+ if (krt->HardKeys[i].excl_ptr)
+ {
+ fprintf(log_fl, " == Exclusive Grab ==\n");
+ EINA_LIST_FOREACH(krt->HardKeys[i].excl_ptr, l, kdata)
+ {
+ pid = e_keyrouter_util_get_pid(kdata->wc, kdata->surface);
+ cmd = e_keyrouter_util_cmd_get_from_pid(pid);
+ fprintf(log_fl, " [surface: %p, client: %p, pid: %d(%s)]\n", kdata->surface, kdata->wc, pid, cmd ?: "Unknown");
+ if(cmd) E_FREE(cmd);
+ if (kdata->surface)
+ {
+ fprintf(log_fl, " -- Surface Information --\n");
+ fprintf(log_fl, " = wl_client: %p\n", wl_resource_get_client(kdata->surface));
+ fprintf(log_fl, " = resource: %s(%d)\n", wl_resource_get_class(kdata->surface), wl_resource_get_id(kdata->surface));
+ }
+ else
+ {
+ fprintf(log_fl, " -- Client Information --\n");
+ fprintf(log_fl, " = connected fd: %d\n", wl_client_get_fd(kdata->wc));
+ }
+ }
+ }
+
+ if (krt->HardKeys[i].or_excl_ptr)
+ {
+ fprintf(log_fl, " == Overidable Exclusive Grab ==\n");
+ _e_keyrouter_keygrab_status_print(log_fl, krt->HardKeys[i].or_excl_ptr);
+ }
+
+ if (krt->HardKeys[i].top_ptr)
+ {
+ fprintf(log_fl, " == Top Position Grab ==\n");
+ _e_keyrouter_keygrab_status_print(log_fl, krt->HardKeys[i].top_ptr);
+ }
+
+ if (krt->HardKeys[i].shared_ptr)
+ {
+ fprintf(log_fl, " == Shared Grab ==\n");
+ _e_keyrouter_keygrab_status_print(log_fl, krt->HardKeys[i].shared_ptr);
+ }
+
+ fprintf(log_fl, "\n");
+ }
+
+ fprintf(log_fl, " ----- End -----\n\n");
+
+ fclose(log_fl);
+ log_fl = NULL;
+}
+
+static Eina_Bool
+_e_keyrouter_cb_key_down(void *data, int type, void *event)
+{
+ Ecore_Event_Key *ev;
+ Eina_Bool res = ECORE_CALLBACK_PASS_ON;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(event, ECORE_CALLBACK_PASS_ON);
+
+ ev = (Ecore_Event_Key *)event;
+
+ TRACE_INPUT_BEGIN(_e_keyrouter_cb_key_down:KEY_PRESS(%d), ev->keycode);
+ TRACE_INPUT_END();
+
+ res = e_keyrouter_event_process(event, type);
+
+ return res;
+}
+
+static Eina_Bool
+_e_keyrouter_cb_key_up(void *data, int type, void *event)
+{
+ Ecore_Event_Key *ev;
+ Eina_Bool res = ECORE_CALLBACK_PASS_ON;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(event, ECORE_CALLBACK_PASS_ON);
+
+ ev = (Ecore_Event_Key *)event;
+
+ TRACE_INPUT_BEGIN(_e_keyrouter_cb_key_down:KEY_RELEASE(%d), ev->keycode);
+ TRACE_INPUT_END();
+
+ res = e_keyrouter_event_process(event, type);
+
+ return res;
+}
+
+static Eina_Bool
+_e_keyrouter_client_cb_stack(void *data, int type, void *event)
+{
+ E_Event_Client *ev = event;
+ E_Client *ec = ev->ec;
+
+ (void) data;
+ (void) type;
+ (void) event;
+ (void) ev;
+ (void) ec;
+
+ //KLDBG("ec: %p, visibile: %d, focused: %d, take_focus: %d, want_focus: %d, bordername: %s, input_only: %d",
+ // ec, ec->visible, ec->focused, ec->take_focus, ec->want_focus, ec->bordername, ec->input_only);
+
+ krt->isWindowStackChanged = EINA_TRUE;
+
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_keyrouter_client_cb_remove(void *data, int type, void *event)
+{
+ E_Event_Client *ev = event;
+ E_Client *ec = ev->ec;
+
+ (void) data;
+ (void) type;
+ (void) ev;
+ (void) ec;
+
+ /* FIXME: Remove this callback or do something others.
+ * It was moved to _e_keyrouter_wl_surface_cb_destroy() where it had here.
+ */
+
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_e_keyrouter_init_handlers(void)
+{
+ E_LIST_HANDLER_APPEND(krt->handlers, E_EVENT_CLIENT_STACK, _e_keyrouter_client_cb_stack, NULL);
+ E_LIST_HANDLER_APPEND(krt->handlers, E_EVENT_CLIENT_REMOVE, _e_keyrouter_client_cb_remove, NULL);
+ E_LIST_HANDLER_APPEND(krt->handlers, ECORE_EVENT_KEY_DOWN, _e_keyrouter_cb_key_down, NULL);
+ E_LIST_HANDLER_APPEND(krt->handlers, ECORE_EVENT_KEY_UP, _e_keyrouter_cb_key_up, NULL);
+
+ e_info_server_hook_set("keyrouter", _e_keyrouter_info_print, NULL);
+ e_info_server_hook_set("keygrab", _e_keyrouter_keygrab_print, NULL);
+}
+
+static void
+_e_keyrouter_deinit_handlers(void)
+{
+ Ecore_Event_Handler *h = NULL;
+
+ if (!krt || !krt->handlers) return;
+
+ EINA_LIST_FREE(krt->handlers, h)
+ ecore_event_handler_del(h);
+
+ e_info_server_hook_set("keyrouter", NULL, NULL);
+ e_info_server_hook_set("keygrab", NULL, NULL);
+}
+
+static Eina_Bool
+_e_keyrouter_query_tizen_key_table(void)
+{
+ E_Keyrouter_Conf_Edd *kconf = krt->conf->conf;
+ Eina_List *l;
+ E_Keyrouter_Tizen_HWKey *data;
+ int res;
+ struct xkb_rule_names names={0,};
+
+ /* TODO: Make struct in HardKeys to pointer.
+ If a key is defined, allocate memory to pointer,
+ that makes to save unnecessary memory */
+ krt->HardKeys = E_NEW(E_Keyrouter_Grabbed_Key, kconf->max_keycode + 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(krt->HardKeys, EINA_FALSE);
+
+ krt->numTizenHWKeys = kconf->num_keycode;
+ krt->max_tizen_hwkeys = kconf->max_keycode;
+
+ EINA_LIST_FOREACH(kconf->KeyList, l, data)
+ {
+ if (!data) continue;
+
+ if (0 > data->keycode || krt->max_tizen_hwkeys < data->keycode)
+ {
+ KLWRN("Given keycode(%d) is invalid. It must be bigger than zero, smaller than the maximum value(%d) or equal to it.", data->keycode, kconf->max_keycode);
+ continue;
+ }
+
+ KLINF("[jeon] keycode: %d, name: %s, no_priv: %d, repeat: %d\n", data->keycode, data->name, data->no_privcheck, data->repeat);
+
+ krt->HardKeys[data->keycode].keycode = data->keycode;
+ krt->HardKeys[data->keycode].keyname = (char *)eina_stringshare_add(data->name);
+ krt->HardKeys[data->keycode].no_privcheck = data->no_privcheck ? EINA_TRUE : EINA_FALSE;
+ krt->HardKeys[data->keycode].repeat = data->repeat ? EINA_TRUE : EINA_FALSE;
+
+ if (e_comp_wl_input_keymap_cache_file_use_get() == EINA_FALSE)
+ {
+ if (krt->HardKeys[data->keycode].repeat == EINA_FALSE)
+ {
+ res = xkb_keymap_key_set_repeats(e_comp_wl->xkb.keymap, data->keycode, 0);
+ if (!res)
+ {
+ KLWRN("Failed to set repeat key(%d), value(%d)", data->keycode, 0);
+ }
+ }
+ }
+ }
+
+ if (e_comp_wl_input_keymap_cache_file_use_get() == EINA_FALSE)
+ {
+ KLINF("Server create a new cache file: %s", e_comp_wl_input_keymap_path_get(names));
+ res = unlink(e_comp_wl_input_keymap_path_get(names));
+
+ e_comp_wl_input_keymap_set(NULL, NULL, NULL, NULL, NULL, xkb_context_ref(e_comp_wl->xkb.context), xkb_keymap_ref(e_comp_wl->xkb.keymap));
+ }
+ else
+ KLINF("Currently cache file is exist. Do not change it.");
+
+ return EINA_TRUE;
+}
+
+static void *
+_e_keyrouter_keygrab_list_get(void)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(krt, NULL);
+ return krt->HardKeys;
+}
+
+static int
+_e_keyrouter_max_keycode_get(void)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(krt, 0);
+ return krt->max_tizen_hwkeys;
+}
+
+E_API int
+e_keyrouter_init(void)
+{
+ E_Keyrouter_Config_Data *kconfig = NULL;
+ Eina_Bool res = EINA_FALSE;
+
+ TRACE_INPUT_BEGIN(e_keyrouter_init);
+
+ EINA_SAFETY_ON_NULL_GOTO(e_comp, err);
+
+ _keyrouter_log_dom = eina_log_domain_register("e-keyrouter", EINA_COLOR_RED);
+ EINA_SAFETY_ON_FALSE_GOTO(_keyrouter_log_dom >= 0, err);
+ eina_log_domain_level_set("e-keyrouter", EINA_LOG_LEVEL_INFO);
+
+ krt = E_NEW(E_Keyrouter, 1);
+ EINA_SAFETY_ON_NULL_GOTO(krt, err);
+
+ kconfig = E_NEW(E_Keyrouter_Config_Data, 1);
+ EINA_SAFETY_ON_NULL_GOTO(kconfig, err);
+
+ e_keyrouter_conf_init(kconfig);
+ EINA_SAFETY_ON_NULL_GOTO(kconfig->conf, err);
+ krt->conf = kconfig;
+ krt->pictureoff_disabled = !!kconfig->conf->pictureoff_disabled;
+
+ res = e_keyrouter_wl_init();
+ EINA_SAFETY_ON_FALSE_GOTO(res, err);
+
+ /* Get keyname and keycode pair from Tizen Key Layout file */
+ res = _e_keyrouter_query_tizen_key_table();
+ EINA_SAFETY_ON_FALSE_GOTO(res, err);
+
+ //ecore handler add for power callback registration
+// if (!krt->pictureoff_disabled)
+// ecore_idle_enterer_add(_e_keyrouter_cb_idler, NULL);
+ _e_keyrouter_init_handlers();
+
+ e_keyrouter.keygrab_list_get = _e_keyrouter_keygrab_list_get;
+ e_keyrouter.max_keycode_get = _e_keyrouter_max_keycode_get;
+
+ TRACE_INPUT_END();
+ return EINA_TRUE;
+
+err:
+ if (kconfig)
+ {
+ e_keyrouter_conf_deinit(kconfig);
+ E_FREE(kconfig);
+ }
+ _e_keyrouter_deinit_handlers();
+ e_keyrouter_wl_shutdown();
+ eina_log_domain_unregister(_keyrouter_log_dom);
+ _keyrouter_log_dom = -1;
+ if (krt) E_FREE(krt);
+
+ TRACE_INPUT_END();
+ return EINA_FALSE;
+}
+
+E_API int
+e_keyrouter_shutdown(void)
+{
+ int i;
+ E_Keyrouter_Config_Data *kconfig = krt->conf;
+
+ e_keyrouter_conf_deinit(kconfig);
+ E_FREE(kconfig);
+
+ _e_keyrouter_deinit_handlers();
+
+ for (i = 0; i < krt->max_tizen_hwkeys+1; i++)
+ {
+ if (krt->HardKeys[i].keyname)
+ eina_stringshare_del(krt->HardKeys[i].keyname);
+ }
+ E_FREE(krt->HardKeys);
+
+ e_keyrouter_wl_shutdown();
+
+ E_FREE(krt);
+ /* TODO: free allocated memory */
+
+ eina_log_domain_unregister(_keyrouter_log_dom);
+
+ return EINA_TRUE;
+}
Eina_List *top_ptr;
Eina_List *shared_ptr;
Eina_List *press_ptr;
- E_Keyrouter_Key_List_Node *registered_ptr;
Eina_List *pic_off_ptr;
};
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);
+E_API int e_keyrouter_init(void);
+E_API int e_keyrouter_shutdown(void);
+
+
#endif
#endif
--- /dev/null
+#include "e_keyrouter_private.h"
+
+void
+e_keyrouter_conf_init(E_Keyrouter_Config_Data *kconfig)
+{
+ kconfig->conf_hwkeys_edd= E_CONFIG_DD_NEW("E_Keyrouter_Config_Key",
+ E_Keyrouter_Tizen_HWKey);
+#undef T
+#undef D
+#define T E_Keyrouter_Tizen_HWKey
+#define D kconfig->conf_hwkeys_edd
+ E_CONFIG_VAL(D, T, name, STR);
+ E_CONFIG_VAL(D, T, keycode, INT);
+ E_CONFIG_VAL(D, T, no_privcheck, INT);
+ E_CONFIG_VAL(D, T, repeat, INT);
+
+ kconfig->conf_edd = E_CONFIG_DD_NEW("Keyrouter_Config", E_Keyrouter_Conf_Edd);
+#undef T
+#undef D
+#define T E_Keyrouter_Conf_Edd
+#define D kconfig->conf_edd
+ 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_LIST(D, T, KeyList, kconfig->conf_hwkeys_edd);
+
+#undef T
+#undef D
+ kconfig->conf = e_config_domain_load("module.keyrouter", kconfig->conf_edd);
+
+ if (!kconfig->conf)
+ {
+ KLDBG("Failed to find module.keyrouter config file.");
+ }
+}
+
+void
+e_keyrouter_conf_deinit(E_Keyrouter_Config_Data *kconfig)
+{
+ E_Keyrouter_Tizen_HWKey *kdata;
+
+ if (kconfig->conf)
+ {
+ EINA_LIST_FREE(kconfig->conf->KeyList, kdata)
+ {
+ eina_stringshare_del(kdata->name);
+ free(kdata);
+ }
+ free(kconfig->conf);
+ }
+
+ E_CONFIG_DD_FREE(kconfig->conf_hwkeys_edd);
+ E_CONFIG_DD_FREE(kconfig->conf_edd);
+}
+
--- /dev/null
+#include "e_keyrouter_private.h"
+
+static Eina_Bool _e_keyrouter_send_key_events(int type, Ecore_Event_Key *ev);
+static Eina_Bool _e_keyrouter_send_key_events_press(int type, Ecore_Event_Key *ev);
+static Eina_Bool _e_keyrouter_send_key_events_release(int type, Ecore_Event_Key *ev);
+static 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_focus(int type, struct wl_resource *surface, Ecore_Event_Key *ev, struct wl_resource **delivered_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);
+
+static Eina_Bool
+_e_keyrouter_is_key_grabbed(int key)
+{
+ if (!krt->HardKeys[key].keycode)
+ {
+ return EINA_FALSE;
+ }
+ if (krt->HardKeys[key].excl_ptr ||
+ krt->HardKeys[key].or_excl_ptr ||
+ krt->HardKeys[key].top_ptr ||
+ krt->HardKeys[key].shared_ptr)
+ {
+ return EINA_TRUE;
+ }
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_keyrouter_event_routed_key_check(Ecore_Event_Key *ev, int type)
+{
+ if (ev->data)
+ {
+ KLDBG("data is exist send to compositor: %p", ev->data);
+ return EINA_FALSE;
+ }
+
+ if (ev->modifiers != 0)
+ {
+ KLDBG("Modifier key delivered to Focus window : Key %s(%d)", ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keycode);
+ return EINA_FALSE;
+ }
+
+ if (krt->max_tizen_hwkeys < ev->keycode)
+ {
+ KLWRN("The key(%d) is too larger to process keyrouting: Invalid keycode", ev->keycode);
+ return EINA_FALSE;
+ }
+
+ if (!krt->HardKeys[ev->keycode].keycode) return EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+/* Function for checking the existing grab for a key and sending key event(s) */
+Eina_Bool
+e_keyrouter_event_process(void *event, int type)
+{
+ Eina_Bool res = EINA_FALSE;
+ Ecore_Event_Key *ev = event;
+
+ KLDBG("[%s] keyname: %s, key: %s, keycode: %d", (type == ECORE_EVENT_KEY_DOWN) ? "KEY_PRESS" : "KEY_RELEASE", ev->keyname, ev->key, ev->keycode);
+
+ e_screensaver_notidle();
+
+ if (!_e_keyrouter_event_routed_key_check(event, type))
+ {
+ goto finish;
+ }
+
+ if (!e_keyrouter_intercept_hook_call(E_KEYROUTER_INTERCEPT_HOOK_BEFORE_KEYROUTING, type, ev))
+ {
+ goto finish;
+ }
+
+ if ((ECORE_EVENT_KEY_UP == type) && (!krt->HardKeys[ev->keycode].press_ptr))
+ {
+ KLDBG("The release key(%d) isn't a processed by keyrouter!", ev->keycode);
+ goto finish;
+ }
+
+ //KLDBG("The key(%d) is going to be sent to the proper wl client(s) !", ev->keycode);
+ KLDBG("[%s] keyname: %s, key: %s, keycode: %d", (type == ECORE_EVENT_KEY_DOWN) ? "KEY_PRESS" : "KEY_RELEASE", ev->keyname, ev->key, ev->keycode);
+ res = _e_keyrouter_send_key_events(type, ev);
+ if (res) return EINA_FALSE;
+
+finish:
+ res = e_comp_wl_key_process(event, type);
+ return res;
+}
+
+/* Function for sending key events to wl_client(s) */
+static Eina_Bool
+_e_keyrouter_send_key_events(int type, Ecore_Event_Key *ev)
+{
+ Eina_Bool res;
+ if (ECORE_EVENT_KEY_DOWN == type)
+ {
+ res = _e_keyrouter_send_key_events_press(type, ev);
+ }
+ else
+ {
+ res = _e_keyrouter_send_key_events_release(type, ev);
+ }
+ return res;
+}
+
+static Eina_Bool
+_e_keyrouter_send_key_events_release(int type, Ecore_Event_Key *ev)
+{
+ int pid = 0;
+ char *pname = NULL, *cmd = NULL;
+ E_Keyrouter_Key_List_NodePtr key_node_data;
+ Eina_Bool res = EINA_TRUE, ret = EINA_TRUE;
+
+ /* Deliver release clean up pressed key list */
+ EINA_LIST_FREE(krt->HardKeys[ev->keycode].press_ptr, key_node_data)
+ {
+ if (key_node_data->status == E_KRT_CSTAT_ALIVE)
+ {
+ res = _e_keyrouter_send_key_event(type, key_node_data->surface, key_node_data->wc, ev,
+ key_node_data->focused, TIZEN_KEYROUTER_MODE_PRESSED);
+
+ 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("Release Pair : %s(%s:%d)(Focus: %d)(Status: %d) => wl_surface (%p) wl_client (%p) (pid: %d) (pname: %s)",
+ ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode, key_node_data->focused,
+ key_node_data->status, key_node_data->surface, key_node_data->wc, pid, pname ?: "Unknown");
+ if(pname) E_FREE(pname);
+ if(cmd) E_FREE(cmd);
+ }
+ else
+ {
+ if (key_node_data->focused == EINA_TRUE)
+ {
+ res = EINA_FALSE;
+ if (key_node_data->status == E_KRT_CSTAT_DEAD)
+ {
+ ev->data = key_node_data->wc;
+ }
+ else
+ {
+ ev->data = (void *)0x1;
+ }
+ }
+ KLINF("Release Pair : %s(%s:%d)(Focus: %d)(Status: %d) => wl_surface (%p) wl_client (%p) process is ungrabbed / dead",
+ ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode, key_node_data->focused,
+ key_node_data->status, key_node_data->surface, key_node_data->wc);
+ }
+
+ E_FREE(key_node_data);
+ if (res == EINA_FALSE) ret = EINA_FALSE;
+ }
+ krt->HardKeys[ev->keycode].press_ptr = NULL;
+
+ return ret;
+}
+
+static Eina_Bool
+_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;
+ int pid = 0;
+ char *pname = NULL, *cmd = NULL;
+
+ 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_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 res;
+ }
+ if (!_e_keyrouter_is_key_grabbed(ev->keycode))
+ {
+ return res;
+ }
+
+ EINA_LIST_FOREACH(krt->HardKeys[keycode].excl_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_EXCLUSIVE);
+
+ 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("EXCLUSIVE : %s(%s:%d) => wl_surface (%p) wl_client (%p) (pid: %d) (pname: %s)",
+ ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
+ key_node_data->surface, key_node_data->wc, pid, pname ?: "Unknown");
+ if(pname) E_FREE(pname);
+ if(cmd) E_FREE(cmd);
+ return res;
+ }
+ }
+
+ EINA_LIST_FOREACH(krt->HardKeys[keycode].or_excl_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_OVERRIDABLE_EXCLUSIVE);
+
+ 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("OVERRIDABLE_EXCLUSIVE : %s(%s:%d) => wl_surface (%p) wl_client (%p) (pid: %d) (pname: %s)",
+ ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
+ key_node_data->surface, key_node_data->wc, pid, pname ?: "Unknown");
+ if(pname) E_FREE(pname);
+ if(cmd) E_FREE(cmd);
+
+ return res;
+ }
+ }
+
+ // Top position grab must need a focus surface.
+ if (surface_focus)
+ {
+ EINA_LIST_FOREACH(krt->HardKeys[keycode].top_ptr, l, key_node_data)
+ {
+ if (key_node_data)
+ {
+ if ((EINA_FALSE == krt->isWindowStackChanged) && (surface_focus == key_node_data->surface))
+ {
+ 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);
+
+ res = _e_keyrouter_send_key_event(type, key_node_data->surface, NULL, ev, key_node_data->focused,
+ TIZEN_KEYROUTER_MODE_TOPMOST);
+ KLINF("TOPMOST (TOP_POSITION) : %s (%s:%d) => wl_surface (%p) (pid: %d) (pname: %s)",
+ ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
+ key_node_data->surface, pid, pname ?: "Unknown");
+
+ if(pname) E_FREE(pname);
+ if(cmd) E_FREE(cmd);
+ return res;
+ }
+ krt->isWindowStackChanged = EINA_FALSE;
+
+ if (_e_keyrouter_check_top_visible_window(ec_focus, keycode))
+ {
+ E_Keyrouter_Key_List_NodePtr top_key_node_data = eina_list_data_get(krt->HardKeys[keycode].top_ptr);
+ pid = e_keyrouter_util_get_pid(top_key_node_data->wc, top_key_node_data->surface);
+ cmd = e_keyrouter_util_cmd_get_from_pid(pid);
+ pname = e_keyrouter_util_process_name_get_from_cmd(cmd);
+
+ res = _e_keyrouter_send_key_event(type, top_key_node_data->surface, NULL, ev, top_key_node_data->focused,
+ TIZEN_KEYROUTER_MODE_TOPMOST);
+ KLINF("TOPMOST (TOP_POSITION) : %s (%s:%d) => wl_surface (%p) (pid: %d) (pname: %s)",
+ ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
+ top_key_node_data->surface, pid, pname ?: "Unknown");
+
+ if(pname) E_FREE(pname);
+ if(cmd) E_FREE(cmd);
+ return res;
+ }
+ break;
+ }
+ }
+ goto need_shared;
+ }
+
+ if (krt->HardKeys[keycode].shared_ptr)
+ {
+need_shared:
+ res = _e_keyrouter_send_key_events_focus(type, surface_focus, ev, &delivered_surface);
+ if (delivered_surface)
+ {
+ res = e_keyrouter_wl_add_surface_destroy_listener(delivered_surface);
+ if (res != TIZEN_KEYROUTER_ERROR_NONE)
+ {
+ KLWRN("Failed to add wl_surface to destroy listener (res: %d)", res);
+ }
+ }
+ EINA_LIST_FOREACH(krt->HardKeys[keycode].shared_ptr, l, key_node_data)
+ {
+ if (key_node_data)
+ {
+ if (delivered_surface && key_node_data->surface == delivered_surface)
+ {
+ // Check for already delivered surface
+ // do not deliver double events in this case.
+ continue;
+ }
+ else
+ {
+ _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("SHARED : %s(%s:%d) => wl_surface (%p) wl_client (%p) (pid: %d) (pname: %s)",
+ ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode, key_node_data->surface, key_node_data->wc, pid, pname ?: "Unknown");
+ if(pname) E_FREE(pname);
+ if(cmd) E_FREE(cmd);
+ }
+ }
+ }
+ return res;
+ }
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_keyrouter_send_key_events_focus(int type, struct wl_resource *surface_focus, Ecore_Event_Key *ev, struct wl_resource **delivered_surface)
+{
+ Eina_Bool res = EINA_TRUE;
+ int pid = 0;
+ char *pname = NULL, *cmd = NULL;
+
+ if (!e_keyrouter_intercept_hook_call(E_KEYROUTER_INTERCEPT_HOOK_DELIVER_FOCUS, type, ev))
+ {
+ if (ev->data)
+ {
+ *delivered_surface = ev->data;
+ ev->data = wl_resource_get_client(ev->data);
+ }
+ return res;
+ }
+
+ pid = e_keyrouter_util_get_pid(NULL, surface_focus);
+ cmd = e_keyrouter_util_cmd_get_from_pid(pid);
+ pname = e_keyrouter_util_process_name_get_from_cmd(cmd);
+
+ res = _e_keyrouter_send_key_event(type, surface_focus, NULL,ev, EINA_TRUE, TIZEN_KEYROUTER_MODE_SHARED);
+ KLINF("FOCUS DIRECT : %s(%s:%d) => wl_surface (%p) (pid: %d) (pname: %s)",
+ ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode, surface_focus, pid, pname ?: "Unknown");
+ *delivered_surface = surface_focus;
+ if(pname) E_FREE(pname);
+ if(cmd) E_FREE(cmd);
+ return res;
+}
+
+static Eina_Bool
+_e_keyrouter_check_top_visible_window(E_Client *ec_focus, int arr_idx)
+{
+ E_Client *ec_top = NULL;
+ Eina_List *l = NULL, *l_next = NULL;
+ E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
+
+ ec_top = e_client_top_get();
+
+ while (ec_top)
+ {
+ if (!ec_top->visible && ec_top == ec_focus)
+ {
+ KLDBG("Top e_client (%p) is invisible(%d) but focus client", ec_top, ec_top->visible);
+ return EINA_FALSE;
+ }
+ if (!ec_top->visible)
+ {
+ ec_top = e_client_below_get(ec_top);
+ continue;
+ }
+
+ /* TODO: Check this client is located inside a display boundary */
+
+ EINA_LIST_FOREACH_SAFE(krt->HardKeys[arr_idx].top_ptr, l, l_next, key_node_data)
+ {
+ if (key_node_data)
+ {
+ if (ec_top == wl_resource_get_user_data(key_node_data->surface))
+ {
+ krt->HardKeys[arr_idx].top_ptr = eina_list_promote_list(krt->HardKeys[arr_idx].top_ptr, l);
+ KLDBG("Move a client(e_client: %p, wl_surface: %p) to first index of list(key: %d)",
+ ec_top, key_node_data->surface, arr_idx);
+ return EINA_TRUE;
+ }
+ }
+ }
+
+ if (ec_top == ec_focus)
+ {
+ KLDBG("The e_client(%p) is a focus client", ec_top);
+ return EINA_FALSE;
+ }
+
+ ec_top = e_client_below_get(ec_top);
+ }
+ return EINA_FALSE;
+}
+
+/* Function for sending key event to wl_client(s) */
+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;
+ Eina_Bool pressed = EINA_FALSE;
+
+ if (surface == NULL) wc_send = wc;
+ else wc_send = wl_resource_get_client(surface);
+
+ if (!wc_send)
+ {
+ KLWRN("wl_surface: %p or wl_client: %p returns null wayland client", surface, wc);
+ return EINA_FALSE;
+ }
+
+ if (ECORE_EVENT_KEY_DOWN == type)
+ {
+ pressed = EINA_TRUE;
+ e_keyrouter_prepend_to_keylist(surface, wc, ev->keycode, TIZEN_KEYROUTER_MODE_PRESSED, focused);
+ }
+
+ e_keyrouter_wl_key_send(ev, pressed, wc_send, surface, focused);
+
+ return EINA_TRUE;
+}
+
+struct wl_resource *
+e_keyrouter_util_get_surface_from_eclient(E_Client *client)
+{
+ if (!client || !client->comp_data) return NULL;
+
+ return client->comp_data->wl_surface;
+}
+
+int
+e_keyrouter_util_get_pid(struct wl_client *client, struct wl_resource *surface)
+{
+ pid_t pid = 0;
+ uid_t uid = 0;
+ gid_t gid = 0;
+ struct wl_client *cur_client = NULL;
+
+ if (client) cur_client = client;
+ else if (surface) cur_client = wl_resource_get_client(surface);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cur_client, 0);
+
+ wl_client_get_credentials(cur_client, &pid, &uid, &gid);
+
+ return pid;
+}
+
+char *
+e_keyrouter_util_cmd_get_from_pid(int pid)
+{
+ Eina_List *l;
+ E_Comp_Connected_Client_Info *cdata;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
+
+ EINA_LIST_FOREACH(e_comp->connected_clients, l, cdata)
+ {
+ if (cdata->pid == pid) return strdup(cdata->name);
+ }
+
+ return NULL;
+}
+
+typedef struct _keycode_map{
+ xkb_keysym_t keysym;
+ xkb_keycode_t keycode;
+}keycode_map;
+
+static void
+find_keycode(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
+{
+ keycode_map *found_keycodes = (keycode_map *)data;
+ xkb_keysym_t keysym = found_keycodes->keysym;
+ int nsyms = 0;
+ const xkb_keysym_t *syms_out = NULL;
+
+ nsyms = xkb_keymap_key_get_syms_by_level(keymap, key, 0, 0, &syms_out);
+ if (nsyms && syms_out)
+ {
+ if (*syms_out == keysym)
+ {
+ found_keycodes->keycode = key;
+ }
+ }
+}
+
+int
+_e_keyrouter_keycode_get_from_keysym(struct xkb_keymap *keymap, xkb_keysym_t keysym)
+{
+ keycode_map found_keycodes = {0,};
+ found_keycodes.keysym = keysym;
+ xkb_keymap_key_for_each(keymap, find_keycode, &found_keycodes);
+
+ return found_keycodes.keycode;
+}
+
+int
+e_keyrouter_util_keycode_get_from_string(char * name)
+{
+ struct xkb_keymap *keymap = NULL;
+ xkb_keysym_t keysym = 0x0;
+ int keycode = 0;
+
+ keymap = e_comp_wl->xkb.keymap;
+ EINA_SAFETY_ON_NULL_GOTO(keymap, finish);
+
+ keysym = xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS);
+ EINA_SAFETY_ON_FALSE_GOTO(keysym != XKB_KEY_NoSymbol, finish);
+
+ keycode = _e_keyrouter_keycode_get_from_keysym(keymap, keysym);
+
+ KLDBG("request name: %s, return value: %d", name, keycode);
+
+ return keycode;
+
+finish:
+ return 0;
+}
+
+char *
+e_keyrouter_util_keyname_get_from_keycode(int keycode)
+{
+ struct xkb_state *state;
+ xkb_keysym_t sym = XKB_KEY_NoSymbol;
+ char name[256] = {0, };
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->xkb.state, NULL);
+
+ state = e_comp_wl->xkb.state;
+ sym = xkb_state_key_get_one_sym(state, keycode);
+ xkb_keysym_get_name(sym, name, sizeof(name));
+
+ return strdup(name);
+}
+
+char *
+e_keyrouter_util_process_name_get_from_cmd(char *cmd)
+{
+ int len, i;
+ char pbuf = '\0';
+ char *pname = NULL;
+ if (cmd)
+ {
+ len = strlen(cmd);
+ for (i = 0; i < len; i++)
+ {
+ pbuf = cmd[len - i - 1];
+ if (pbuf == '/')
+ {
+ pname = &cmd[len - i];
+ return strdup(pname);
+ }
+ }
+ }
+ return NULL;
+}
+
--- /dev/null
+#include "e_keyrouter_private.h"
+
+static int _e_keyrouter_find_duplicated_client(struct wl_resource *surface, struct wl_client *wc, uint32_t key, uint32_t mode);
+static Eina_Bool _e_keyrouter_find_key_in_list(struct wl_resource *surface, struct wl_client *wc, int key, int mode);
+static Eina_List **_e_keyrouter_get_list(int mode, int key);
+
+/* add a new key grab info to the list */
+int
+e_keyrouter_set_keygrab_in_list(struct wl_resource *surface, struct wl_client *client, uint32_t key, uint32_t mode)
+{
+ int res = TIZEN_KEYROUTER_ERROR_NONE;
+
+ EINA_SAFETY_ON_FALSE_RETURN_VAL
+ (((mode == TIZEN_KEYROUTER_MODE_EXCLUSIVE) ||
+ (mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE) ||
+ (mode == TIZEN_KEYROUTER_MODE_TOPMOST) ||
+ (mode == TIZEN_KEYROUTER_MODE_SHARED)),
+ TIZEN_KEYROUTER_ERROR_INVALID_MODE);
+
+ if (mode == TIZEN_KEYROUTER_MODE_EXCLUSIVE)
+ {
+ EINA_SAFETY_ON_TRUE_RETURN_VAL
+ ((krt->HardKeys[key].excl_ptr != NULL),
+ TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY);
+ }
+
+ if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
+ {
+ EINA_SAFETY_ON_NULL_RETURN_VAL
+ (surface, TIZEN_KEYROUTER_ERROR_INVALID_SURFACE);
+ }
+
+ res = e_keyrouter_prepend_to_keylist(surface,
+ surface ? NULL : client,
+ key,
+ mode,
+ EINA_FALSE);
+
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(res == TIZEN_KEYROUTER_ERROR_NONE, res);
+
+ return res;
+}
+
+/* Function for checking whether the key has been grabbed already by the same wl_surface or not */
+static int
+_e_keyrouter_find_duplicated_client(struct wl_resource *surface, struct wl_client *wc, uint32_t key, uint32_t mode)
+{
+ Eina_List *keylist_ptr = NULL, *l = NULL;
+ E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
+
+ switch(mode)
+ {
+ case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
+ return TIZEN_KEYROUTER_ERROR_NONE;
+
+ case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+ keylist_ptr = krt->HardKeys[key].or_excl_ptr;
+ break;
+
+ case TIZEN_KEYROUTER_MODE_TOPMOST:
+ keylist_ptr = krt->HardKeys[key].top_ptr;
+ break;
+
+ case TIZEN_KEYROUTER_MODE_SHARED:
+ keylist_ptr = krt->HardKeys[key].shared_ptr;
+ break;
+
+ 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)", key, mode);
+ return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
+ }
+
+ EINA_LIST_FOREACH(keylist_ptr, l, key_node_data)
+ {
+ if (!key_node_data) continue;
+
+ if (surface)
+ {
+ if (key_node_data->surface == surface)
+ {
+ KLDBG("The key(%d) is already grabbed same mode(%s) on the same wl_surface %p",
+ key, e_keyrouter_mode_to_string(mode), surface);
+ return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY;
+ }
+ }
+ else
+ {
+ if (key_node_data->wc == wc)
+ {
+ KLDBG("The key(%d) is already grabbed same mode(%s) on the same wl_client %p",
+ key, e_keyrouter_mode_to_string(mode), wc);
+ return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY;
+ }
+ }
+ }
+
+ return TIZEN_KEYROUTER_ERROR_NONE;
+}
+
+static Eina_Bool
+_e_keyrouter_find_key_in_list(struct wl_resource *surface, struct wl_client *wc, int key, int mode)
+{
+ Eina_List **list = NULL;
+ Eina_List *l = NULL, *l_next = NULL;
+ E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
+
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(((!surface) && (!wc)), EINA_FALSE);
+
+ list = _e_keyrouter_get_list(mode, key);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(list, EINA_FALSE);
+
+ EINA_LIST_FOREACH_SAFE(*list, l, l_next, key_node_data)
+ {
+ if (!key_node_data) continue;
+
+ if ((surface) && (surface == key_node_data->surface)) return EINA_TRUE;
+ else if ((wc == key_node_data->wc)) return EINA_TRUE;
+ }
+
+ return EINA_FALSE;
+}
+
+
+/* Function for prepending a new key grab information in the keyrouting list */
+int
+e_keyrouter_prepend_to_keylist(struct wl_resource *surface, struct wl_client *wc, uint32_t key, uint32_t mode, Eina_Bool focused)
+{
+ int res = TIZEN_KEYROUTER_ERROR_NONE;
+
+ res = _e_keyrouter_find_duplicated_client(surface, wc, key, mode);
+ CHECK_ERR_VAL(res);
+
+ E_Keyrouter_Key_List_NodePtr new_keyptr = E_NEW(E_Keyrouter_Key_List_Node, 1);
+
+ if (!new_keyptr)
+ {
+ KLERR("Failled to allocate memory for new_keyptr");
+ return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
+ }
+
+ new_keyptr->surface = surface;
+ new_keyptr->wc = wc;
+ new_keyptr->focused = focused;
+ new_keyptr->status = E_KRT_CSTAT_ALIVE;
+
+ switch(mode)
+ {
+ case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
+ krt->HardKeys[key].excl_ptr = eina_list_prepend(krt->HardKeys[key].excl_ptr, new_keyptr);
+ break;
+
+ case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+ krt->HardKeys[key].or_excl_ptr= eina_list_prepend(krt->HardKeys[key].or_excl_ptr, new_keyptr);
+ break;
+
+ case TIZEN_KEYROUTER_MODE_TOPMOST:
+ krt->HardKeys[key].top_ptr = eina_list_prepend(krt->HardKeys[key].top_ptr, new_keyptr);
+ break;
+
+ case TIZEN_KEYROUTER_MODE_SHARED:
+ krt->HardKeys[key].shared_ptr= eina_list_prepend(krt->HardKeys[key].shared_ptr, new_keyptr);
+ break;
+
+ 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)", key, mode);
+ E_FREE(new_keyptr);
+ return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
+ }
+
+ if (TIZEN_KEYROUTER_MODE_PRESSED != mode)
+ {
+ if (surface)
+ {
+ e_keyrouter_wl_add_surface_destroy_listener(surface);
+ /* TODO: if failed add surface_destory_listener, remove keygrabs */
+ }
+ else if (wc)
+ {
+ e_keyrouter_wl_add_client_destroy_listener(wc);
+ /* TODO: if failed add client_destory_listener, remove keygrabs */
+ }
+ }
+
+ return TIZEN_KEYROUTER_ERROR_NONE;
+}
+
+/* remove key grab info from the list */
+void
+e_keyrouter_find_and_remove_client_from_list(struct wl_resource *surface, struct wl_client *wc, uint32_t key, uint32_t mode)
+{
+ Eina_List **list = NULL;
+ Eina_List *l = NULL, *l_next = NULL;
+ E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
+
+ list = _e_keyrouter_get_list(mode, key);
+ EINA_SAFETY_ON_NULL_RETURN(list);
+
+ EINA_LIST_FOREACH_SAFE(*list, l, l_next, key_node_data)
+ {
+ if (!key_node_data) continue;
+
+ if (surface)
+ {
+ if (surface == key_node_data->surface)
+ {
+ if (mode == TIZEN_KEYROUTER_MODE_PRESSED)
+ {
+ key_node_data->status = E_KRT_CSTAT_UNGRAB;
+ }
+ else
+ {
+ *list = eina_list_remove_list(*list, l);
+ E_FREE(key_node_data);
+ }
+ KLDBG("Remove a %s Mode Grabbed key(%d) by surface(%p)", e_keyrouter_mode_to_string(mode), key, surface);
+ }
+ }
+ else if ((wc == key_node_data->wc))
+ {
+ if (mode == TIZEN_KEYROUTER_MODE_PRESSED)
+ {
+ key_node_data->status = E_KRT_CSTAT_UNGRAB;
+ }
+ else
+ {
+ *list = eina_list_remove_list(*list, l);
+ E_FREE(key_node_data);
+ }
+ KLDBG("Remove a %s Mode Grabbed key(%d) by wc(%p)", e_keyrouter_mode_to_string(mode), key, wc);
+ }
+ }
+}
+
+void
+e_keyrouter_remove_client_from_list(struct wl_resource *surface, struct wl_client *wc)
+{
+ int i = 0;
+ Eina_List *l = NULL, *l_next = NULL;
+ E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
+
+ EINA_SAFETY_ON_TRUE_RETURN(((!surface) && (!wc)));
+
+ 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 (!key_node_data) continue;
+
+ if (surface)
+ {
+ if (surface == key_node_data->surface)
+ {
+ krt->HardKeys[i].excl_ptr = eina_list_remove_list(krt->HardKeys[i].excl_ptr, l);
+ E_FREE(key_node_data);
+ KLDBG("Remove a Exclusive Mode Grabbed key(%d) by wl_surface(%p)", i, surface);
+ }
+ }
+ else if ((wc == key_node_data->wc))
+ {
+ krt->HardKeys[i].excl_ptr = eina_list_remove_list(krt->HardKeys[i].excl_ptr, l);
+ E_FREE(key_node_data);
+ KLDBG("Remove a Exclusive Mode Grabbed key(%d) by wl_client(%p)", i, wc);
+ }
+ }
+ EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].or_excl_ptr, l, l_next, key_node_data)
+ {
+ if (!key_node_data) continue;
+
+ if (surface)
+ {
+ if (surface == key_node_data->surface)
+ {
+ krt->HardKeys[i].or_excl_ptr = eina_list_remove_list(krt->HardKeys[i].or_excl_ptr, l);
+ E_FREE(key_node_data);
+ KLDBG("Remove a Overridable_Exclusive Mode Grabbed key(%d) by wl_surface(%p)", i, surface);
+ }
+ }
+ else if ((wc == key_node_data->wc))
+ {
+ krt->HardKeys[i].or_excl_ptr = eina_list_remove_list(krt->HardKeys[i].or_excl_ptr, l);
+ E_FREE(key_node_data);
+ KLDBG("Remove a Overridable_Exclusive Mode Grabbed key(%d) by wl_client(%p)", i, wc);
+ }
+ }
+ EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].top_ptr, l, l_next, key_node_data)
+ {
+ if (!key_node_data) continue;
+
+ if (surface)
+ {
+ if (surface == key_node_data->surface)
+ {
+ krt->HardKeys[i].top_ptr = eina_list_remove_list(krt->HardKeys[i].top_ptr, l);
+ E_FREE(key_node_data);
+ KLDBG("Remove a Topmost Mode Grabbed key(%d) by wl_surface(%p)", i, surface);
+ }
+ }
+ else if ((wc == key_node_data->wc))
+ {
+ krt->HardKeys[i].top_ptr = eina_list_remove_list(krt->HardKeys[i].top_ptr, l);
+ E_FREE(key_node_data);
+ KLDBG("Remove a Topmost Mode Grabbed key(%d) by wl_client(%p)", i, wc);
+ }
+ }
+ EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].shared_ptr, l, l_next, key_node_data)
+ {
+ if (!key_node_data) continue;
+
+ if (surface)
+ {
+ if (surface == key_node_data->surface)
+ {
+ krt->HardKeys[i].shared_ptr = eina_list_remove_list(krt->HardKeys[i].shared_ptr, l);
+ E_FREE(key_node_data);
+ KLDBG("Remove a Shared Mode Grabbed key(%d) by wl_surface(%p)", i, surface);
+ }
+ }
+ else if ((wc == key_node_data->wc))
+ {
+ krt->HardKeys[i].shared_ptr = eina_list_remove_list(krt->HardKeys[i].shared_ptr, l);
+ E_FREE(key_node_data);
+ KLDBG("Remove a Shared Mode Grabbed key(%d) by wl_client(%p)", i, wc);
+ }
+ }
+ EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].press_ptr, l, l_next, key_node_data)
+ {
+ if (!key_node_data) continue;
+
+ if (surface)
+ {
+ if (surface == key_node_data->surface)
+ {
+ key_node_data->status = E_KRT_CSTAT_DEAD;
+ KLDBG("Remove a Pressed key(%d) by wl_surface(%p)", i, surface);
+ key_node_data->wc = wl_resource_get_client(surface);
+ }
+ }
+ else if ((wc == key_node_data->wc))
+ {
+ key_node_data->status = E_KRT_CSTAT_DEAD;
+ KLDBG("Remove a Pressed key(%d) by wl_client(%p)", 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)
+ {
+ if (surface == key_node_data->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);
+ }
+ }
+ }
+}
+
+int
+e_keyrouter_find_key_in_list(struct wl_resource *surface, struct wl_client *wc, uint32_t key)
+{
+ int mode = TIZEN_KEYROUTER_MODE_NONE;
+ Eina_Bool found = EINA_FALSE;
+
+ mode = TIZEN_KEYROUTER_MODE_EXCLUSIVE;
+ found = _e_keyrouter_find_key_in_list(surface, wc, key, mode);
+ if (found) goto finish;
+
+ mode = TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE;
+ found = _e_keyrouter_find_key_in_list(surface, wc, key, mode);
+ if (found) goto finish;
+
+ mode = TIZEN_KEYROUTER_MODE_TOPMOST;
+ found = _e_keyrouter_find_key_in_list(surface, wc, key, mode);
+ if (found) goto finish;
+
+ mode = TIZEN_KEYROUTER_MODE_SHARED;
+ found = _e_keyrouter_find_key_in_list(surface, wc, key, mode);
+ if (found) goto finish;
+
+ KLDBG("%d key is not grabbed by (wl_surface: %p, wl_client: %p)", key, surface, wc);
+ return TIZEN_KEYROUTER_MODE_NONE;
+
+finish:
+ KLDBG("Find %d key grabbed by (wl_surface: %p, wl_client: %p) in %s mode",
+ key, surface, wc, e_keyrouter_mode_to_string(mode));
+ return mode;
+}
+
+const char *
+e_keyrouter_mode_to_string(uint32_t mode)
+{
+ const char *str = NULL;
+
+ switch (mode)
+ {
+ case TIZEN_KEYROUTER_MODE_EXCLUSIVE: str = "Exclusive"; break;
+ case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE: str = "Overridable_Exclusive"; break;
+ case TIZEN_KEYROUTER_MODE_TOPMOST: str = "Topmost"; break;
+ case TIZEN_KEYROUTER_MODE_SHARED: str = "Shared"; break;
+ case TIZEN_KEYROUTER_MODE_PRESSED: str = "Pressed"; break;
+ default: str = "UnknownMode"; break;
+ }
+
+ return str;
+}
+
+static Eina_List **
+_e_keyrouter_get_list(int mode, int key)
+{
+ Eina_List **list = NULL;
+
+ switch (mode)
+ {
+ case TIZEN_KEYROUTER_MODE_EXCLUSIVE: list = &krt->HardKeys[key].excl_ptr; break;
+ case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE: list = &krt->HardKeys[key].or_excl_ptr; break;
+ case TIZEN_KEYROUTER_MODE_TOPMOST: list = &krt->HardKeys[key].top_ptr; break;
+ case TIZEN_KEYROUTER_MODE_SHARED: list = &krt->HardKeys[key].shared_ptr; break;
+ case TIZEN_KEYROUTER_MODE_PRESSED: list = &krt->HardKeys[key].press_ptr; break;
+ default: break;
+ }
+
+ return list;
+}
+
+
+int
+e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface, int key, int mode)
+{
+ int res=0;
+
+#ifdef HAVE_CYNARA
+ if (EINA_FALSE == e_keyrouter_wl_util_do_privilege_check(client, mode, key))
+ {
+ KLINF("No permission for %d grab mode ! (key=%d)", mode, key);
+ return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
+ }
+#endif
+
+ if (!surface)
+ {
+ /* Regarding topmost mode, a client must request to grab a key with a valid surface. */
+ if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
+ {
+ KLWRN("Invalid surface for %d grab mode ! (key=%d)", mode, key);
+
+ return TIZEN_KEYROUTER_ERROR_INVALID_SURFACE;
+ }
+ }
+
+ /* Check the given key range */
+ if (krt->max_tizen_hwkeys < key)
+ {
+ KLWRN("Invalid range of key ! (keycode:%d)", key);
+ return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
+ }
+
+ /* Check whether the key can be grabbed or not !
+ * Only key listed in Tizen key layout file can be grabbed. */
+ if (0 == krt->HardKeys[key].keycode)
+ {
+ KLWRN("Invalid key ! Disabled to grab ! (keycode:%d)", key);
+ return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
+ }
+
+ /* Check whether the request key can be grabbed or not */
+ res = e_keyrouter_set_keygrab_in_list(surface, client, key, mode);
+
+ return res;
+}
+
+int
+e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface, int key)
+{
+ /* Ungrab top position grabs first. This grab mode do not need privilege */
+ if (!surface)
+ e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
+ else
+ e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
+
+#ifdef HAVE_CYNARA
+ if (EINA_FALSE == e_keyrouter_wl_util_do_privilege_check(client, TIZEN_KEYROUTER_MODE_NONE, key))
+ {
+ goto finish;
+ }
+#endif
+
+ if (!surface)
+ {
+ /* EXCLUSIVE grab */
+ e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_EXCLUSIVE);
+
+ /* OVERRIDABLE_EXCLUSIVE grab */
+ e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
+
+ /* SHARED grab */
+ e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_SHARED);
+
+ /* Press List */
+ e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_PRESSED);
+ }
+ else
+ {
+ /* EXCLUSIVE grab */
+ e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_EXCLUSIVE);
+
+ /* OVERRIDABLE_EXCLUSIVE grab */
+ e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
+
+ /* SHARED grab */
+ e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_SHARED);
+
+ /* Press List */
+ e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_PRESSED);
+ }
+
+finish:
+ e_keyrouter_keycancel_send(client, surface, key);
+
+ return TIZEN_KEYROUTER_ERROR_NONE;
+}
--- /dev/null
+#include "e.h"
+#include "e_keyrouter.h"
+#ifdef HAVE_CYNARA
+#include <cynara-session.h>
+#include <cynara-client.h>
+#include <cynara-creds-socket.h>
+#include <sys/smack.h>
+#endif
+#include <tizen-extension-server-protocol.h>
+
+#define CHECK_ERR(val) if (TIZEN_KEYROUTER_ERROR_NONE != val) return;
+#define CHECK_ERR_VAL(val) if (TIZEN_KEYROUTER_ERROR_NONE != val) return val;
+#define CHECK_NULL(val) if (!val) return;
+#define CHECK_NULL_VAL(val) if (!val) return val;
+
+#define KLERR(msg, ARG...) ERR(msg, ##ARG)
+#define KLWRN(msg, ARG...) WRN(msg, ##ARG)
+#define KLINF(msg, ARG...) INF(msg, ##ARG)
+#define KLDBG(msg, ARG...) DBG(msg, ##ARG)
+
+typedef struct _E_Keyrouter E_Keyrouter;
+typedef struct _E_Keyrouter* E_KeyrouterPtr;
+typedef struct _E_Keyrouter_Grab_Request E_Keyrouter_Grab_Request;
+typedef struct _E_Keyrouter_Ungrab_Request E_Keyrouter_Ungrab_Request;
+
+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;
+
+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
+};
+
+struct _E_Keyrouter_Config_Data
+{
+ E_Config_DD *conf_edd;
+ E_Config_DD *conf_hwkeys_edd;
+ E_Keyrouter_Conf_Edd *conf;
+};
+
+struct _E_Keyrouter
+{
+ struct wl_global *global;
+ Ecore_Event_Filter *ef_handler;
+ Eina_List *handlers;
+ Eina_List *resources;
+
+ E_Keyrouter_Config_Data *conf;
+
+ E_Keyrouter_Grabbed_Key *HardKeys;
+ Eina_List *grab_surface_list;
+ Eina_List *grab_client_list;
+
+ Eina_Bool isWindowStackChanged;
+ int numTizenHWKeys;
+ int max_tizen_hwkeys;
+#ifdef HAVE_CYNARA
+ cynara *p_cynara;
+#endif
+ int isPictureOffEnabled;
+ Eina_Bool pictureoff_disabled;
+};
+
+struct _E_Keyrouter_Grab_Request {
+ int key;
+ int mode;
+ int err;
+};
+
+struct _E_Keyrouter_Ungrab_Request {
+ int key;
+ int err;
+};
+
+int e_keyrouter_set_keygrab_in_list(struct wl_resource *surface, struct wl_client *client, uint32_t key, uint32_t mode);
+int e_keyrouter_prepend_to_keylist(struct wl_resource *surface, struct wl_client *wc, uint32_t key, uint32_t mode, Eina_Bool focused);
+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_process_key_event(void *event, int type);
+
+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);
+char *e_keyrouter_util_cmd_get_from_pid(int pid);
+int e_keyrouter_util_keycode_get_from_string(char *name);
+char *e_keyrouter_util_keyname_get_from_keycode(int keycode);
+char *e_keyrouter_util_process_name_get_from_cmd(char *cmd);
+const char *e_keyrouter_mode_to_string(uint32_t mode);
+
+void e_keyrouter_conf_init(E_Keyrouter_Config_Data *kconfig);
+void e_keyrouter_conf_deinit(E_Keyrouter_Config_Data *kconfig);
+int e_keyrouter_cb_picture_off(const int option, void *data);
+
+Eina_Bool e_keyrouter_wl_init(void);
+void e_keyrouter_wl_shutdown(void);
+int e_keyrouter_wl_add_client_destroy_listener(struct wl_client *client);
+int e_keyrouter_wl_add_surface_destroy_listener(struct wl_resource *surface);
+#ifdef HAVE_CYNARA
+Eina_Bool e_keyrouter_wl_util_do_privilege_check(struct wl_client *client, uint32_t mode, uint32_t keycode);
+#endif
+
+int e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface, int key, int mode);
+int e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface, int key);
+
+Eina_Bool e_keyrouter_event_process(void *event, int type);
+
+Eina_Bool e_keyrouter_wl_key_send(Ecore_Event_Key *ev, Eina_Bool pressed, struct wl_client *client, struct wl_resource *surface, Eina_Bool focused);
+void e_keyrouter_keycancel_send(struct wl_client *client, struct wl_resource *surface, unsigned int key);
--- /dev/null
+#include "e_keyrouter_private.h"
+
+static void
+_e_keyrouter_wl_key_send(Ecore_Event_Key *ev, enum wl_keyboard_key_state state, Eina_List *key_list, Eina_Bool focused, struct wl_client *client, struct wl_resource *surface)
+{
+ struct wl_resource *res;
+ Eina_List *l;
+ uint32_t serial, keycode;
+ struct wl_client *wc;
+ E_Comp_Config *comp_conf = NULL;
+
+ keycode = (ev->keycode - 8);
+
+ serial = wl_display_next_serial(e_comp_wl->wl.disp);
+
+ comp_conf = e_comp_config_get();
+
+ EINA_LIST_FOREACH(key_list, l, res)
+ {
+ wc = wl_resource_get_client(res);
+ if (!focused && wc != client) continue;
+ TRACE_INPUT_BEGIN(_e_comp_wl_key_send);
+// _e_comp_wl_send_event_device(client, ev->timestamp, ev->dev, serial);
+
+ if (comp_conf && comp_conf->input_log_enable)
+ INF("[Server] Routed Key %s (time: %d)\n", (state ? "Down" : "Up"), ev->timestamp);
+
+ wl_keyboard_send_key(res, serial, ev->timestamp,
+ keycode, state);
+ TRACE_INPUT_END();
+ }
+}
+
+Eina_Bool
+e_keyrouter_wl_key_send(Ecore_Event_Key *ev, Eina_Bool pressed, struct wl_client *client, struct wl_resource *surface, Eina_Bool focused)
+{
+ E_Client *ec = NULL;
+ struct wl_client *wc = NULL;
+ uint32_t keycode;
+ enum wl_keyboard_key_state state;
+
+ if ((e_comp->comp_type != E_PIXMAP_TYPE_WL) || (ev->window != e_comp->ee_win))
+ {
+ return EINA_FALSE;
+ }
+
+ keycode = (ev->keycode - 8);
+ if (!(e_comp_wl = e_comp->wl_comp_data))
+ {
+ return EINA_FALSE;
+ }
+
+#ifndef E_RELEASE_BUILD
+ if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
+ ((ev->modifiers & ECORE_EVENT_MODIFIER_ALT) ||
+ (ev->modifiers & ECORE_EVENT_MODIFIER_ALTGR)) &&
+ eina_streq(ev->key, "BackSpace"))
+ {
+ exit(0);
+ }
+#endif
+
+ if (pressed) state = WL_KEYBOARD_KEY_STATE_PRESSED;
+ else state = WL_KEYBOARD_KEY_STATE_RELEASED;
+
+ if (!focused)
+ {
+ _e_keyrouter_wl_key_send(ev, state, e_comp_wl->kbd.resources, EINA_FALSE, client, surface);
+ return EINA_FALSE;
+ }
+
+ if ((!e_client_action_get()) && (!e_comp->input_key_grabs))
+ {
+ ec = e_client_focused_get();
+ if (ec && ec->comp_data && ec->comp_data->surface)
+ {
+ if (e_comp_wl->kbd.focused)
+ {
+ wc = wl_resource_get_client(ec->comp_data->surface);
+ _e_keyrouter_wl_key_send(ev, state, e_comp_wl->kbd.focused, EINA_TRUE, wc, surface);
+ }
+
+ /* update modifier state */
+ e_comp_wl_input_keyboard_state_update(keycode, pressed);
+ }
+ }
+ return !!ec;
+}
+
+void
+e_keyrouter_keycancel_send(struct wl_client *client, struct wl_resource *surface, unsigned int key)
+{
+ Eina_List *l;
+ struct wl_resource *resource = NULL;
+ struct wl_client *wc = NULL;
+ E_Keyrouter_Key_List_NodePtr data;
+
+ if (surface) wc = wl_resource_get_client(surface);
+ else wc = client;
+
+ EINA_SAFETY_ON_NULL_RETURN(wc);
+
+ EINA_LIST_FOREACH(krt->HardKeys[key].press_ptr, l, data)
+ {
+ if (surface)
+ {
+ if (surface == data->surface)
+ {
+ EINA_LIST_FOREACH(krt->resources, l, resource)
+ {
+ if (wl_resource_get_client(resource) != wc) continue;
+
+ tizen_keyrouter_send_key_cancel(resource, key-8);
+ }
+ }
+ }
+ else if (client == data->wc)
+ {
+ EINA_LIST_FOREACH(krt->resources, l, resource)
+ {
+ if (wl_resource_get_client(resource) != wc) continue;
+
+ tizen_keyrouter_send_key_cancel(resource, key-8);
+ }
+ }
+ }
+}
+
+static int
+_e_keyrouter_wl_array_length(const struct wl_array *array)
+{
+ int *data = NULL;
+ int count = 0;
+
+ wl_array_for_each(data, array)
+ {
+ count++;
+ }
+
+ return count;
+}
+
+/* tizen_keyrouter_set_keygrab request handler */
+static void
+_e_keyrouter_cb_keygrab_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode)
+{
+ int res = 0;
+
+ TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set);
+
+ res = e_keyrouter_keygrab_set(client, surface, key, mode);
+
+ TRACE_INPUT_END();
+
+ if (res == TIZEN_KEYROUTER_ERROR_NONE)
+ {
+ if (mode == TIZEN_KEYROUTER_MODE_EXCLUSIVE)
+ {
+ KLINF("Success to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d)", key, e_keyrouter_mode_to_string(mode),
+ client, surface, e_keyrouter_util_get_pid(client, surface));
+ }
+ else
+ {
+ KLDBG("Success to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d)", key, e_keyrouter_mode_to_string(mode),
+ client, surface, e_keyrouter_util_get_pid(client, surface));
+ }
+ }
+ else
+ KLINF("Failed to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d", key, e_keyrouter_mode_to_string(mode),
+ client, surface, e_keyrouter_util_get_pid(client, surface), res);
+ tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res);
+}
+
+/* tizen_keyrouter unset_keygrab request handler */
+static void
+_e_keyrouter_cb_keygrab_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
+{
+ int res = 0;
+
+ TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset);
+
+ res = e_keyrouter_keygrab_unset(client, surface, key);
+
+ TRACE_INPUT_END();
+
+ if (res == TIZEN_KEYROUTER_ERROR_NONE)
+ KLDBG("Success to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d)", key, client, surface,
+ e_keyrouter_util_get_pid(client, surface));
+ else
+ KLINF("Failed to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d", key, client, surface,
+ e_keyrouter_util_get_pid(client, surface), res);
+ tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res);
+}
+
+/* tizen_keyrouter get_keygrab_status request handler */
+static void
+_e_keyrouter_cb_get_keygrab_status(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
+{
+ (void) client;
+ (void) resource;
+ (void) surface;
+ (void) key;
+ int mode = TIZEN_KEYROUTER_MODE_NONE;
+
+ TRACE_INPUT_BEGIN(_e_keyrouter_cb_get_keygrab_status);
+ mode = e_keyrouter_find_key_in_list(surface, client, key);
+
+ TRACE_INPUT_END();
+ tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, TIZEN_KEYROUTER_ERROR_NONE);
+}
+
+static void
+_e_keyrouter_cb_keygrab_set_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
+{
+ E_Keyrouter_Grab_Request *grab_request = NULL;
+ int res = TIZEN_KEYROUTER_ERROR_NONE;
+ int array_len = 0;
+
+ TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set_list);
+
+ array_len = _e_keyrouter_wl_array_length(grab_list);
+
+ if (0 != (array_len % 3))
+ {
+ /* FIX ME: Which way is effectively to notify invalid pair to client */
+ KLWRN("Invalid keycode and grab mode pair. Check arguments in a list");
+ TRACE_INPUT_END();
+ tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
+ return;
+ }
+
+ wl_array_for_each(grab_request, grab_list)
+ {
+ res = e_keyrouter_keygrab_set(client, surface, grab_request->key, grab_request->mode);
+ grab_request->err = res;
+ if (res == TIZEN_KEYROUTER_ERROR_NONE)
+ KLDBG("Success to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d)",
+ grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
+ client, surface, e_keyrouter_util_get_pid(client, surface));
+ else
+ KLINF("Failed to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d): res: %d",
+ grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
+ client, surface, e_keyrouter_util_get_pid(client, surface), grab_request->err);
+ }
+
+
+ TRACE_INPUT_END();
+ tizen_keyrouter_send_keygrab_notify_list(resource, surface, grab_list);
+}
+
+static void
+_e_keyrouter_cb_keygrab_unset_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *ungrab_list)
+{
+ E_Keyrouter_Ungrab_Request *ungrab_request = NULL;
+ int res = TIZEN_KEYROUTER_ERROR_NONE;
+ int array_len = 0;
+
+ TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset_list);
+
+ array_len = _e_keyrouter_wl_array_length(ungrab_list);
+
+ if (0 != (array_len % 2))
+ {
+ /* FIX ME: Which way is effectively to notify invalid pair to client */
+ KLWRN("Invalid keycode and error pair. Check arguments in a list");
+ TRACE_INPUT_END();
+ tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
+ return;
+ }
+
+ wl_array_for_each(ungrab_request, ungrab_list)
+ {
+ res = e_keyrouter_keygrab_unset(client, surface, ungrab_request->key);
+ ungrab_request->err = res;
+ if (res == TIZEN_KEYROUTER_ERROR_NONE)
+ KLDBG("Success to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d)",
+ ungrab_request->key, client, surface, e_keyrouter_util_get_pid(client, surface));
+ else
+ KLINF("Failed to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d): res: %d",
+ ungrab_request->key, client, surface, e_keyrouter_util_get_pid(client, surface), ungrab_request->err);
+ }
+
+ TRACE_INPUT_END();
+ tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
+}
+
+static void
+_e_keyrouter_cb_keygrab_get_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface)
+{
+ (void) client;
+
+ tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL);
+}
+
+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;
+ (void) data;
+
+ tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, 0);
+}
+
+static void
+_e_keyrouter_cb_get_keyregister_status(struct wl_client *client, struct wl_resource *resource, uint32_t key)
+{
+ (void) client;
+ (void) key;
+
+ tizen_keyrouter_send_keyregister_notify(resource, (int)EINA_FALSE);
+}
+
+static void
+_e_keyrouter_cb_set_input_config(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *surface EINA_UNUSED, uint32_t config_mode EINA_UNUSED, uint32_t value EINA_UNUSED)
+{
+ tizen_keyrouter_send_set_input_config_notify(resource, 0);
+}
+
+static void
+_e_keyrouter_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static const struct tizen_keyrouter_interface _e_keyrouter_implementation = {
+ _e_keyrouter_cb_keygrab_set,
+ _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_get_list,
+ _e_keyrouter_cb_set_register_none_key,
+ _e_keyrouter_cb_get_keyregister_status,
+ _e_keyrouter_cb_set_input_config,
+ _e_keyrouter_cb_destroy,
+};
+
+static void
+_e_keyrouter_cb_unbind(struct wl_resource *resource)
+{
+ krt->resources = eina_list_remove(krt->resources, resource);
+}
+
+/* tizen_keyrouter global object bind function */
+static void
+_e_keyrouter_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+ E_KeyrouterPtr krt_instance = data;
+ struct wl_resource *resource;
+
+ resource = wl_resource_create(client, &tizen_keyrouter_interface, version, id);
+
+ KLDBG("wl_resource_create(...,&tizen_keyrouter_interface,...)");
+
+ if (!resource)
+ {
+ KLERR("Failed to create resource ! (version :%d, id:%d)", version, id);
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ krt->resources = eina_list_append(krt->resources, resource);
+
+ wl_resource_set_implementation(resource, &_e_keyrouter_implementation, krt_instance, _e_keyrouter_cb_unbind);
+}
+
+static void
+_e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
+{
+ struct wl_client *client = data;
+
+ KLDBG("Listener(%p) called: wl_client: %p is died", l, client);
+ e_keyrouter_remove_client_from_list(NULL, client);
+
+ wl_list_remove(&l->link);
+ E_FREE(l);
+
+ krt->grab_client_list = eina_list_remove(krt->grab_client_list, client);
+}
+
+static void
+_e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
+{
+ struct wl_resource *surface = (struct wl_resource *)data;
+
+ KLDBG("Listener(%p) called: surface: %p is died", l, surface);
+ e_keyrouter_remove_client_from_list(surface, NULL);
+
+ wl_list_remove(&l->link);
+ E_FREE(l);
+
+ krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, surface);
+}
+
+int
+e_keyrouter_wl_add_client_destroy_listener(struct wl_client *client)
+{
+ struct wl_listener *destroy_listener = NULL;
+ Eina_List *l;
+ struct wl_client *wc_data;
+
+ if (!client) return TIZEN_KEYROUTER_ERROR_NONE;
+
+ EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
+ {
+ if (wc_data)
+ {
+ if (wc_data == client)
+ {
+ return TIZEN_KEYROUTER_ERROR_NONE;
+ }
+ }
+ }
+
+ destroy_listener = E_NEW(struct wl_listener, 1);
+
+ if (!destroy_listener)
+ {
+ KLERR("Failed to allocate memory for wl_client destroy listener !");
+ return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
+ }
+
+ destroy_listener->notify = _e_keyrouter_wl_client_cb_destroy;
+ wl_client_add_destroy_listener(client, destroy_listener);
+ krt->grab_client_list = eina_list_append(krt->grab_client_list, client);
+
+ return TIZEN_KEYROUTER_ERROR_NONE;
+}
+
+/* Function for registering wl_surface destroy listener */
+int
+e_keyrouter_wl_add_surface_destroy_listener(struct wl_resource *surface)
+{
+ struct wl_listener *destroy_listener = NULL;
+ Eina_List *l;
+ struct wl_resource *surface_data;
+
+ if (!surface) return TIZEN_KEYROUTER_ERROR_NONE;
+
+ EINA_LIST_FOREACH(krt->grab_surface_list, l, surface_data)
+ {
+ if (surface_data)
+ {
+ if (surface_data == surface)
+ {
+ return TIZEN_KEYROUTER_ERROR_NONE;
+ }
+ }
+ }
+
+ destroy_listener = E_NEW(struct wl_listener, 1);
+
+ if (!destroy_listener)
+ {
+ KLERR("Failed to allocate memory for wl_surface destroy listener !");
+ return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
+ }
+
+ destroy_listener->notify = _e_keyrouter_wl_surface_cb_destroy;
+ wl_resource_add_destroy_listener(surface, destroy_listener);
+ krt->grab_surface_list = eina_list_append(krt->grab_surface_list, surface);
+
+ return TIZEN_KEYROUTER_ERROR_NONE;
+}
+
+#ifdef HAVE_CYNARA
+static void
+_e_keyrouter_wl_util_cynara_log(const char *func_name, int err)
+{
+#define CYNARA_BUFSIZE 128
+ char buf[CYNARA_BUFSIZE] = "\0";
+ int ret;
+
+ ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
+ if (ret != CYNARA_API_SUCCESS)
+ {
+ KLWRN("Failed to cynara_strerror: %d (error log about %s: %d)", ret, func_name, err);
+ return;
+ }
+ KLWRN("%s is failed: %s", func_name, buf);
+}
+
+Eina_Bool
+e_keyrouter_wl_util_do_privilege_check(struct wl_client *client, uint32_t mode, uint32_t keycode)
+{
+ int ret, retry_cnt=0, len=0;
+ char *clientSmack=NULL, *client_session=NULL, uid2[16]={0, };
+ Eina_Bool res = EINA_FALSE;
+ Eina_List *l;
+ struct wl_client *wc_data;
+ static Eina_Bool retried = EINA_FALSE;
+ pid_t pid = 0;
+ uid_t uid = 0;
+ gid_t gid = 0;
+
+ /* Top position grab is always allowed. This mode do not need privilege.*/
+ if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
+ return EINA_TRUE;
+
+ if (krt->HardKeys[keycode].no_privcheck == EINA_TRUE)
+ return EINA_TRUE;
+
+ if (!client) return EINA_FALSE;
+
+ /* If initialize cynara is failed, allow keygrabs regardless of the previlege permition. */
+ if (krt->p_cynara == NULL)
+ {
+ if (retried == EINA_FALSE)
+ {
+ retried = EINA_TRUE;
+ for(retry_cnt = 0; retry_cnt < 5; retry_cnt++)
+ {
+ KLDBG("Retry cynara initialize: %d", retry_cnt+1);
+ ret = cynara_initialize(&krt->p_cynara, NULL);
+ if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
+ {
+ _e_keyrouter_wl_util_cynara_log("cynara_initialize", ret);
+ krt->p_cynara = NULL;
+ }
+ else
+ {
+ KLDBG("Success cynara initialize to try %d times", retry_cnt+1);
+ break;
+ }
+ }
+ }
+ return EINA_TRUE;
+ }
+
+ EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
+ {
+ if (wc_data == client)
+ {
+ res = EINA_TRUE;
+ goto finish;
+ }
+ }
+
+ wl_client_get_credentials(client, &pid, &uid, &gid);
+
+ len = smack_new_label_from_process((int)pid, &clientSmack);
+ if (len <= 0) goto finish;
+
+ snprintf(uid2, 15, "%d", (int)uid);
+ client_session = cynara_session_from_pid(pid);
+
+ ret = cynara_check(krt->p_cynara, clientSmack, client_session, uid2, "http://tizen.org/privilege/keygrab");
+ if (CYNARA_API_ACCESS_ALLOWED == ret)
+ {
+ res = EINA_TRUE;
+ }
+ else
+ {
+ KLINF("Fail to check cynara, error : %d (pid : %d)", ret, pid);
+ }
+finish:
+ if (client_session) E_FREE(client_session);
+ if (clientSmack) E_FREE(clientSmack);
+
+ return res;
+}
+#endif
+
+Eina_Bool
+e_keyrouter_wl_init(void)
+{
+ int ret;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(krt, EINA_FALSE);
+
+ krt->global = wl_global_create(e_comp_wl->wl.disp, &tizen_keyrouter_interface, 1, krt, _e_keyrouter_cb_bind);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(krt->global, EINA_FALSE);
+
+#ifdef HAVE_CYNARA
+ ret = cynara_initialize(&krt->p_cynara, NULL);
+ if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
+ {
+ _e_keyrouter_wl_util_cynara_log("cynara_initialize", ret);
+ krt->p_cynara = NULL;
+ }
+#endif
+
+ return EINA_TRUE;
+}
+
+void
+e_keyrouter_wl_shutdown(void)
+{
+ Eina_List *l, *l_next;
+ struct wl_resource *resource;
+ struct wl_client *client;
+ struct wl_listener *destroy_listener;
+
+ EINA_SAFETY_ON_NULL_RETURN(krt);
+
+ EINA_LIST_FOREACH_SAFE(krt->grab_client_list, l, l_next, client)
+ {
+ destroy_listener = wl_client_get_destroy_listener(client, _e_keyrouter_wl_client_cb_destroy);
+ if (destroy_listener)
+ {
+ wl_list_remove(&destroy_listener->link);
+ E_FREE(destroy_listener);
+ }
+ krt->grab_client_list = eina_list_remove(krt->grab_client_list, client);
+ }
+ EINA_LIST_FOREACH_SAFE(krt->grab_surface_list, l, l_next, resource)
+ {
+ destroy_listener = wl_resource_get_destroy_listener(resource, _e_keyrouter_wl_surface_cb_destroy);
+ if (destroy_listener)
+ {
+ wl_list_remove(&destroy_listener->link);
+ E_FREE(destroy_listener);
+ }
+ krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, client);
+ }
+
+ EINA_LIST_FREE(krt->resources, resource)
+ wl_resource_destroy(resource);
+
+ if (krt->global) wl_global_destroy(krt->global);
+
+#ifdef HAVE_CYNARA
+ if (krt->p_cynara) cynara_finish(krt->p_cynara);
+#endif
+}
_e_main_shutdown_push(_e_main_screens_shutdown);
TRACE_DS_END();
+ TSB("E_Keyrouter Init");
+ if (!e_keyrouter_init())
+ {
+ e_error_message_show(_("Enlightenment cannot set up its keyrouting system.\n"));
+ goto failed;
+ }
+ TSE("E_Keyrouter Init Done");
+ _e_main_shutdown_push(e_keyrouter_shutdown);
+
if (e_config->eom_enable)
{
TSB("Eom Init");