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
#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)
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);
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,
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.");
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;
}
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.");
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;
}
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)
{
}
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)
{
}
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
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
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;
}
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;
+}
#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;
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;
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
+#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;
}