From d67d917ad16c8e89ee5cfd94371b04fc426ebd29 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 10 Jun 2022 14:42:22 +0900 Subject: [PATCH] keyrouter: Refactor out ds_tizen_keyrouter Change-Id: I35add1ab1c81c8589789708b8ef38f4693cc1ee2 --- include/libds-tizen/keyrouter.h | 55 +++++ src/keyrouter/keyrouter.c | 398 ++++++++++++++++----------------- src/keyrouter/keyrouter.h | 71 +++--- src/keyrouter/keyrouter_grab.c | 478 +++++++++++++++++++--------------------- 4 files changed, 509 insertions(+), 493 deletions(-) diff --git a/include/libds-tizen/keyrouter.h b/include/libds-tizen/keyrouter.h index a870003..bd47b54 100644 --- a/include/libds-tizen/keyrouter.h +++ b/include/libds-tizen/keyrouter.h @@ -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 diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index 730b8a8..4bcee93 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -13,39 +13,21 @@ #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; +} diff --git a/src/keyrouter/keyrouter.h b/src/keyrouter/keyrouter.h index 11fbadc..bea9ab1 100644 --- a/src/keyrouter/keyrouter.h +++ b/src/keyrouter/keyrouter.h @@ -5,37 +5,34 @@ #include #include +#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 diff --git a/src/keyrouter/keyrouter_grab.c b/src/keyrouter/keyrouter_grab.c index ae29e8e..fed301b 100644 --- a/src/keyrouter/keyrouter_grab.c +++ b/src/keyrouter/keyrouter_grab.c @@ -1,3 +1,4 @@ +#include #include #include @@ -5,343 +6,324 @@ #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; } -- 2.7.4