libds-tizen-keyrouter supports the tizen_keyrouter extension.
This is the first impelemtaion for it. It can be added the additional
apis onward.
Change-Id: I53e8df054d3534c0fa84f14273a61761332b1bf6
--- /dev/null
+#ifndef LIBDS_TIZEN_KEYROUTER_H
+#define LIBDS_TIZEN_KEYROUTER_H
+
+#include <wayland-server.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ds_tizen_keyrouter;
+
+struct ds_tizen_keyrouter *
+ds_tizen_keyrouter_create(struct wl_display *display);
+
+void
+ds_tizen_keyrouter_add_destroy_listener(struct ds_tizen_keyrouter *keyrouter,
+ struct wl_listener *listener);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
option('tizen', type: 'boolean', value: false, description: 'Build Tizen features')
+option('keylayout_dir', type: 'string', value: '', description: 'Directory where tizen key layout file is')
\ No newline at end of file
BuildRequires: pkgconfig(wayland-server)
BuildRequires: pkgconfig(wayland-client)
BuildRequires: pkgconfig(wayland-protocols)
+BuildRequires: pkgconfig(tizen-extension-server)
BuildRequires: pkgconfig(pixman-1)
BuildRequires: pkgconfig(libdrm)
BuildRequires: pkgconfig(xkbcommon)
%description tizen-devel
Wayland Compositor development library for Tizen platform
+%package tizen-keyrouter
+Summary: Wayland Compositor Library for keyrouter
+Group: Development/Libraries
+
+%description tizen-keyrouter
+Wayland Compositor Library for tizen keyrouter
+
+%package tizen-keyrouter-devel
+Summary: Keyrouter Development package for Wayland Compositor Library
+Group: Development/Libraries
+
+%description tizen-keyrouter-devel
+Keyrouter Development package for Wayland Compositor Library
+
%prep
%setup -q
cp %{SOURCE1001} .
--libdir %{_libdir} \
--bindir %{_bindir} \
builddir \
- -Dtizen=true
+ -Dtizen=true \
+ -Dkeylayout_dir="%{TZ_SYS_RO_SHARE}/X11/xkb/tizen_key_layout.txt"
ninja -C builddir all
%install
%manifest %{name}.manifest
%defattr(-,root,root,-)
%license LICENSE
-%{_libdir}/*.so.*
+%{_libdir}/libds.so.*
+%{_libdir}/libds-tizen.so.*
%files devel
%manifest %{name}.manifest
%{_bindir}/tdm-backend
%{_bindir}/tinyds-tdm
%{_bindir}/ds-simple-tbm
+
+%files tizen-keyrouter
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%license LICENSE
+%{_libdir}/libds-tizen-keyrouter.so.*
+
+%files tizen-keyrouter-devel
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%license LICENSE
+%{_includedir}/libds-tizen/keyrouter.h
+%{_libdir}/pkgconfig/libds-tizen-keyrouter.pc
+%{_libdir}/libds-tizen-keyrouter.so
--- /dev/null
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "libds/log.h"
+#include "libds-tizen/keyrouter.h"
+
+#include "util.h"
+#include "keyrouter.h"
+
+static void
+tizen_keyrouter_bind(struct wl_client *client, void *data, uint32_t version,
+ uint32_t id);
+static bool
+keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client,
+ struct wl_client *client, uint32_t mode, uint32_t keycode);
+static void
+tizen_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);
+
+ tizen_security_finish();
+
+ free(keyrouter->opts);
+
+ wl_list_remove(&keyrouter->display_destroy.link);
+
+ wl_global_destroy(keyrouter->global);
+
+ tizen_keyrouter_grab_destroy(keyrouter->keyrouter_grab);
+
+ free(keyrouter);
+}
+
+WL_EXPORT struct ds_tizen_keyrouter *
+ds_tizen_keyrouter_create(struct wl_display *display)
+{
+ struct ds_tizen_keyrouter *keyrouter;
+
+ keyrouter = calloc(1, sizeof *keyrouter);
+ if (!keyrouter) {
+ return NULL;
+ }
+
+ keyrouter->keyrouter_grab = tizen_keyrouter_grab_create();
+ if (keyrouter->keyrouter_grab == NULL) {
+ ds_err("Failed to create keyrouter.");
+ free(keyrouter);
+ return NULL;
+ }
+
+ keyrouter->global = wl_global_create(display, &tizen_keyrouter_interface,
+ 2, keyrouter, tizen_keyrouter_bind);
+ if (!keyrouter->global) {
+ tizen_keyrouter_grab_destroy(keyrouter->keyrouter_grab);
+ free(keyrouter);
+ return NULL;
+ }
+
+ wl_list_init(&keyrouter->clients);
+
+ wl_signal_init(&keyrouter->events.destroy);
+
+ keyrouter->display_destroy.notify = keyrouter_handle_display_destroy;
+ wl_display_add_destroy_listener(display, &keyrouter->display_destroy);
+
+ tizen_keyrouter_options_set(keyrouter);
+
+ if (!tizen_security_init()) {
+ ds_inf("tizen_security_init() is not sucessful. keyrouter works without security.");
+ }
+
+ ds_inf("Global created: ds_tizen_keyrouter(%p)", keyrouter);
+
+ return keyrouter;
+}
+
+WL_EXPORT void
+ds_tizen_keyrouter_add_destroy_listener(struct ds_tizen_keyrouter *keyrouter,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&keyrouter->events.destroy, listener);
+}
+
+static void
+keyrouter_handle_keygrab_set(struct wl_client *client,
+ struct wl_resource *resource, struct wl_resource *surface,
+ uint32_t key, uint32_t mode)
+{
+ struct ds_tizen_keyrouter_client *keyrouter_client;
+ struct ds_tizen_keyrouter *keyrouter;
+ int res = TIZEN_KEYROUTER_ERROR_NONE;
+ bool ret;
+
+ keyrouter_client = wl_resource_get_user_data(resource);
+ keyrouter = keyrouter_client->keyrouter;
+
+ ret = keyrouter_check_privilege(keyrouter_client, client, mode, key);
+ if (ret == false) {
+ tizen_keyrouter_send_keygrab_notify(resource, surface,
+ key, mode, TIZEN_KEYROUTER_ERROR_NO_PERMISSION);
+ return;
+ }
+
+ res = tizen_keyrouter_grab_grab_key(keyrouter->keyrouter_grab,
+ mode, key, (void *)client);
+ if (res == TIZEN_KEYROUTER_ERROR_NONE && keyrouter_client->grabbed != true)
+ keyrouter_client->grabbed = true;
+
+ tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res);
+}
+
+static void
+keyrouter_handle_keygrab_unset(struct wl_client *client,
+ struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
+{
+ struct ds_tizen_keyrouter_client *keyrouter_client;
+ struct ds_tizen_keyrouter *keyrouter;
+ int res = TIZEN_KEYROUTER_ERROR_NONE;
+ bool ret;
+
+ keyrouter_client = wl_resource_get_user_data(resource);
+ keyrouter = keyrouter_client->keyrouter;
+
+ /* ungrab TOP POSITION grab first, this grab mode is not check privilege */
+ tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
+ TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)client);
+
+ ret = keyrouter_check_privilege(keyrouter_client,
+ 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;
+ }
+
+ tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
+ TIZEN_KEYROUTER_MODE_EXCLUSIVE, key, (void *)client);
+ tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
+ TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, key, (void *)client);
+ tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
+ TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)client);
+ tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
+ TIZEN_KEYROUTER_MODE_SHARED, key, (void *)client);
+
+ tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res);
+}
+
+static void
+keyrouter_handle_get_keygrab_status(struct wl_client *client,
+ struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
+{
+ tizen_keyrouter_send_keygrab_notify(resource, surface, key,
+ TIZEN_KEYROUTER_MODE_NONE, TIZEN_KEYROUTER_ERROR_NO_PERMISSION);
+}
+
+static int
+keyrouter_get_array_length(const struct wl_array *array)
+{
+ int *data = NULL;
+ int count = 0;
+
+ wl_array_for_each(data, array) {
+ count++;
+ }
+
+ return count;
+}
+
+static void
+keyrouter_handle_keygrab_set_list(struct wl_client *client,
+ struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
+{
+ struct ds_tizen_keyrouter_client *keyrouter_client;
+ struct ds_tizen_keyrouter *keyrouter;
+ struct wl_array *return_list;
+ struct ds_tizen_grab_data *grab_data = NULL;
+ int res = TIZEN_KEYROUTER_ERROR_NONE;
+ bool ret;
+
+ keyrouter_client = wl_resource_get_user_data(resource);
+ keyrouter = 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.");
+ tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
+ return;
+ }
+
+ wl_array_for_each(grab_data, grab_list) {
+ ret = keyrouter_check_privilege(keyrouter_client, client, grab_data->mode, grab_data->key);
+ if (ret == false) {
+ grab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
+ } else {
+ res = tizen_keyrouter_grab_grab_key(keyrouter->keyrouter_grab,
+ grab_data->mode, grab_data->key, (void *)client);
+ if (res == TIZEN_KEYROUTER_ERROR_NONE && keyrouter_client->grabbed != true)
+ keyrouter_client->grabbed = true;
+
+ grab_data->err = res;
+ }
+ }
+
+ return_list = grab_list;
+
+ tizen_keyrouter_send_keygrab_notify_list(resource, surface, return_list);
+}
+
+static void
+keyrouter_handle_keygrab_unset_list(struct wl_client *client,
+ struct wl_resource *resource, struct wl_resource *surface,
+ struct wl_array *ungrab_list)
+{
+ struct ds_tizen_keyrouter_client *keyrouter_client;
+ struct ds_tizen_keyrouter *keyrouter;
+ struct wl_array *return_list = NULL;
+ struct ds_tizen_ungrab_data *ungrab_data = NULL;
+ bool ret;
+
+ keyrouter_client = wl_resource_get_user_data(resource);
+ keyrouter = keyrouter_client->keyrouter;
+
+ if ((keyrouter_get_array_length(ungrab_list) % 3) != 0) {
+ ds_err("Invalid keycode and grab mode pair. Check arguments in a list.");
+ tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
+ return;
+ }
+
+ wl_array_for_each(ungrab_data, ungrab_list) {
+ tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
+ TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)client);
+
+ ret = keyrouter_check_privilege(keyrouter_client, client,
+ TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key);
+ if (!ret) {
+ ungrab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
+ } else {
+ tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
+ TIZEN_KEYROUTER_MODE_EXCLUSIVE, ungrab_data->key, (void *)client);
+
+ tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
+ TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, ungrab_data->key, (void *)client);
+
+ tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
+ TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)client);
+
+ tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
+ TIZEN_KEYROUTER_MODE_SHARED, ungrab_data->key, (void *)client);
+
+ ungrab_data->err = TIZEN_KEYROUTER_ERROR_NONE;
+ }
+ }
+
+ return_list = ungrab_list;
+
+ tizen_keyrouter_send_keygrab_notify_list(resource, surface, return_list);
+}
+
+static void
+keyrouter_handle_get_keygrab_list(struct wl_client *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 *client,
+ struct wl_resource *resource, struct wl_resource *surface,
+ uint32_t data)
+{
+ tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, 0);
+}
+
+static void
+keyrouter_handle_get_keyregister_status(struct wl_client *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 *client,
+ struct wl_resource *resource, struct wl_resource *surface,
+ uint32_t config_mode, uint32_t value)
+{
+ tizen_keyrouter_send_set_input_config_notify(resource, (int)false);
+}
+
+static void
+keyrouter_handle_destory(struct wl_client *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
+};
+
+static void
+keyrouter_handle_resource_destory(struct wl_resource *resource)
+{
+ struct ds_tizen_keyrouter_client *keyrouter_client = wl_resource_get_user_data(resource);
+
+ wl_list_remove(&keyrouter_client->link);
+ free(keyrouter_client);
+}
+
+static void
+tizen_keyrouter_bind(struct wl_client *client, void *data, uint32_t version,
+ uint32_t id)
+{
+ struct ds_tizen_keyrouter *keyrouter = data;
+ struct ds_tizen_keyrouter_client *keyrouter_client;
+
+ keyrouter_client = calloc(1, sizeof *keyrouter_client);
+ if (keyrouter_client == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ keyrouter_client->resource =
+ wl_resource_create(client, &tizen_keyrouter_interface, MIN(version, 2), id);
+ if (keyrouter_client->resource == NULL) {
+ ds_err("wl_resource_create() failed.(version :%d, id:%d)", version, id);
+ free(keyrouter_client);
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ wl_resource_set_implementation(keyrouter_client->resource, &tizen_keyrouter_impl,
+ keyrouter_client, keyrouter_handle_resource_destory);
+
+ wl_list_insert(&keyrouter->clients, &keyrouter_client->link);
+}
+
+static bool
+keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client,
+ struct wl_client *client, uint32_t mode, uint32_t keycode)
+{
+ struct ds_tizen_keyrouter *keyrouter = keyrouter_client->keyrouter;
+
+ pid_t pid = 0;
+ uid_t uid = 0;
+ gid_t gid = 0;
+
+ /* Top position grab is always allowed. This mode do not need privilege.*/
+ if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
+ return true;
+
+ // check no privilege option on the keycode
+ if (keyrouter->opts) {
+ if (keyrouter->opts[keycode].no_privilege)
+ return true;
+ }
+
+ // grabbed client is already checked the privilege before.
+ if (keyrouter_client->grabbed)
+ return true;
+
+ wl_client_get_credentials(client, &pid, &uid, &gid);
+
+ return tizen_security_check_privilege(pid, uid, "http://tizen.org/privilege/keygrab");
+}
+
+static void
+tizen_keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter)
+{
+ FILE *file;
+ int keycode;
+ char *ret, *tmp, *buf_ptr, buf[1024] = {0,};
+
+ keyrouter->opts = calloc(KEYROUTER_MAX_KEYS,
+ sizeof(struct ds_tizen_keyrouter_key_options));
+ if (!keyrouter->opts) {
+ return;
+ }
+
+ file = fopen(KEYLAYOUT_DIR, "r");
+ if (!file) {
+ ds_err("Failed to open key layout file(%s): (err msg: %m)\n", KEYLAYOUT_DIR);
+ free(keyrouter->opts);
+ keyrouter->opts = NULL;
+ return;
+ }
+
+ while (!feof(file)) {
+ ret = fgets(buf, 1024, file);
+ if (!ret) continue;
+
+ tmp = strtok_r(buf, " ", &buf_ptr);
+ tmp = strtok_r(NULL, " ", &buf_ptr);
+ if (!tmp) continue;
+ keycode = atoi(tmp);
+ if ((0 >= keycode) || (keycode >= KEYROUTER_MAX_KEYS)) {
+ ds_err("Currently %d key is invalid to support\n", keycode);
+ continue;
+ }
+
+ keyrouter->opts[keycode].enabled = true;
+
+ if (strstr(buf_ptr, "no_priv") != NULL) {
+ keyrouter->opts[keycode].no_privilege = true;
+ }
+ }
+
+ fclose(file);
+}
--- /dev/null
+#ifndef DS_TIZEN_KEYROUTER_H
+#define DS_TIZEN_KEYROUTER_H
+
+#include <stdbool.h>
+#include <wayland-server.h>
+#include <tizen-extension-server-protocol.h>
+
+#define KEYROUTER_MAX_KEYS 512
+
+struct ds_tizen_keyrouter_key_info
+{
+ void *data;
+ struct wl_list link;
+};
+
+struct ds_tizen_keyrouter_grabbed
+{
+ int keycode;
+
+ struct {
+ struct wl_list excl;
+ struct wl_list or_excl;
+ struct wl_list top;
+ struct wl_list shared;
+ } grab;
+
+ struct wl_list pressed;
+};
+
+struct ds_tizen_keyrouter_grab
+{
+ struct ds_tizen_keyrouter_grabbed *hard_keys;
+
+ void *focus_client;
+ void *top_client;
+};
+
+struct ds_tizen_keyrouter_key_options
+{
+ bool enabled;
+ bool no_privilege;
+};
+
+struct ds_tizen_keyrouter
+{
+ struct wl_global *global;
+
+ struct wl_list clients;
+
+ struct wl_listener display_destroy;
+
+ struct {
+ struct wl_signal destroy;
+ } events;
+
+ struct ds_tizen_keyrouter_key_options *opts;
+
+ struct ds_tizen_keyrouter_grab *keyrouter_grab;
+};
+
+struct ds_tizen_keyrouter_client
+{
+ struct ds_tizen_keyrouter *keyrouter;
+
+ struct wl_resource *resource;
+
+ bool grabbed;
+
+ struct wl_list link; // ds_tizen_keyrouter::clients
+};
+
+struct ds_tizen_grab_data
+{
+ int key;
+ int mode;
+ int err;
+};
+
+struct ds_tizen_ungrab_data
+{
+ int key;
+ int err;
+};
+
+struct ds_tizen_keyrouter_grab *
+tizen_keyrouter_grab_create(void);
+void
+tizen_keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keyrouter_grab);
+int
+tizen_keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ int type, int keycode, void *data);
+void
+tizen_keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ int type, int keycode, void *data);
+int
+tizen_keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ int keycode, int pressed, struct wl_list *delivery_list);
+void
+tizen_keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ void *focus_client);
+void
+tizen_keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ void *top_client);
+bool
+tizen_keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ int keycode);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "libds/log.h"
+
+#include "keyrouter.h"
+
+static struct wl_list *
+keyrouter_grab_get_grabbed_list(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ int type, int keycode)
+{
+ switch(type) {
+ case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
+ return &keyrouter_grab->hard_keys[keycode].grab.excl;
+ case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
+ return &keyrouter_grab->hard_keys[keycode].grab.or_excl;
+ case TIZEN_KEYROUTER_MODE_TOPMOST:
+ return &keyrouter_grab->hard_keys[keycode].grab.top;
+ case TIZEN_KEYROUTER_MODE_SHARED:
+ return &keyrouter_grab->hard_keys[keycode].grab.shared;
+ default:
+ return NULL;
+ }
+}
+
+bool
+tizen_keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, int keycode)
+{
+ struct wl_list *list;
+
+ list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_EXCLUSIVE, keycode);
+ if (list && !wl_list_empty(list))
+ return true;
+
+ list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, keycode);
+ if (list && !wl_list_empty(list))
+ return true;
+
+ list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_TOPMOST, keycode);
+ if (list && !wl_list_empty(list))
+ return true;
+
+ list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_SHARED, keycode);
+ if (list && !wl_list_empty(list))
+ return true;
+
+ return false;
+}
+
+static bool
+keyrouter_grab_check_duplicated_data(struct wl_list *list, void *data)
+{
+ struct ds_tizen_keyrouter_key_info *info;
+
+ if (wl_list_empty(list))
+ return false;
+
+ wl_list_for_each(info, list, link) {
+ if (info->data == data)
+ return true;
+ }
+
+ return false;
+}
+
+static bool
+keyrouter_grab_check_grabbed(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ int type, int keycode, void *data)
+{
+ struct wl_list *list;
+ bool ret;
+
+ list = keyrouter_grab_get_grabbed_list(keyrouter_grab, type, keycode);
+ if (list == NULL) {
+ ds_err("keycode(%d) had no list for type(%d).", keycode, type);
+ return false;
+ }
+
+ switch(type) {
+ case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
+ if (wl_list_empty(list) == false)
+ ret = false;
+ else
+ ret = true;
+ 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);
+ break;
+ default:
+ ret = TIZEN_KEYROUTER_ERROR_INVALID_MODE;
+ break;
+ }
+
+ return ret;
+}
+
+void
+tizen_keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ void *focus_client)
+{
+ keyrouter_grab->focus_client = focus_client;
+
+ 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__);
+}
+
+void
+tizen_keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, void *top_client)
+{
+ keyrouter_grab->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
+tizen_keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ int keycode, int pressed, struct wl_list *delivery_list)
+{
+ struct ds_tizen_keyrouter_key_info *info, *delivery;
+ int count = 0;
+
+ if (keycode <= 0 && keycode >= KEYROUTER_MAX_KEYS) {
+ ds_err("Invalid keycode(%d)", keycode);
+ return 0;
+ }
+
+ if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.excl)) {
+ info = wl_container_of(keyrouter_grab->hard_keys[keycode].grab.excl.next, info, link);
+ if (info) {
+ 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("Exclusive Mode: keycode: %d to data: %p", keycode, info->data);
+ return 1;
+ }
+ } else if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.or_excl)) {
+ info = wl_container_of(keyrouter_grab->hard_keys[keycode].grab.or_excl.next, info, link);
+ if (info) {
+ 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("OR-Excl Mode: keycode: %d to data: %p", keycode, info->data);
+ return 1;
+ }
+ } else if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.top)) {
+ wl_list_for_each(info, &keyrouter_grab->hard_keys[keycode].grab.top, link) {
+ if (keyrouter_grab->top_client && keyrouter_grab->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;
+ }
+ }
+ }
+
+ if (keyrouter_grab->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 = keyrouter_grab->focus_client;
+ wl_list_insert(delivery_list, &delivery->link);
+ count++;
+ ds_dbg("Focus: keycode: %d to data: %p, count: %d", keycode, delivery->data, count);
+ }
+
+ if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.shared)) {
+ wl_list_for_each(info, &keyrouter_grab->hard_keys[keycode].grab.shared, link) {
+ if (keyrouter_grab->focus_client && keyrouter_grab->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);
+ }
+ }
+
+ return count;
+}
+
+int
+tizen_keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ int type, int keycode, void *data)
+{
+ struct ds_tizen_keyrouter_key_info *info = NULL;
+ struct wl_list *list = NULL;
+
+ if (keycode <= 0 && keycode >= KEYROUTER_MAX_KEYS) {
+ ds_err("Invalid keycode(%d)", keycode);
+ return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
+ }
+
+ if (keyrouter_grab_check_grabbed(keyrouter_grab, 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;
+ }
+ info->data = data;
+
+ wl_list_init(&info->link);
+
+ list = keyrouter_grab_get_grabbed_list(keyrouter_grab, type, keycode);
+ if (!list) {
+ ds_err("keycode(%d) had no list for type(%d)", keycode, type);
+ free(info);
+ return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
+ }
+
+ if (!keyrouter_grab->hard_keys[keycode].keycode)
+ keyrouter_grab->hard_keys[keycode].keycode = keycode;
+
+ wl_list_insert(list, &info->link);
+
+ return TIZEN_KEYROUTER_ERROR_NONE;
+}
+
+static void
+keyrouter_list_remove_data(struct wl_list *list, void *data)
+{
+ struct ds_tizen_keyrouter_key_info *info, *tmp;
+
+ if (wl_list_empty(list))
+ return;
+
+ wl_list_for_each_safe(info ,tmp, list, link) {
+ if (info->data == data) {
+ wl_list_remove(&info->link);
+ free(info);
+ }
+ }
+}
+
+void
+tizen_keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab,
+ int type, int keycode, void *data)
+{
+ struct wl_list *list;
+
+ if (keycode <= 0 && keycode >= KEYROUTER_MAX_KEYS) {
+ ds_err("Invalid keycode(%d)", keycode);
+ return;
+ }
+
+ if (keyrouter_grab->hard_keys[keycode].keycode == 0)
+ return;
+
+ list = keyrouter_grab_get_grabbed_list(keyrouter_grab, type, keycode);
+ if (list == NULL) {
+ ds_err("keycode(%d) had no list for type(%d)", keycode, type);
+ return;
+ }
+
+ keyrouter_list_remove_data(list, data);
+}
+
+struct ds_tizen_keyrouter_grab *
+tizen_keyrouter_grab_create(void)
+{
+ struct ds_tizen_keyrouter_grab *keyrouter_grab = NULL;
+ int i;
+
+ keyrouter_grab = calloc(1, sizeof(struct ds_tizen_keyrouter_grab));
+ if (keyrouter_grab == NULL) {
+ ds_err("Failed to allocate memory.");
+ return NULL;
+ }
+
+ /* FIXME: Who defined max keycode? */
+ keyrouter_grab->hard_keys = calloc(KEYROUTER_MAX_KEYS, sizeof(struct ds_tizen_keyrouter_grabbed));
+ if (keyrouter_grab == NULL) {
+ ds_err("Failed to allocate memory.");
+ free(keyrouter_grab);
+ return NULL;
+ }
+
+ for (i = 0; i < KEYROUTER_MAX_KEYS; i++) {
+ /* Enable all of keys to grab */
+ //keyrouter_grab->hard_keys[i].keycode = i;
+ wl_list_init(&keyrouter_grab->hard_keys[i].grab.excl);
+ wl_list_init(&keyrouter_grab->hard_keys[i].grab.or_excl);
+ wl_list_init(&keyrouter_grab->hard_keys[i].grab.top);
+ wl_list_init(&keyrouter_grab->hard_keys[i].grab.shared);
+ wl_list_init(&keyrouter_grab->hard_keys[i].pressed);
+ }
+
+ return keyrouter_grab;
+}
+
+static void
+keyrouter_grab_delete_list(struct wl_list *list)
+{
+ struct ds_tizen_keyrouter_key_info *info, *tmp;
+
+ if (wl_list_empty(list))
+ return;
+
+ wl_list_for_each_safe(info, tmp, list, link) {
+ wl_list_remove(&info->link);
+ free(info);
+ }
+}
+
+void
+tizen_keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keyrouter_grab)
+{
+ int i;
+
+ for (i = 0; i < KEYROUTER_MAX_KEYS; i++) {
+ keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.excl);
+ keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.or_excl);
+ keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.top);
+ keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.shared);
+ keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].pressed);
+ }
+
+ free(keyrouter_grab->hard_keys);
+ free(keyrouter_grab);
+}
--- /dev/null
+libds_tizen_keyrouter_files = [
+ 'keyrouter_grab.c',
+ 'keyrouter.c',
+]
+
+libds_tizen_keyrouter_deps = [
+ dep_libds,
+ dep_libds_tizen,
+ dependency('tizen-extension-server', required: true),
+]
+
+keylayout_dir = get_option('keylayout_dir')
+
+lib_libds_tizen_keyrouter = shared_library('ds-tizen-keyrouter', libds_tizen_keyrouter_files,
+ dependencies: libds_tizen_keyrouter_deps,
+ include_directories: [ common_inc, include_directories('.'), include_directories('..') ],
+ version: meson.project_version(),
+ c_args: [ '-DKEYLAYOUT_DIR="@0@"'.format(keylayout_dir) ],
+ install: true
+)
+
+dep_libds_tizen_keyrouter = declare_dependency(
+ link_with: lib_libds_tizen_keyrouter,
+ dependencies: libds_tizen_keyrouter_deps,
+ include_directories: [ common_inc, include_directories('.') ],
+)
+
+pkgconfig = import('pkgconfig')
+pkgconfig.generate(lib_libds_tizen_keyrouter,
+ version: meson.project_version(),
+ filebase: 'libds-tizen-keyrouter',
+ name: 'libds-tizen-keyrouter',
+ description: 'tizen keyrouter extension of libds-tizen for tizen platform',
+)
\ No newline at end of file
name: 'libds-tizen',
description: 'extension of libds for tizen platform',
)
+
+subdir('keyrouter')
+