keyrouter: Refactor out ds_tizen_keyrouter 26/278226/1
authorSeunghun Lee <shiin.lee@samsung.com>
Fri, 10 Jun 2022 05:42:22 +0000 (14:42 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 18 Jul 2022 05:59:02 +0000 (14:59 +0900)
Change-Id: I35add1ab1c81c8589789708b8ef38f4693cc1ee2

include/libds-tizen/keyrouter.h
src/keyrouter/keyrouter.c
src/keyrouter/keyrouter.h
src/keyrouter/keyrouter_grab.c

index a870003..bd47b54 100644 (file)
@@ -7,15 +7,70 @@
 extern "C" {
 #endif
 
+/**
+ * A handle for accessing ds_tizen_keyrouter.
+ */
 struct ds_tizen_keyrouter;
 
+/**
+ * The information of keyroute
+ */
+struct ds_tizen_keyroute_info
+{
+    struct wl_client *wl_client;
+};
+
+/**
+ * Keyroute mode of keyroutes returned by ds_tizen_keyrouter_get_keyroutes()
+ * for a given keycode.
+ */
+enum ds_tizen_keyroute_mode {
+    /**
+     * The keycode is not under any keyroute mode.
+     * The compositor may send a keycode to a focused wayland cliet as usual.
+     */
+    DS_TIZEN_KEYROUTE_MODE_NONE,
+    /**
+     * Exclusive mode means that a given keycode is required to be sent
+     * exclusively to wayland clients of returned keyroutes. So the compositor
+     * must not send this keycode to any other wayland clients except for
+     * returned wayland clients.
+     */
+    DS_TIZEN_KEYROUTE_MODE_EXCLUSIVE,
+    /**
+     * The keycode is required to be shared with returned wayland clients.
+     * The compositor must send the keycode not only to returned wayland
+     * clients, but also to a focused wayland client.
+     */
+    DS_TIZEN_KEYROUTE_MODE_SHARED,
+};
+
+/**
+ * Creates a ds_tizen_keyrouter.
+ */
 struct ds_tizen_keyrouter *
 ds_tizen_keyrouter_create(struct wl_display *display);
 
+/**
+ * Adds destroy listener of ds_tizen_keyrouter
+ */
 void
 ds_tizen_keyrouter_add_destroy_listener(struct ds_tizen_keyrouter *keyrouter,
         struct wl_listener *listener);
 
+/**
+ * Gets keyroutes and mode for a given keycode.
+ * The compositor must send a keycode to returned wayland clients according to
+ * the mode. The parameter, topmost_client, should be given to determine whether
+ * the given topmost_client require a keycode exclusively when one of its
+ * surfaces is on very top of stack. See tizen_keyrouter protocol in
+ * tizen-extension.xml for more detail.
+ */
+enum ds_tizen_keyroute_mode
+ds_tizen_keyrouter_get_keyroutes(struct ds_tizen_keyrouter *keyrouter,
+        int keycode, struct wl_client *topmost_client,
+        struct wl_array *keyroutes);
+
 #ifdef __cplusplus
 }
 #endif
index 730b8a8..4bcee93 100644 (file)
 #define TIZEN_KEYROUTER_VERSION 2
 #define TIZEN_KEYROUTER_PRIVILEGE "http://tizen.org/privilege/keygrab"
 
-static void
-keyrouter_bind(struct wl_client *wl_client, void *data, uint32_t version,
-        uint32_t id);
+static void keyrouter_bind(struct wl_client *wl_client, void *data,
+        uint32_t version, uint32_t id);
+static void keyrouter_handle_display_destroy(struct wl_listener *listener,
+        void *data);
+static void keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter);
+static void create_keyrouter_client(struct ds_tizen_keyrouter *keyrouter,
+        struct wl_client *wl_client, uint32_t version, uint32_t id);
+static void destroy_keyrouter_client(struct keyrouter_client *client);
 static bool
-keyrouter_check_privilege(struct ds_tizen_keyrouter_client *client,
-        struct wl_client *wl_client, uint32_t mode, uint32_t keycode);
-static void
-keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter);
-
-static void
-keyrouter_handle_display_destroy(struct wl_listener *listener, void *data)
-{
-    struct ds_tizen_keyrouter *keyrouter;
-
-    keyrouter = wl_container_of(listener, keyrouter, display_destroy);
-
-    ds_inf("Global destroy: ds_tizen_keyrouter(%p)", keyrouter);
-
-    wl_signal_emit(&keyrouter->events.destroy, keyrouter);
-
-    if (keyrouter->security_initialized)
-        tizen_security_finish();
-
-    free(keyrouter->opts);
-
-    wl_list_remove(&keyrouter->display_destroy.link);
-
-    wl_global_destroy(keyrouter->global);
-
-    keyrouter_grab_destroy(keyrouter->keygrab);
-
-    free(keyrouter);
-}
+keyrouter_client_check_privilege(struct keyrouter_client *client, uint32_t mode,
+        uint32_t keycode);
+static int keyrouter_client_grab_key(struct keyrouter_client *client, int mode,
+        int keycode);
+static int keyrouter_client_ungrab_key(struct keyrouter_client *client,
+        int keycode);
 
 WL_EXPORT struct ds_tizen_keyrouter *
 ds_tizen_keyrouter_create(struct wl_display *display)
@@ -57,21 +39,15 @@ ds_tizen_keyrouter_create(struct wl_display *display)
         return NULL;
     }
 
-    keyrouter->keygrab = keyrouter_grab_create();
-    if (keyrouter->keygrab == NULL) {
-        ds_err("Failed to create keyrouter.");
-        free(keyrouter);
-        return NULL;
-    }
-
     keyrouter->global = wl_global_create(display, &tizen_keyrouter_interface,
             TIZEN_KEYROUTER_VERSION, keyrouter, keyrouter_bind);
     if (!keyrouter->global) {
-        keyrouter_grab_destroy(keyrouter->keygrab);
         free(keyrouter);
         return NULL;
     }
 
+    keyrouter_grab_init(&keyrouter->keygrab);
+
     wl_list_init(&keyrouter->clients);
 
     wl_signal_init(&keyrouter->events.destroy);
@@ -99,70 +75,43 @@ ds_tizen_keyrouter_add_destroy_listener(struct ds_tizen_keyrouter *keyrouter,
     wl_signal_add(&keyrouter->events.destroy, listener);
 }
 
+WL_EXPORT enum ds_tizen_keyroute_mode
+ds_tizen_keyrouter_get_keyroutes(struct ds_tizen_keyrouter *keyrouter,
+        int keycode, struct wl_client *topmost_client,
+        struct wl_array *keyroutes)
+{
+    return keyrouter_grab_get_keyroutes(&keyrouter->keygrab,
+            keycode, topmost_client, keyroutes);
+}
+
 static void
-keyrouter_handle_keygrab_set(struct wl_client *wl_client,
+keyrouter_client_handle_set_keygrab(struct wl_client *wl_client,
         struct wl_resource *resource, struct wl_resource *surface,
         uint32_t key, uint32_t mode)
 {
-    struct ds_tizen_keyrouter_client *client;
-    struct ds_tizen_keyrouter *keyrouter;
-    int res = TIZEN_KEYROUTER_ERROR_NONE;
-    bool ret;
+    struct keyrouter_client *client;
+    int err;
 
     client = wl_resource_get_user_data(resource);
-    keyrouter = client->keyrouter;
-
-    ret = keyrouter_check_privilege(client, wl_client, mode, key);
-    if (ret == false) {
-        tizen_keyrouter_send_keygrab_notify(resource, surface,
-            key, mode, TIZEN_KEYROUTER_ERROR_NO_PERMISSION);
-        return;
-    }
-
-    res = keyrouter_grab_grab_key(keyrouter->keygrab,
-        mode, key, (void *)wl_client);
-
-    tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res);
+    err = keyrouter_client_grab_key(client, mode, key);
+    tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, err);
 }
 
 static void
-keyrouter_handle_keygrab_unset(struct wl_client *wl_client,
+keyrouter_client_handle_unset_keygrab(struct wl_client *wl_client,
         struct wl_resource *resource, struct wl_resource *surface,  uint32_t key)
 {
-    struct ds_tizen_keyrouter_client *client;
-    struct ds_tizen_keyrouter *keyrouter;
-    int res = TIZEN_KEYROUTER_ERROR_NONE;
-    bool ret;
+    struct keyrouter_client *client;
+    int err;
 
     client = wl_resource_get_user_data(resource);
-    keyrouter = client->keyrouter;
-
-    /* ungrab TOP POSITION grab first, this grab mode is not check privilege */
-    keyrouter_grab_ungrab_key(keyrouter->keygrab,
-        TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)wl_client);
-
-    ret = keyrouter_check_privilege(client,
-        wl_client, TIZEN_KEYROUTER_MODE_NONE, key);
-    if (ret == false) {
-        tizen_keyrouter_send_keygrab_notify(resource, surface, key,
-            TIZEN_KEYROUTER_MODE_NONE, TIZEN_KEYROUTER_ERROR_NO_PERMISSION);
-        return;
-    }
-
-    keyrouter_grab_ungrab_key(keyrouter->keygrab,
-        TIZEN_KEYROUTER_MODE_EXCLUSIVE, key, (void *)wl_client);
-    keyrouter_grab_ungrab_key(keyrouter->keygrab,
-        TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, key, (void *)wl_client);
-    keyrouter_grab_ungrab_key(keyrouter->keygrab,
-        TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)wl_client);
-    keyrouter_grab_ungrab_key(keyrouter->keygrab,
-        TIZEN_KEYROUTER_MODE_SHARED, key, (void *)wl_client);
-
-    tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res);
+    err = keyrouter_client_ungrab_key(client, key);
+    tizen_keyrouter_send_keygrab_notify(resource, surface, key,
+            TIZEN_KEYROUTER_MODE_NONE, err);
 }
 
 static void
-keyrouter_handle_get_keygrab_status(struct wl_client *wl_client,
+keyrouter_client_handle_get_keygrab_status(struct wl_client *wl_client,
         struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
 {
     tizen_keyrouter_send_keygrab_notify(resource, surface, key,
@@ -172,29 +121,22 @@ keyrouter_handle_get_keygrab_status(struct wl_client *wl_client,
 static int
 keyrouter_get_array_length(const struct wl_array *array)
 {
-    int *data = NULL;
+    int *data;
     int count = 0;
 
-    wl_array_for_each(data, array) {
+    wl_array_for_each(data, array)
         count++;
-    }
 
     return count;
 }
 
 static void
-keyrouter_handle_keygrab_set_list(struct wl_client *wl_client,
+keyrouter_client_handle_set_keygrab_list(struct wl_client *wl_client,
         struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
 {
-    struct ds_tizen_keyrouter_client *client;
-    struct ds_tizen_keyrouter *keyrouter;
+    struct keyrouter_client *client;
+    struct ds_tizen_grab_data *grab_data;
     struct wl_array *return_list;
-    struct ds_tizen_grab_data *grab_data = NULL;
-    int res = TIZEN_KEYROUTER_ERROR_NONE;
-    bool ret;
-
-    client = wl_resource_get_user_data(resource);
-    keyrouter = client->keyrouter;
 
     if ((keyrouter_get_array_length(grab_list) % 3) != 0) {
         ds_err("Invalid keycode and grab mode pair. Check arguments in a list.");
@@ -202,16 +144,11 @@ keyrouter_handle_keygrab_set_list(struct wl_client *wl_client,
         return;
     }
 
+    client = wl_resource_get_user_data(resource);
+
     wl_array_for_each(grab_data, grab_list) {
-        ret = keyrouter_check_privilege(client, wl_client, grab_data->mode, grab_data->key);
-        if (ret == false) {
-            grab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
-        } else {
-            res = keyrouter_grab_grab_key(keyrouter->keygrab,
-                grab_data->mode, grab_data->key, (void *)wl_client);
-
-            grab_data->err = res;
-        }
+        grab_data->err = keyrouter_client_grab_key(client, grab_data->mode,
+                grab_data->key);
     }
 
     return_list = grab_list;
@@ -220,18 +157,13 @@ keyrouter_handle_keygrab_set_list(struct wl_client *wl_client,
 }
 
 static void
-keyrouter_handle_keygrab_unset_list(struct wl_client *wl_client,
+keyrouter_client_handle_unset_keygrab_list(struct wl_client *wl_client,
         struct wl_resource *resource, struct wl_resource *surface,
         struct wl_array *ungrab_list)
 {
-    struct ds_tizen_keyrouter_client *client;
-    struct ds_tizen_keyrouter *keyrouter;
-    struct wl_array *return_list = NULL;
-    struct ds_tizen_ungrab_data *ungrab_data = NULL;
-    bool ret;
-
-    client = wl_resource_get_user_data(resource);
-    keyrouter = client->keyrouter;
+    struct keyrouter_client *client;
+    struct wl_array *return_list;
+    struct ds_tizen_ungrab_data *ungrab_data;
 
     if ((keyrouter_get_array_length(ungrab_list) % 3) != 0) {
         ds_err("Invalid keycode and grab mode pair. Check arguments in a list.");
@@ -239,29 +171,11 @@ keyrouter_handle_keygrab_unset_list(struct wl_client *wl_client,
         return;
     }
 
-    wl_array_for_each(ungrab_data, ungrab_list) {
-        keyrouter_grab_ungrab_key(keyrouter->keygrab,
-            TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)wl_client);
-
-        ret = keyrouter_check_privilege(client, wl_client,
-            TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key);
-        if (!ret) {
-            ungrab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
-        } else {
-            keyrouter_grab_ungrab_key(keyrouter->keygrab,
-                TIZEN_KEYROUTER_MODE_EXCLUSIVE, ungrab_data->key, (void *)wl_client);
-
-            keyrouter_grab_ungrab_key(keyrouter->keygrab,
-                TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, ungrab_data->key, (void *)wl_client);
-
-            keyrouter_grab_ungrab_key(keyrouter->keygrab,
-                TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)wl_client);
-
-            keyrouter_grab_ungrab_key(keyrouter->keygrab,
-                TIZEN_KEYROUTER_MODE_SHARED, ungrab_data->key, (void *)wl_client);
+    client = wl_resource_get_user_data(resource);
 
-            ungrab_data->err = TIZEN_KEYROUTER_ERROR_NONE;
-        }
+    wl_array_for_each(ungrab_data, ungrab_list) {
+        ungrab_data->err = keyrouter_client_ungrab_key(client,
+                ungrab_data->key);
     }
 
     return_list = ungrab_list;
@@ -270,14 +184,14 @@ keyrouter_handle_keygrab_unset_list(struct wl_client *wl_client,
 }
 
 static void
-keyrouter_handle_get_keygrab_list(struct wl_client *wl_client,
+keyrouter_client_handle_get_keygrab_list(struct wl_client *wl_client,
         struct wl_resource *resource, struct wl_resource *surface)
 {
     tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL);
 }
 
 static void
-keyrouter_handle_set_register_none_key(struct wl_client *wl_client,
+keyrouter_client_handle_set_register_none_key(struct wl_client *wl_client,
         struct wl_resource *resource, struct wl_resource *surface,
         uint32_t data)
 {
@@ -285,14 +199,14 @@ keyrouter_handle_set_register_none_key(struct wl_client *wl_client,
 }
 
 static void
-keyrouter_handle_get_keyregister_status(struct wl_client *wl_client,
+keyrouter_client_handle_get_keyregister_status(struct wl_client *wl_client,
         struct wl_resource *resource, uint32_t key)
 {
     tizen_keyrouter_send_keyregister_notify(resource, (int)false);
 }
 
 static void
-keyrouter_handle_set_input_config(struct wl_client *wl_client,
+keyrouter_client_handle_set_input_config(struct wl_client *wl_client,
         struct wl_resource *resource, struct wl_resource *surface,
         uint32_t config_mode, uint32_t value)
 {
@@ -300,32 +214,32 @@ keyrouter_handle_set_input_config(struct wl_client *wl_client,
 }
 
 static void
-keyrouter_handle_destory(struct wl_client *wl_client,
+keyrouter_client_handle_destroy(struct wl_client *wl_client,
         struct wl_resource *resource)
 {
     wl_resource_destroy(resource);
 }
 
 static const struct tizen_keyrouter_interface tizen_keyrouter_impl = {
-   keyrouter_handle_keygrab_set,
-   keyrouter_handle_keygrab_unset,
-   keyrouter_handle_get_keygrab_status,
-   keyrouter_handle_keygrab_set_list,
-   keyrouter_handle_keygrab_unset_list,
-   keyrouter_handle_get_keygrab_list,
-   keyrouter_handle_set_register_none_key,
-   keyrouter_handle_get_keyregister_status,
-   keyrouter_handle_set_input_config,
-   keyrouter_handle_destory
+   .set_keygrab = keyrouter_client_handle_set_keygrab,
+   .unset_keygrab = keyrouter_client_handle_unset_keygrab,
+   .get_keygrab_status = keyrouter_client_handle_get_keygrab_status,
+   .set_keygrab_list = keyrouter_client_handle_set_keygrab_list,
+   .unset_keygrab_list = keyrouter_client_handle_unset_keygrab_list,
+   .get_keygrab_list = keyrouter_client_handle_get_keygrab_list,
+   .set_register_none_key = keyrouter_client_handle_set_register_none_key,
+   .get_keyregister_status = keyrouter_client_handle_get_keyregister_status,
+   .set_input_config = keyrouter_client_handle_set_input_config,
+   .destroy = keyrouter_client_handle_destroy
 };
 
 static void
-keyrouter_handle_resource_destory(struct wl_resource *resource)
+keyrouter_client_handle_resource_destroy(struct wl_resource *resource)
 {
-    struct ds_tizen_keyrouter_client *client = wl_resource_get_user_data(resource);
+    struct keyrouter_client *client;
 
-    wl_list_remove(&client->link);
-    free(client);
+    client = wl_resource_get_user_data(resource);
+    destroy_keyrouter_client(client);
 }
 
 static void
@@ -333,61 +247,33 @@ keyrouter_bind(struct wl_client *wl_client, void *data, uint32_t version,
         uint32_t id)
 {
     struct ds_tizen_keyrouter *keyrouter = data;
-    struct ds_tizen_keyrouter_client *client;
-
-    client = calloc(1, sizeof *client);
-    if (client == NULL) {
-        wl_client_post_no_memory(wl_client);
-        return;
-    }
-
-    client->keyrouter = keyrouter;
-    client->resource =
-        wl_resource_create(wl_client, &tizen_keyrouter_interface,
-                MIN(version, TIZEN_KEYROUTER_VERSION), id);
-    if (client->resource == NULL) {
-        ds_err("wl_resource_create() failed.(version :%d, id:%d)", version, id);
-        free(client);
-        wl_client_post_no_memory(wl_client);
-        return;
-    }
 
-    wl_resource_set_implementation(client->resource, &tizen_keyrouter_impl,
-        client, keyrouter_handle_resource_destory);
-
-    wl_list_insert(&keyrouter->clients, &client->link);
+    create_keyrouter_client(keyrouter, wl_client, version, id);
 }
 
-static bool
-keyrouter_check_privilege(struct ds_tizen_keyrouter_client *client,
-        struct wl_client *wl_client, uint32_t mode, uint32_t keycode)
+static void
+keyrouter_handle_display_destroy(struct wl_listener *listener, void *data)
 {
-    struct ds_tizen_keyrouter *keyrouter = client->keyrouter;
+    struct ds_tizen_keyrouter *keyrouter;
 
-    pid_t pid = 0;
-    uid_t uid = 0;
-    gid_t gid = 0;
+    keyrouter = wl_container_of(listener, keyrouter, display_destroy);
 
-    /* Top position grab is always allowed. This mode do not need privilege.*/
-    if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
-        return true;
+    ds_inf("Global destroy: ds_tizen_keyrouter(%p)", keyrouter);
 
-    // check no privilege option on the keycode
-    if (keyrouter->opts) {
-        if (keyrouter->opts[keycode].no_privilege)
-            return true;
-    }
+    wl_signal_emit(&keyrouter->events.destroy, keyrouter);
 
-    // already checked the privilege before.
-    if (client->privileged)
-        return true;
+    if (keyrouter->security_initialized)
+        tizen_security_finish();
 
-    wl_client_get_credentials(wl_client, &pid, &uid, &gid);
+    free(keyrouter->opts);
 
-    client->privileged = tizen_security_check_privilege(pid, uid,
-            TIZEN_KEYROUTER_PRIVILEGE);
+    wl_list_remove(&keyrouter->display_destroy.link);
 
-    return client->privileged;
+    wl_global_destroy(keyrouter->global);
+
+    keyrouter_grab_finish(&keyrouter->keygrab);
+
+    free(keyrouter);
 }
 
 static void
@@ -398,7 +284,7 @@ keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter)
     char *ret, *tmp, *buf_ptr, buf[1024] = {0,};
 
     keyrouter->opts = calloc(KEYROUTER_MAX_KEYS,
-        sizeof(struct ds_tizen_keyrouter_key_options));
+            sizeof(struct keyrouter_key_options));
     if (!keyrouter->opts) {
         return;
     }
@@ -433,3 +319,107 @@ keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter)
 
     fclose(file);
 }
+
+static void
+create_keyrouter_client(struct ds_tizen_keyrouter *keyrouter,
+        struct wl_client *wl_client, uint32_t version, uint32_t id)
+{
+    struct keyrouter_client *client;
+
+    client = calloc(1, sizeof *client);
+    if (!client) {
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    client->keyrouter = keyrouter;
+    client->wl_client = wl_client;
+    client->resource = wl_resource_create(wl_client, &tizen_keyrouter_interface,
+            MIN(version, TIZEN_KEYROUTER_VERSION), id);
+    if (!client->resource) {
+        ds_err("wl_resource_create() failed. (version :%d, id:%d)",
+                version, id);
+        free(client);
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    wl_resource_set_implementation(client->resource, &tizen_keyrouter_impl,
+            client, keyrouter_client_handle_resource_destroy);
+
+    wl_list_insert(&keyrouter->clients, &client->link);
+}
+
+static void
+destroy_keyrouter_client(struct keyrouter_client *client)
+{
+    wl_list_remove(&client->link);
+    free(client);
+}
+
+static bool
+keyrouter_client_check_privilege(struct keyrouter_client *client, uint32_t mode,
+        uint32_t keycode)
+{
+    struct ds_tizen_keyrouter *keyrouter = client->keyrouter;
+    pid_t pid = 0;
+    uid_t uid = 0;
+
+    /* Top position grab is always allowed. This mode do not need privilege.*/
+    if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
+        return true;
+
+    // check no privilege option on the keycode
+    if (keyrouter->opts && keyrouter->opts[keycode].no_privilege)
+        return true;
+
+    // already checked the privilege before.
+    if (client->privileged)
+        return true;
+
+    wl_client_get_credentials(client->wl_client, &pid, &uid, NULL);
+
+    client->privileged = tizen_security_check_privilege(pid, uid,
+            TIZEN_KEYROUTER_PRIVILEGE);
+
+    return client->privileged;
+}
+
+static int
+keyrouter_client_grab_key(struct keyrouter_client *client, int mode,
+        int keycode)
+{
+    struct ds_tizen_keyrouter *keyrouter = client->keyrouter;
+
+    if (!keyrouter_client_check_privilege(client, mode, keycode))
+        return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
+
+    return keyrouter_grab_grab_key(&keyrouter->keygrab, mode, keycode,
+            client->wl_client);
+}
+
+static int
+keyrouter_client_ungrab_key(struct keyrouter_client *client, int keycode)
+{
+    struct ds_tizen_keyrouter *keyrouter = client->keyrouter;
+
+    /* ungrab TOP POSITION grab first, this grab mode is not check privilege */
+    keyrouter_grab_ungrab_key(&keyrouter->keygrab,
+        TIZEN_KEYROUTER_MODE_TOPMOST, keycode, client->wl_client);
+
+    if (!keyrouter_client_check_privilege(client, TIZEN_KEYROUTER_MODE_NONE,
+                keycode))
+        return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
+
+    keyrouter_grab_ungrab_key(&keyrouter->keygrab,
+        TIZEN_KEYROUTER_MODE_EXCLUSIVE, keycode, client->wl_client);
+    keyrouter_grab_ungrab_key(&keyrouter->keygrab,
+        TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, keycode,
+        client->wl_client);
+    keyrouter_grab_ungrab_key(&keyrouter->keygrab,
+        TIZEN_KEYROUTER_MODE_TOPMOST, keycode, client->wl_client);
+    keyrouter_grab_ungrab_key(&keyrouter->keygrab,
+        TIZEN_KEYROUTER_MODE_SHARED, keycode, client->wl_client);
+
+    return TIZEN_KEYROUTER_ERROR_NONE;
+}
index 11fbadc..bea9ab1 100644 (file)
@@ -5,37 +5,34 @@
 #include <wayland-server.h>
 #include <tizen-extension-server-protocol.h>
 
+#include "libds-tizen/keyrouter.h"
+
 #define KEYROUTER_MAX_KEYS 512
 
-struct ds_tizen_keyrouter_key_info
+struct keyroute_info
 {
-       void *data;
-       struct wl_list link;
+    struct wl_client *wl_client;
+    struct wl_list link;
 };
 
-struct ds_tizen_keyrouter_grabbed
+struct keyrouter_grabbed
 {
-    int keycode;
-
     struct {
-        struct wl_list excl;
-        struct wl_list or_excl;
-        struct wl_list top;
-        struct wl_list shared;
+        struct wl_list excl; // keyroute_info::link
+        struct wl_list or_excl; // keyroute_info::link
+        struct wl_list top; // keyroute_info::link
+        struct wl_list shared; // keyroute_info::link
     } grab;
 
     struct wl_list pressed;
 };
 
-struct ds_tizen_keyrouter_grab
+struct keyrouter_grab
 {
-    struct ds_tizen_keyrouter_grabbed *hard_keys;
-
-    void *focus_client;
-    void *top_client;
+    struct keyrouter_grabbed hard_keys[KEYROUTER_MAX_KEYS];
 };
 
-struct ds_tizen_keyrouter_key_options
+struct keyrouter_key_options
 {
     bool enabled;
     bool no_privilege;
@@ -53,18 +50,19 @@ struct ds_tizen_keyrouter
         struct wl_signal destroy;
     } events;
 
-    struct ds_tizen_keyrouter_key_options *opts;
+    struct keyrouter_key_options *opts;
 
-    struct ds_tizen_keyrouter_grab *keygrab;
+    struct keyrouter_grab keygrab;
 
     bool security_initialized;
 };
 
-struct ds_tizen_keyrouter_client
+struct keyrouter_client
 {
     struct ds_tizen_keyrouter *keyrouter;
 
     struct wl_resource *resource;
+    struct wl_client *wl_client;
 
     bool privileged;
 
@@ -84,27 +82,18 @@ struct ds_tizen_ungrab_data
        int err;
 };
 
-struct ds_tizen_keyrouter_grab *
-keyrouter_grab_create(void);
-void
-keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keygrab);
-int
-keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keygrab,
-        int type, int keycode, void *data);
-void
-keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keygrab,
-        int type, int keycode, void *data);
-int
-keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keygrab,
-        int keycode, int pressed, struct wl_list *delivery_list);
-void
-keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keygrab,
-        void *focus_client);
-void
-keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keygrab,
-        void *top_client);
-bool
-keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keygrab,
-        int keycode);
+void keyrouter_grab_init(struct keyrouter_grab *keygrab);
+
+void keyrouter_grab_finish(struct keyrouter_grab *keygrab);
+
+int keyrouter_grab_grab_key(struct keyrouter_grab *keygrab, int mode,
+        int keycode, struct wl_client *wl_client);
+
+void keyrouter_grab_ungrab_key(struct keyrouter_grab *keygrab, int mode,
+        int keycode, struct wl_client *wl_client);
+
+enum ds_tizen_keyroute_mode
+keyrouter_grab_get_keyroutes(struct keyrouter_grab *keygrab, int keycode,
+        struct wl_client *topmost_client, struct wl_array *keyroutes);
 
 #endif
index ae29e8e..fed301b 100644 (file)
@@ -1,3 +1,4 @@
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 
 #include "keyrouter.h"
 
+#define KEYGRAB_IS_VALID_KEYCODE(code) \
+    ((code > 0) && (code < KEYROUTER_MAX_KEYS))
+#define KEYGRAB_LIST_FIRST(head, sample, member) \
+    wl_container_of((head)->next, sample, member)
+
 static struct wl_list *
-keyrouter_grab_get_grabbed_list(struct ds_tizen_keyrouter_grab *keygrab,
-        int type, int keycode)
+keyrouter_grab_get_mode_list(struct keyrouter_grab *keygrab, int mode,
+        int keycode);
+static void mode_list_clean(struct wl_list *list);
+static void mode_list_remove_wl_client(struct wl_list *list,
+        struct wl_client *wl_client);
+static bool mode_list_check_duplicated(struct wl_list *list,
+        struct wl_client *wl_client);
+static struct keyroute_info *create_keyroute_info(struct wl_client *wl_client);
+static void destroy_key_info(struct keyroute_info *info);
+static struct keyroute_info *
+keyrouter_grab_get_exclusive_first(struct keyrouter_grab *keygrab, int keycode);
+static struct keyroute_info *
+keyrouter_grab_get_overridable_exclusive_first(struct keyrouter_grab *keygrab,
+        int keycode);
+static struct keyroute_info *
+keyrouter_grab_topmost_find(struct keyrouter_grab *keygrab, int keycode,
+        struct wl_client *topmost_client);
+static bool keyrouter_grab_get_shared_keyroutes(struct keyrouter_grab *keygrab,
+        int keycode, struct wl_array *keyroutes);
+static bool keyroutes_add_info(struct wl_array *keyroutes,
+        struct wl_client *wl_client);
+
+void
+keyrouter_grab_init(struct keyrouter_grab *keygrab)
 {
-    switch(type) {
-        case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
-            return &keygrab->hard_keys[keycode].grab.excl;
-        case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
-            return &keygrab->hard_keys[keycode].grab.or_excl;
-        case TIZEN_KEYROUTER_MODE_TOPMOST:
-            return &keygrab->hard_keys[keycode].grab.top;
-        case TIZEN_KEYROUTER_MODE_SHARED:
-            return &keygrab->hard_keys[keycode].grab.shared;
-        default:
-            return NULL;
+    for (size_t i = 0; i < KEYROUTER_MAX_KEYS; i++) {
+        wl_list_init(&keygrab->hard_keys[i].grab.excl);
+        wl_list_init(&keygrab->hard_keys[i].grab.or_excl);
+        wl_list_init(&keygrab->hard_keys[i].grab.top);
+        wl_list_init(&keygrab->hard_keys[i].grab.shared);
+        wl_list_init(&keygrab->hard_keys[i].pressed);
     }
 }
 
-bool
-keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keygrab, int keycode)
+void
+keyrouter_grab_finish(struct keyrouter_grab *keygrab)
 {
-    struct wl_list *list;
+    for (size_t i = 0; i < KEYROUTER_MAX_KEYS; i++) {
+        mode_list_clean(&keygrab->hard_keys[i].grab.excl);
+        mode_list_clean(&keygrab->hard_keys[i].grab.or_excl);
+        mode_list_clean(&keygrab->hard_keys[i].grab.top);
+        mode_list_clean(&keygrab->hard_keys[i].grab.shared);
+        mode_list_clean(&keygrab->hard_keys[i].pressed);
+    }
+}
 
-    list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_EXCLUSIVE, keycode);
-    if (list && !wl_list_empty(list))
-        return true;
+enum ds_tizen_keyroute_mode
+keyrouter_grab_get_keyroutes(struct keyrouter_grab *keygrab, int keycode,
+        struct wl_client *topmost_client, struct wl_array *keyroutes)
+{
+    struct keyroute_info *info;
 
-    list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, keycode);
-    if (list && !wl_list_empty(list))
-        return true;
+    if (!KEYGRAB_IS_VALID_KEYCODE(keycode)) {
+        ds_err("Invalid keycode(%d)", keycode);
+        goto none_out;
+    }
 
-    list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_TOPMOST, keycode);
-    if (list && !wl_list_empty(list))
-        return true;
+    info = keyrouter_grab_get_exclusive_first(keygrab, keycode);
+    if (info)
+        goto exclusive_out;
 
-    list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_SHARED, keycode);
-    if (list && !wl_list_empty(list))
-        return true;
+    info = keyrouter_grab_get_overridable_exclusive_first(keygrab, keycode);
+    if (info)
+        goto exclusive_out;
 
-    return false;
-}
+    info = keyrouter_grab_topmost_find(keygrab, keycode, topmost_client);
+    if (info)
+        goto exclusive_out;
 
-static bool
-keyrouter_grab_check_duplicated_data(struct wl_list *list, void *data)
-{
-    struct ds_tizen_keyrouter_key_info *info;
+    if (keyrouter_grab_get_shared_keyroutes(keygrab, keycode, keyroutes))
+        return DS_TIZEN_KEYROUTE_MODE_SHARED;
 
-    if (wl_list_empty(list))
-        return false;
+none_out:
+    return DS_TIZEN_KEYROUTE_MODE_NONE;
 
-    wl_list_for_each(info, list, link) {
-        if (info->data == data)
-            return true;
-    }
+exclusive_out:
+    if (!keyroutes_add_info(keyroutes, info->wl_client))
+        ds_err("Could not add wl_client to keyroutes");
 
-    return false;
+    return DS_TIZEN_KEYROUTE_MODE_EXCLUSIVE;
 }
 
-static bool
-keyrouter_grab_check_grabbed(struct ds_tizen_keyrouter_grab *keygrab,
-        int type, int keycode, void *data)
+int
+keyrouter_grab_grab_key(struct keyrouter_grab *keygrab, int mode, int keycode,
+        struct wl_client *wl_client)
 {
+    struct keyroute_info *info;
     struct wl_list *list;
-    bool ret;
 
-    list = keyrouter_grab_get_grabbed_list(keygrab, type, keycode);
-    if (list == NULL) {
-        ds_err("keycode(%d) had no list for type(%d).", keycode, type);
-        return false;
+    if (!KEYGRAB_IS_VALID_KEYCODE(keycode)) {
+        ds_err("Invalid keycode(%d)", keycode);
+        return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
     }
 
-    switch(type) {
+    switch (mode) {
         case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
-            if (wl_list_empty(list) == false)
-                ret = true;
-            else
-                ret = false;
+            list = &keygrab->hard_keys[keycode].grab.excl;
+            if (!wl_list_empty(list))
+                return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY;
             break;
         case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
-            ret = keyrouter_grab_check_duplicated_data(list, data);
-            break;
         case TIZEN_KEYROUTER_MODE_TOPMOST:
-            ret = keyrouter_grab_check_duplicated_data(list, data);
-            break;
         case TIZEN_KEYROUTER_MODE_SHARED:
-            ret = keyrouter_grab_check_duplicated_data(list, data);
+            if (mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE)
+                list = &keygrab->hard_keys[keycode].grab.or_excl;
+            else if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
+                list = &keygrab->hard_keys[keycode].grab.top;
+            else
+                list = &keygrab->hard_keys[keycode].grab.shared;
+
+            if (mode_list_check_duplicated(list, wl_client))
+                return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY;
             break;
         default:
-            ret = true;
-            break;
+            return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
     }
 
-    return ret;
-}
+    info = create_keyroute_info(wl_client);
+    if (!info) {
+        ds_err("Could not create key info");
+        return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
+    }
 
-void
-keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keygrab,
-        void *focus_client)
-{
-    keygrab->focus_client = focus_client;
+    wl_list_insert(list, &info->link);
 
-    if (focus_client)
-        ds_dbg("[%s] focus client has been set. (focus_client=0x%p)", __FUNCTION__, focus_client);
-    else
-        ds_dbg("[%s] focus client has been set to NULL.", __FUNCTION__);
+    return TIZEN_KEYROUTER_ERROR_NONE;
 }
 
 void
-keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keygrab, void *top_client)
-{
-    keygrab->top_client = top_client;
-
-    if (top_client)
-        ds_dbg("[%s] top client has been set. (top_client=0x%p)", __FUNCTION__, top_client);
-    else
-        ds_dbg("[%s] top client has been set to NULL.", __FUNCTION__);
-}
-
-int
-keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keygrab,
-        int keycode, int pressed, struct wl_list *delivery_list)
+keyrouter_grab_ungrab_key(struct keyrouter_grab *keygrab,
+        int mode, int keycode, struct wl_client *wl_client)
 {
-    struct ds_tizen_keyrouter_key_info *info, *delivery;
-    int count = 0;
+    struct wl_list *list;
 
-    if (keycode <= 0 || keycode >= KEYROUTER_MAX_KEYS) {
+    if (!KEYGRAB_IS_VALID_KEYCODE(keycode)) {
         ds_err("Invalid keycode(%d)", keycode);
-        return 0;
+        return;
     }
 
-    if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.excl)) {
-        delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
-        if (delivery == NULL) {
-            ds_err("Failed to allocate memory.");
-            return 0;
-        }
-        info = wl_container_of(keygrab->hard_keys[keycode].grab.excl.next, info, link);
-        delivery->data = info->data;
-        wl_list_insert(delivery_list, &delivery->link);
-        ds_dbg("Exclusive Mode: keycode: %d to data: %p", keycode, info->data);
-        return 1;
-    } else if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.or_excl)) {
-        delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
-        if (delivery == NULL) {
-            ds_err("Failed to allocate memory.");
-            return 0;
-        }
-        info = wl_container_of(keygrab->hard_keys[keycode].grab.or_excl.next, info, link);
-        delivery->data = info->data;
-        wl_list_insert(delivery_list, &delivery->link);
-        ds_dbg("OR-Excl Mode: keycode: %d to data: %p", keycode, info->data);
-        return 1;
-    } else if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.top)) {
-        wl_list_for_each(info, &keygrab->hard_keys[keycode].grab.top, link) {
-            if (keygrab->top_client && keygrab->top_client == info->data) {
-                delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
-                if (delivery == NULL) {
-                    ds_err("Failed to allocate memory.");
-                    return 0;
-                }
-                delivery->data = info->data;
-                wl_list_insert(delivery_list, &delivery->link);
-                ds_dbg("Topmost Mode: keycode: %d to data: %p", keycode, info->data);
-                return 1;
-            }
-        }
+    list = keyrouter_grab_get_mode_list(keygrab, mode, keycode);
+    if (!list) {
+        ds_err("keycode(%d) had no list for mode(%d)", keycode, mode);
+        return;
     }
 
-    if (keygrab->focus_client) {
-        delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
-        if (delivery == NULL) {
-            ds_err("Failed to allocate memory.");
-            return 0;
-        }
-        delivery->data = keygrab->focus_client;
-        wl_list_insert(delivery_list, &delivery->link);
-        count++;
-        ds_dbg("Focus: keycode: %d to data: %p, count: %d", keycode, delivery->data, count);
-    }
+    mode_list_remove_wl_client(list, wl_client);
+}
 
-    if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.shared)) {
-        wl_list_for_each(info, &keygrab->hard_keys[keycode].grab.shared, link) {
-            if (keygrab->focus_client && keygrab->focus_client == info->data)
-                continue;
-            delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
-            if (delivery == NULL) {
-                ds_err("Failed to allocate memory.");
-                return 0;
-            }
-            delivery->data = info->data;
-            wl_list_insert(delivery_list, &delivery->link);
-            count++;
-            ds_dbg("Shared: keycode: %d to data: %p, count: %d", keycode, info->data, count);
-        }
-    }
+static void
+mode_list_clean(struct wl_list *list)
+{
+    struct keyroute_info *info, *tmp;
 
-    return count;
+    wl_list_for_each_safe(info, tmp, list, link)
+        destroy_key_info(info);
 }
 
-int
-keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keygrab,
-        int type, int keycode, void *data)
+static void
+mode_list_remove_wl_client(struct wl_list *list, struct wl_client *wl_client)
 {
-    struct ds_tizen_keyrouter_key_info *info = NULL;
-    struct wl_list *list = NULL;
+    struct keyroute_info *info, *tmp;
 
-    if (keycode <= 0 || keycode >= KEYROUTER_MAX_KEYS) {
-        ds_err("Invalid keycode(%d)", keycode);
-        return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
+    wl_list_for_each_safe(info ,tmp, list, link) {
+        if (info->wl_client == wl_client)
+            destroy_key_info(info);
     }
+}
 
-    if (keyrouter_grab_check_grabbed(keygrab, type, keycode, data))
-        return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY;
-
-    info = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
-    if (info == NULL) {
-        ds_err("Failed to allocate memory.");
-        return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
+static struct wl_list *
+keyrouter_grab_get_mode_list(struct keyrouter_grab *keygrab,
+        int mode, int keycode)
+{
+    switch(mode) {
+        case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
+            return &keygrab->hard_keys[keycode].grab.excl;
+        case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+            return &keygrab->hard_keys[keycode].grab.or_excl;
+        case TIZEN_KEYROUTER_MODE_TOPMOST:
+            return &keygrab->hard_keys[keycode].grab.top;
+        case TIZEN_KEYROUTER_MODE_SHARED:
+            return &keygrab->hard_keys[keycode].grab.shared;
+        default:
+            return NULL;
     }
-    info->data = data;
+}
 
-    wl_list_init(&info->link);
+static bool
+mode_list_check_duplicated(struct wl_list *list, struct wl_client *wl_client)
+{
+    struct keyroute_info *info;
 
-    list = keyrouter_grab_get_grabbed_list(keygrab, type, keycode);
-    if (!list) {
-        ds_err("keycode(%d) had no list for type(%d)", keycode, type);
-        free(info);
-        return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
+    wl_list_for_each(info, list, link) {
+        if (info->wl_client == wl_client)
+            return true;
     }
 
-    if (!keygrab->hard_keys[keycode].keycode)
-        keygrab->hard_keys[keycode].keycode = keycode;
+    return false;
+}
+
+static struct keyroute_info *
+create_keyroute_info(struct wl_client *wl_client)
+{
+    struct keyroute_info *info;
 
-    wl_list_insert(list, &info->link);
+    info = calloc(1, sizeof *info);
+    if (!info)
+        return NULL;
 
-    return TIZEN_KEYROUTER_ERROR_NONE;
+    info->wl_client = wl_client;
+
+    return info;
 }
 
 static void
-keyrouter_list_remove_data(struct wl_list *list, void *data)
+destroy_key_info(struct keyroute_info *info)
 {
-    struct ds_tizen_keyrouter_key_info *info, *tmp;
+    wl_list_remove(&info->link);
+    free(info);
+}
+
+static struct keyroute_info *
+keyrouter_grab_get_exclusive_first(struct keyrouter_grab *keygrab, int keycode)
+{
+    struct wl_list *list = &keygrab->hard_keys[keycode].grab.excl;
+    struct keyroute_info *info;
 
     if (wl_list_empty(list))
-        return;
+        return NULL;
 
-    wl_list_for_each_safe(info ,tmp, list, link) {
-        if (info->data == data) {
-            wl_list_remove(&info->link);
-            free(info);
-        }
-    }
+    info = KEYGRAB_LIST_FIRST(list, info, link);
+
+    ds_dbg("Exclusive Mode: keycode: %d to wl_client: %p",
+            keycode, info->wl_client);
+
+    return info;
 }
 
-void
-keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keygrab,
-        int type, int keycode, void *data)
+static struct keyroute_info *
+keyrouter_grab_get_overridable_exclusive_first(struct keyrouter_grab *keygrab,
+        int keycode)
 {
-    struct wl_list *list;
+    struct wl_list *list = &keygrab->hard_keys[keycode].grab.or_excl;
+    struct keyroute_info *info;
 
-    if (keycode <= 0 || keycode >= KEYROUTER_MAX_KEYS) {
-        ds_err("Invalid keycode(%d)", keycode);
-        return;
-    }
+    if (wl_list_empty(list))
+        return NULL;
 
-    if (keygrab->hard_keys[keycode].keycode == 0)
-        return;
+    info = KEYGRAB_LIST_FIRST(list, info, link);
 
-    list = keyrouter_grab_get_grabbed_list(keygrab, type, keycode);
-    if (list == NULL) {
-        ds_err("keycode(%d) had no list for type(%d)", keycode, type);
-        return;
-    }
+    ds_dbg("OR-Excl Mode: keycode: %d to wl_client: %p",
+            keycode, info->wl_client);
 
-    keyrouter_list_remove_data(list, data);
+    return info;
 }
 
-struct ds_tizen_keyrouter_grab *
-keyrouter_grab_create(void)
+static struct keyroute_info *
+keyrouter_grab_topmost_find(struct keyrouter_grab *keygrab,
+        int keycode, struct wl_client *topmost_client)
 {
-    struct ds_tizen_keyrouter_grab *keygrab = NULL;
-    int i;
+    struct wl_list *list = &keygrab->hard_keys[keycode].grab.top;
+    struct keyroute_info *info;
 
-    keygrab = calloc(1, sizeof(struct ds_tizen_keyrouter_grab));
-    if (keygrab == NULL) {
-        ds_err("Failed to allocate memory.");
+    if (!topmost_client)
         return NULL;
-    }
 
-    /* FIXME: Who defined max keycode? */
-    keygrab->hard_keys = calloc(KEYROUTER_MAX_KEYS, sizeof(struct ds_tizen_keyrouter_grabbed));
-    if (keygrab->hard_keys == NULL) {
-        ds_err("Failed to allocate memory.");
-        free(keygrab);
-        return NULL;
-    }
+    wl_list_for_each(info, list, link) {
+        if (info->wl_client != topmost_client)
+            continue;
 
-    for (i = 0; i < KEYROUTER_MAX_KEYS; i++) {
-        /* Enable all of keys to grab */
-        //keygrab->hard_keys[i].keycode = i;
-        wl_list_init(&keygrab->hard_keys[i].grab.excl);
-        wl_list_init(&keygrab->hard_keys[i].grab.or_excl);
-        wl_list_init(&keygrab->hard_keys[i].grab.top);
-        wl_list_init(&keygrab->hard_keys[i].grab.shared);
-        wl_list_init(&keygrab->hard_keys[i].pressed);
+        ds_dbg("Topmost Mode: keycode: %d to wl_client: %p",
+                keycode, info->wl_client);
+
+        return info;
     }
 
-    return keygrab;
+    return NULL;
 }
 
-static void
-keyrouter_grab_delete_list(struct wl_list *list)
+static bool
+keyrouter_grab_get_shared_keyroutes(struct keyrouter_grab *keygrab,
+        int keycode, struct wl_array *keyroutes)
 {
-    struct ds_tizen_keyrouter_key_info *info, *tmp;
+    struct wl_list *list = &keygrab->hard_keys[keycode].grab.shared;
+    struct keyroute_info *info;
+    int count = 0;
 
-    if (wl_list_empty(list))
-        return;
+    wl_list_for_each(info, list, link) {
+        if (!keyroutes_add_info(keyroutes, info->wl_client)) {
+            ds_err("Could not prepend wl_client to delivery_list");
+            continue;
+        }
 
-    wl_list_for_each_safe(info, tmp, list, link) {
-        wl_list_remove(&info->link);
-        free(info);
+        count++;
+
+        ds_dbg("Shared: keycode: %d to wl_client: %p, count: %d",
+                keycode, info->wl_client, count);
     }
+
+    return !!count;
 }
 
-void
-keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keygrab)
+static bool
+keyroutes_add_info(struct wl_array *keyroutes,
+        struct wl_client *wl_client)
 {
-    int i;
-
-    for (i = 0; i < KEYROUTER_MAX_KEYS; i++) {
-        keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.excl);
-        keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.or_excl);
-        keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.top);
-        keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.shared);
-        keyrouter_grab_delete_list(&keygrab->hard_keys[i].pressed);
-    }
+    struct ds_tizen_keyroute_info *info;
+
+    info = wl_array_add(keyroutes, sizeof *info);
+    if (!info)
+        return false;
+
+    info->wl_client = wl_client;
 
-    free(keygrab->hard_keys);
-    free(keygrab);
+    return true;
 }