--- /dev/null
+#include <stdlib.h>
+#include <time.h> // gettimeofday()
+#include <libds/backend.h>
+#include <libds/log.h>
+#include <libds-tizen/input_devicemgr.h>
+#include <libds/interfaces/backend.h>
+#include <libds/interfaces/keyboard.h>
+#include <libds/interfaces/pointer.h>
+#include <libds/interfaces/touch.h>
+
+#include "util.h"
+#include "security.h"
+#include "input_devicemgr.h"
+
+#define TIZEN_INPUT_DEVICEMGR_VERSION 4
+#define TIZEN_PRIV_INPUT_GENERATOR "http://tizen.org/privilege/inputgenerator"
+#define TIZEN_PRIV_INPUT_BLOCK "http://tizen.org/privilege/internal/inputdevice.block"
+#define TIZEN_INPUT_DEVICEMGR_MAX_BTN 16
+
+static const struct ds_keyboard_grab_interface devicemgr_keyboard_grab_iface;
+
+//listeners
+static void
+backend_handle_destroy(struct wl_listener *listener, void *data);
+static void
+backend_handle_input_device_add(struct wl_listener *listener, void *data);
+static void
+seat_handle_destroy(struct wl_listener *listener, void *data);
+
+//tizen_input_device_manager bind/unbind
+static void
+device_manager_handle_bind(struct wl_client *client, void *data,
+ uint32_t version, uint32_t id);
+static void
+device_manager_client_handle_resource_destroy(struct wl_resource *resource);
+
+//tizen_input_device_manager's handlers for requests
+static void
+device_manager_handle_block_events(struct wl_client *client,
+ struct wl_resource *resource, uint32_t serial,
+ uint32_t clas, uint32_t duration);
+static void
+device_manager_handle_unblock_events(struct wl_client *client,
+ struct wl_resource *resource, uint32_t serial);
+static void
+device_manager_handle_init_generator(struct wl_client *client,
+ struct wl_resource *resource, uint32_t clas);
+static void
+device_manager_handle_init_generator_with_name(struct wl_client *client,
+ struct wl_resource *resource, uint32_t clas, const char *name);
+static void
+device_manager_handle_deinit_generator(struct wl_client *client,
+ struct wl_resource *resource, uint32_t clas);
+static void
+device_manager_handle_generate_key(struct wl_client *client,
+ struct wl_resource *resource,
+ const char *keyname, uint32_t pressed);
+static void
+device_manager_handle_generate_touch(struct wl_client *client,
+ struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y,
+ uint32_t finger);
+static void
+device_manager_handle_generate_pointer(struct wl_client *client,
+ struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y,
+ uint32_t button);
+static void
+device_manager_handle_destroy(struct wl_client *client,
+ struct wl_resource *resource);
+
+//
+static void tz_devicemgr_destroy(struct ds_tizen_input_devicemgr *tz_devicemgr);
+static int
+tz_devicemgr_init_generator(struct ds_tizen_input_devicemgr *tz_devicemgr,
+ struct wl_resource *resource, uint32_t clas, const char *name);
+static int
+tz_devicemgr_deinit_generator(struct ds_tizen_input_devicemgr *tz_devicemgr,
+ struct wl_resource *resource);
+static bool
+tz_devicemgr_generate_key(struct ds_input_device *device, int keycode,
+ int pressed);
+static bool
+tz_devicemgr_pressed_keys_update(struct ds_tizen_input_devicemgr *tz_devicemgr,
+ int keycode, bool pressed);
+static void
+tz_devicemgr_pressed_keys_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr);
+static void
+tz_devicemgr_keymap_list_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr);
+static int
+tz_devicemgr_keyname_to_keycode(struct wl_list *list, const char *name);
+
+static bool
+tz_devicemgr_generate_touch_move(struct ds_input_device *device, double x, double y,
+ uint32_t finger);
+static bool
+tz_devicemgr_generate_touch_down(struct ds_input_device *device, double x, double y,
+ uint32_t finger);
+static bool
+tz_devicemgr_generate_touch_up(struct ds_input_device *device, uint32_t finger);
+static bool
+tz_devicemgr_generate_mouse_move(struct ds_input_device *device, double x, double y);
+static bool
+tz_devicemgr_generate_mouse_button(struct ds_input_device *device, uint32_t button, bool state);
+
+static bool
+tz_devicemgr_check_privilege(struct ds_tizen_input_devicemgr *tz_devicemgr,
+ struct wl_client *client, const char *rule);
+
+static void
+tz_devicemgr_grab_keyboard(struct ds_tizen_input_devicemgr *tz_devicemgr);
+static void
+tz_devicemgr_ungrab_keyboard(struct ds_tizen_input_devicemgr *tz_devicemgr);
+static void
+tz_devicemgr_ungrab_keyboard_check(struct ds_tizen_input_devicemgr *tz_devicemgr);
+static void
+tz_devicemgr_blocked_keys_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr);
+
+WL_EXPORT struct ds_tizen_input_devicemgr *
+ds_tizen_input_devicemgr_create(struct ds_backend *backend,
+ struct ds_seat *seat)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+
+ tz_devicemgr = calloc(1, sizeof *tz_devicemgr);
+ if (!tz_devicemgr) {
+ ds_err("Fail to allocate ds_tizen_input_devicemgr");
+ return NULL;
+ }
+
+ tz_devicemgr->backend = backend;
+ tz_devicemgr->backend_destroy.notify = backend_handle_destroy;
+ ds_backend_add_destroy_listener(backend, &tz_devicemgr->backend_destroy);
+
+ tz_devicemgr->seat = seat;
+ tz_devicemgr->seat_destroy.notify = seat_handle_destroy;
+ ds_seat_add_destroy_listener(seat, &tz_devicemgr->seat_destroy);
+
+ tz_devicemgr->new_input.notify = backend_handle_input_device_add;
+ ds_backend_add_new_input_listener(backend, &tz_devicemgr->new_input);
+
+ tz_devicemgr->global = wl_global_create(backend->display,
+ &tizen_input_device_manager_interface,
+ TIZEN_INPUT_DEVICEMGR_VERSION,
+ tz_devicemgr, device_manager_handle_bind);
+ if (!tz_devicemgr->global) {
+ goto err_global;
+ }
+
+ tz_devicemgr->devices.kbd = calloc(1,
+ sizeof(struct ds_tizen_input_devicemgr_device));
+ if (!tz_devicemgr->devices.kbd) {
+ goto err_kbd;
+ }
+ tz_devicemgr->devices.ptr = calloc(1,
+ sizeof(struct ds_tizen_input_devicemgr_device));
+ if (!tz_devicemgr->devices.ptr) {
+ goto err_ptr;
+ }
+ tz_devicemgr->devices.touch = calloc(1,
+ sizeof(struct ds_tizen_input_devicemgr_device));
+ if (!tz_devicemgr->devices.touch) {
+ goto err_touch;
+ }
+ tz_devicemgr->touch_max_count = 5;//TODO: make this variable configurable
+
+ tz_devicemgr->grab = ds_seat_create_keyboard_grab(
+ tz_devicemgr->seat, &devicemgr_keyboard_grab_iface, tz_devicemgr);
+ if (!tz_devicemgr->grab) {
+ goto err_grab;
+ }
+
+ wl_signal_init(&tz_devicemgr->events.destroy);
+ wl_list_init(&tz_devicemgr->clients);
+ wl_list_init(&tz_devicemgr->devices.kbd->key.pressed);
+ wl_list_init(&tz_devicemgr->keymap_list);
+ wl_list_init(&tz_devicemgr->blocked_keys);
+
+ if (!tizen_security_init()) {
+ ds_inf("tizen_security_init() is failed. go on without security");
+ }
+
+ ds_inf("Global created: ds_tizen_input_devicemgr(%p) ", tz_devicemgr);
+ return tz_devicemgr;
+
+err_grab:
+ free(tz_devicemgr->devices.touch);
+err_touch:
+ free(tz_devicemgr->devices.ptr);
+err_ptr:
+ free(tz_devicemgr->devices.kbd);
+err_kbd:
+ wl_global_destroy(tz_devicemgr->global);
+err_global:
+ wl_list_remove(&tz_devicemgr->backend_destroy.link);
+ wl_list_remove(&tz_devicemgr->seat_destroy.link);
+ wl_list_remove(&tz_devicemgr->new_input.link);
+ free(tz_devicemgr);
+ return NULL;
+}
+
+WL_EXPORT void
+ds_tizen_input_devicemgr_add_destroy_listener(
+ struct ds_tizen_input_devicemgr *tz_devicemgr,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&tz_devicemgr->events.destroy, listener);
+}
+
+WL_EXPORT bool
+ds_tizen_input_devicemgr_set_keymap_list(
+ struct ds_tizen_input_devicemgr *tz_devicemgr, struct wl_list *list)
+{
+ struct ds_tizen_input_devicemgr_keymap_data *data, *new_data;
+
+ if (!tz_devicemgr || !list) {
+ ds_err("Please insert correct data\n");
+ return false;
+ }
+
+ wl_list_for_each(data, list, link) {
+ new_data = calloc(1, sizeof *data);
+ if (!new_data) {
+ ds_err("Failed to alloc memory");
+ return false;
+ }
+ new_data->name = strdup(data->name);
+ new_data->keycode = data->keycode;
+ wl_list_insert(&tz_devicemgr->keymap_list, &new_data->link);
+ }
+ ds_inf("keymap set. length:%d",
+ wl_list_length(&tz_devicemgr->keymap_list));
+
+ return true;
+}
+
+WL_EXPORT bool
+ds_tizen_input_devicemgr_set_output_width_height(
+ struct ds_tizen_input_devicemgr *tz_devicemgr,
+ uint32_t width, uint32_t height)
+{
+ if (!tz_devicemgr) return false;
+
+ tz_devicemgr->output.width = width;
+ tz_devicemgr->output.height = height;
+
+ ds_inf("output's width: %d, height:%d", width, height);
+
+ return true;
+}
+
+static void
+tz_devicemgr_destroy(struct ds_tizen_input_devicemgr *tz_devicemgr)
+{
+ struct ds_tizen_input_devicemgr_client *client_data, *tmp;
+
+ tizen_security_finish();
+
+ tz_devicemgr_keymap_list_cleanup(tz_devicemgr);
+ tz_devicemgr_blocked_keys_cleanup(tz_devicemgr);
+ tz_devicemgr_ungrab_keyboard(tz_devicemgr);
+ ds_seat_keyboard_destroy_grab(tz_devicemgr->grab);
+
+ wl_signal_emit(&tz_devicemgr->events.destroy, tz_devicemgr);
+ wl_list_remove(&tz_devicemgr->backend_destroy.link);
+ wl_list_remove(&tz_devicemgr->seat_destroy.link);
+ wl_list_remove(&tz_devicemgr->new_input.link);
+
+ wl_global_destroy(tz_devicemgr->global);
+
+ wl_list_for_each_safe(client_data, tmp, &tz_devicemgr->clients, link) {
+ wl_list_remove(&client_data->link);
+ tz_devicemgr_deinit_generator(tz_devicemgr, client_data->resource);
+
+ wl_resource_set_user_data(client_data->resource, NULL);
+ free(client_data);
+ }
+
+ free(tz_devicemgr->devices.touch);
+ free(tz_devicemgr->devices.ptr);
+ free(tz_devicemgr->devices.kbd);
+ free(tz_devicemgr);
+}
+
+static void
+backend_handle_destroy(struct wl_listener *listener, void *data)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+
+ tz_devicemgr = wl_container_of(listener, tz_devicemgr, backend_destroy);
+
+ ds_inf("Global destroy: ds_tizen_input_devicemgr(%p)", tz_devicemgr);
+
+ tz_devicemgr_destroy(tz_devicemgr);
+}
+
+static void
+seat_handle_destroy(struct wl_listener *listener, void *data)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+
+ tz_devicemgr = wl_container_of(listener, tz_devicemgr, seat_destroy);
+
+ wl_list_remove(&tz_devicemgr->seat_destroy.link);
+ wl_list_init(&tz_devicemgr->seat_destroy.link);
+ tz_devicemgr->seat = NULL;
+}
+
+static void
+tz_devicemgr_device_close(struct ds_tizen_input_devicemgr_device *dev)
+{
+ if (!dev->input_device) return;
+ ds_input_device_destroy(dev->input_device);
+ dev->input_device = NULL;
+}
+
+static void
+backend_handle_input_device_add(struct wl_listener *listener, void *data)
+{
+ struct ds_input_device *dev = data;
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+ enum ds_input_device_type dev_type;
+
+ tz_devicemgr = wl_container_of(listener, tz_devicemgr, new_input);
+
+ dev_type = ds_input_device_get_type(dev);
+ if (dev_type == DS_INPUT_DEVICE_KEYBOARD) {
+ if (tz_devicemgr->devices.kbd->input_device) return;
+ ds_inf("devicemgr's kbd device is set to dev(%p)", dev);
+ tz_devicemgr->devices.kbd->input_device = dev;
+ }
+ else if (dev_type == DS_INPUT_DEVICE_POINTER) {
+ if (tz_devicemgr->devices.ptr->input_device) return;
+ ds_inf("devicemgr's ptr device is set to dev(%p)", dev);
+ tz_devicemgr->devices.ptr->input_device = dev;
+ }
+ else if (dev_type == DS_INPUT_DEVICE_TOUCH) {
+ if (tz_devicemgr->devices.touch->input_device) return;
+ ds_inf("devicemgr's touch device is set to dev(%p)", dev);
+ tz_devicemgr->devices.touch->input_device = dev;
+ }
+}
+
+static const struct tizen_input_device_manager_interface _devicemgr_impl = {
+ .block_events = device_manager_handle_block_events,
+ .unblock_events = device_manager_handle_unblock_events,
+ .init_generator = device_manager_handle_init_generator,
+ .deinit_generator = device_manager_handle_deinit_generator,
+ .generate_key = device_manager_handle_generate_key,
+ .generate_pointer = device_manager_handle_generate_pointer,
+ .generate_touch = device_manager_handle_generate_touch,
+ .pointer_warp = NULL,
+ .init_generator_with_name =
+ device_manager_handle_init_generator_with_name, // v2
+ .destroy = device_manager_handle_destroy, // v3
+ .generate_axis = NULL, // v3
+ .set_touch_count = NULL, // v4
+};
+
+static void
+device_manager_client_handle_resource_destroy(struct wl_resource *resource)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+ struct ds_tizen_input_devicemgr_client *client_data, *tmp;
+
+ tz_devicemgr = wl_resource_get_user_data(resource);
+
+ tz_devicemgr_deinit_generator(tz_devicemgr, resource);
+
+ if (resource == tz_devicemgr->block_resource) {
+ tz_devicemgr_ungrab_keyboard_check(tz_devicemgr);
+ if (tz_devicemgr->timer) {
+ wl_event_source_remove(tz_devicemgr->timer);
+ tz_devicemgr->timer = NULL;
+ }
+ }
+
+ wl_list_for_each_safe(client_data, tmp, &tz_devicemgr->clients, link) {
+ if (client_data->resource == resource) {
+ wl_list_remove(&client_data->link);
+ free(client_data);
+ }
+ }
+}
+
+static void
+device_manager_handle_bind(struct wl_client *client, void *data,
+ uint32_t version, uint32_t id)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr = data;
+ struct ds_tizen_input_devicemgr_client *client_data;
+
+ client_data = calloc(1, sizeof *client_data);
+ if (!client_data) {
+ ds_err("Failed to allocate memory !\n");
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ client_data->resource = wl_resource_create(client,
+ &tizen_input_device_manager_interface, MIN(version,4), id);
+ if (!client_data->resource) {
+ ds_err("Failed to create resource! (ver. :%d, id:%d)", version, id);
+ free(client_data);
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ client_data->init = false;
+ wl_list_init(&client_data->link);
+ wl_list_insert(&tz_devicemgr->clients, &client_data->link);
+
+ wl_resource_set_implementation(client_data->resource, &_devicemgr_impl,
+ tz_devicemgr, device_manager_client_handle_resource_destroy);
+}
+
+static void
+device_manager_handle_init_generator(struct wl_client *client,
+ struct wl_resource *resource, uint32_t clas)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+
+ tz_devicemgr = wl_resource_get_user_data(resource);
+
+ if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
+ TIZEN_PRIV_INPUT_GENERATOR)) {
+ ds_err("No permission to input generate");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
+ goto finish;
+ }
+
+ ret = tz_devicemgr_init_generator(tz_devicemgr, resource, clas,
+ "Input Generator");
+ if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
+ ds_err("Failed to init input generator\n");
+ goto finish;
+ }
+
+finish:
+ tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+device_manager_handle_init_generator_with_name(struct wl_client *client,
+ struct wl_resource *resource, uint32_t clas, const char *name)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+
+ tz_devicemgr = wl_resource_get_user_data(resource);
+
+ if (!name) {
+ ds_err("no name for device");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+ goto finish;
+ }
+
+ if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
+ TIZEN_PRIV_INPUT_GENERATOR)) {
+ ds_err("No permission to input generate");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
+ goto finish;
+ }
+
+ ret = tz_devicemgr_init_generator(tz_devicemgr, resource, clas,
+ name);
+ if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
+ ds_err("Failed to init input generator\n");
+ goto finish;
+ }
+
+finish:
+ tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+device_manager_handle_deinit_generator(struct wl_client *client,
+ struct wl_resource *resource, uint32_t clas __attribute__((unused)))
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+
+ tz_devicemgr = wl_resource_get_user_data(resource);
+
+ if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
+ TIZEN_PRIV_INPUT_GENERATOR)) {
+ ds_err("No permission to input generate");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
+ goto finish;
+ }
+
+ ret = tz_devicemgr_deinit_generator(tz_devicemgr, resource);
+ if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
+ ds_err("Failed to deinit input generator\n");
+ goto finish;
+ }
+
+finish:
+ tizen_input_device_manager_send_error(resource, ret);
+}
+
+struct keycode_map{
+ xkb_keysym_t keysym;
+ xkb_keycode_t keycode;
+};
+
+static void
+find_keycode(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
+{
+ struct keycode_map *found_keycodes = (struct keycode_map *)data;
+ xkb_keysym_t keysym = found_keycodes->keysym;
+ int nsyms = 0;
+ const xkb_keysym_t *syms_out = NULL;
+
+ if (found_keycodes->keycode) return;
+
+ nsyms = xkb_keymap_key_get_syms_by_level(keymap, key, 0, 0, &syms_out);
+ if (nsyms && syms_out) {
+ if (*syms_out == keysym) {
+ found_keycodes->keycode = key;
+ }
+ }
+}
+
+static void
+tz_devicemgr_xkb_keycode_from_keysym(struct xkb_keymap *keymap,
+ xkb_keysym_t keysym, xkb_keycode_t *keycode)
+{
+ struct keycode_map found_keycodes = {0,};
+ found_keycodes.keysym = keysym;
+ xkb_keymap_key_for_each(keymap, find_keycode, &found_keycodes);
+
+ *keycode = found_keycodes.keycode;
+}
+
+static int
+tz_devicemgr_xkb_keyname_to_keycode(struct xkb_keymap *keymap,
+ const char *name)
+{
+ xkb_keysym_t keysym = 0x0;
+ xkb_keycode_t keycode = 0;
+
+ if (!strncmp(name, "Keycode-", sizeof("Keycode-")-1)) {
+ keycode = atoi(name + 8);
+ } else {
+ keysym = xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS);
+ tz_devicemgr_xkb_keycode_from_keysym(keymap, keysym, &keycode);
+ }
+
+ return keycode;
+}
+
+static uint32_t
+tz_devicemgr_client_get_device_clas(struct ds_tizen_input_devicemgr *tz_devicemgr,
+ struct wl_resource *resource)
+{
+ struct ds_tizen_input_devicemgr_client *client_data;
+
+ wl_list_for_each(client_data, &tz_devicemgr->clients, link) {
+ if (client_data->resource == resource)
+ return client_data->clas;
+ }
+ return 0;
+}
+
+static void
+device_manager_handle_generate_key(struct wl_client *client,
+ struct wl_resource *resource, const char *keyname, uint32_t pressed)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+ int keycode = 0;
+ bool res;
+ struct ds_keyboard *kbd;
+ uint32_t clas;
+
+ tz_devicemgr = wl_resource_get_user_data(resource);
+
+ clas = tz_devicemgr_client_get_device_clas(tz_devicemgr, resource);
+ if ((clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) == 0)
+ {
+ ds_err("Keyboard generator is not initialized by client");
+ goto finish;
+ }
+
+ if (!tz_devicemgr->devices.kbd ||
+ !tz_devicemgr->devices.kbd->input_device) {
+ ds_err("Keyboard device is not initialized\n");
+ goto finish;
+ }
+
+ if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
+ TIZEN_PRIV_INPUT_GENERATOR)) {
+ ds_err("No permission to input generate");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
+ goto finish;
+ }
+
+ // keyname to keycode using xkb_info
+ kbd = ds_input_device_get_keyboard(
+ tz_devicemgr->devices.kbd->input_device);
+ if (kbd->keymap) {
+ keycode = tz_devicemgr_xkb_keyname_to_keycode(kbd->keymap, keyname);
+ }
+
+ if (keycode <= 0) {
+ keycode = tz_devicemgr_keyname_to_keycode(&tz_devicemgr->keymap_list,
+ keyname);
+ }
+ if (keycode <= 0)
+ goto finish;
+
+ res = tz_devicemgr_generate_key(tz_devicemgr->devices.kbd->input_device,
+ keycode, pressed);
+ if (!res) {
+ ds_err("Generating key is failed. key: %s, pressed: %d",
+ keyname, pressed);
+ goto finish;
+ }
+ res = tz_devicemgr_pressed_keys_update(tz_devicemgr, keycode, pressed);
+ if (!res) {
+ ds_err("Updating pressed keys is failed. key: %s, pressed: %d",
+ keyname, pressed);
+ goto finish;
+ }
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+finish:
+ tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+device_manager_handle_generate_pointer(struct wl_client *client,
+ struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y,
+ uint32_t button)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+ bool res;
+ bool state;
+ uint32_t clas;
+
+ tz_devicemgr = wl_resource_get_user_data(resource);
+
+ clas = tz_devicemgr_client_get_device_clas(tz_devicemgr, resource);
+ if ((clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE) == 0)
+ {
+ ds_err("Pointer generator is not initialized by client");
+ goto finish;
+ }
+
+ if (!tz_devicemgr->devices.ptr ||
+ !tz_devicemgr->devices.ptr->input_device) {
+ ds_err("Pointer device is not initialized\n");
+ goto finish;
+ }
+
+ if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
+ TIZEN_PRIV_INPUT_GENERATOR)) {
+ ds_err("No permission to input generate");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
+ goto finish;
+ }
+
+ if (button <= 0 || button >= TIZEN_INPUT_DEVICEMGR_MAX_BTN)
+ {
+ ds_err("Invalid button: %d\n", button);
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+ goto finish;
+ }
+
+ if (type == TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE) {
+ res = tz_devicemgr_generate_mouse_move(
+ tz_devicemgr->devices.ptr->input_device, (double)x, (double)y);
+ if (!res) goto finish;
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+ }
+ else {
+ state = (type == TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN) ?
+ true : false;
+ res = tz_devicemgr_generate_mouse_button(
+ tz_devicemgr->devices.ptr->input_device, button, state);
+ if (!res) goto finish;
+ if (state) tz_devicemgr->devices.ptr->mouse.pressed |= 1 << (button - 1);
+ else tz_devicemgr->devices.ptr->mouse.pressed &= ~(1 << (button - 1));
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+ }
+
+finish:
+ tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+device_manager_handle_generate_touch(struct wl_client *client,
+ struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y,
+ uint32_t finger)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+ double transformed_x = .0, transformed_y = .0;
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+ bool res;
+ uint32_t clas;
+
+ tz_devicemgr = wl_resource_get_user_data(resource);
+
+ clas = tz_devicemgr_client_get_device_clas(tz_devicemgr, resource);
+ if ((clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN) == 0)
+ {
+ ds_err("Touch generator is not initialized by client");
+ goto finish;
+ }
+
+ if (!tz_devicemgr->devices.touch ||
+ !tz_devicemgr->devices.touch->input_device) {
+ ds_err("Touch device is not initialized\n");
+ goto finish;
+ }
+
+ if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
+ TIZEN_PRIV_INPUT_GENERATOR)) {
+ ds_err("No permission to input generate");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
+ goto finish;
+ }
+
+ if (finger >= tz_devicemgr->touch_max_count)
+ {
+ ds_err("Invalid fingers: %d\n", finger);
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+ goto finish;
+ }
+
+ if (tz_devicemgr->output.width != 0 && tz_devicemgr->output.height != 0) {
+ transformed_x = x / (double)tz_devicemgr->output.width;
+ transformed_y = y / (double)tz_devicemgr->output.height;
+ }
+
+ switch(type) {
+ case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN: // 0
+ res = tz_devicemgr_generate_touch_move(
+ tz_devicemgr->devices.touch->input_device, transformed_x, transformed_y, finger);
+ if (!res) break;
+ res= tz_devicemgr_generate_touch_down(
+ tz_devicemgr->devices.touch->input_device, transformed_x, transformed_y, finger);
+ if (!res) break;
+ tz_devicemgr->devices.touch->touch.pressed |= 1 << finger;
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+ break;
+ case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END: // 2
+ res = tz_devicemgr_generate_touch_up(
+ tz_devicemgr->devices.touch->input_device, finger);
+ if (!res) break;
+ tz_devicemgr->devices.touch->touch.pressed &= ~(1 << finger);
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+ break;
+ case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE: // 1
+ res = tz_devicemgr_generate_touch_move(
+ tz_devicemgr->devices.touch->input_device, transformed_x, transformed_y, finger);
+ if (!res) break;
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+ break;
+ default:
+ break;
+ }
+
+finish:
+ tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+device_manager_handle_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static bool
+tz_devicemgr_check_privilege(struct ds_tizen_input_devicemgr *tz_devicemgr,
+ struct wl_client *client, const char *rule)
+{
+ pid_t pid = 0;
+ uid_t uid = 0;
+ gid_t gid = 0;
+
+ if (!client) return false;
+
+ wl_client_get_credentials(client, &pid, &uid, &gid);
+
+ return tizen_security_check_privilege(pid, uid, rule);
+}
+
+static const struct ds_input_device_interface input_device_iface =
+{
+ .destroy = NULL,
+};
+
+static struct ds_keyboard *
+create_ds_keyboard()
+{
+ struct ds_keyboard *kbd;
+ kbd = calloc(1, sizeof *kbd);
+ if (!kbd) {
+ ds_err("Could not allocate memory");
+ return NULL;
+ }
+ ds_keyboard_init(kbd, NULL);
+
+ return kbd;
+}
+
+static struct ds_pointer *
+create_ds_pointer()
+{
+ struct ds_pointer *pointer;
+ pointer = calloc(1, sizeof *pointer);
+ if (!pointer) {
+ ds_err("Could not allocate memory");
+ return NULL;
+ }
+ ds_pointer_init(pointer, NULL);
+
+ return pointer;
+}
+
+static struct ds_touch *
+create_ds_touch()
+{
+ struct ds_touch *touch;
+ touch = calloc(1, sizeof *touch);
+ if (!touch) {
+ ds_err("Could not allocate memory");
+ return NULL;
+ }
+ ds_touch_init(touch, NULL);
+
+ return touch;
+}
+
+static int
+tz_devicemgr_create_device(struct ds_tizen_input_devicemgr_device *dev,
+ uint32_t clas, const char *name)
+{
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+ const char *dev_name;
+
+ if (dev->name && strlen(dev->name) > 0) {
+ ds_inf("device already has name. name:%s", dev->name);
+ return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+ }
+
+ if (dev->input_device) {
+ dev_name = ds_input_device_get_name(dev->input_device);
+ ds_inf("device was already set. name:%s", dev_name);
+ dev->name = strdup(dev_name);
+ return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+ }
+
+ //input_device create
+ dev->input_device = calloc(1, sizeof(struct ds_input_device));
+ if(!dev->input_device) {
+ ds_err("Failed to create input device !\n");
+ return ret;
+ }
+
+ if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD)
+ {
+ ds_input_device_init(dev->input_device, DS_INPUT_DEVICE_KEYBOARD,
+ &input_device_iface, name, -1, -1);
+ dev->input_device->keyboard = create_ds_keyboard();
+ }
+ else if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE)
+ {
+ ds_input_device_init(dev->input_device, DS_INPUT_DEVICE_POINTER,
+ &input_device_iface, name, -1, -1);
+ dev->input_device->pointer = create_ds_pointer();
+ }
+ else if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN)
+ {
+ ds_input_device_init(dev->input_device, DS_INPUT_DEVICE_TOUCH,
+ &input_device_iface, name, -1, -1);
+ dev->input_device->touch = create_ds_touch();
+ }
+
+ dev->created = true;
+ dev->name = strdup(name);
+
+ return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+}
+
+static int
+tz_devicemgr_init_generator(struct ds_tizen_input_devicemgr *tz_devicemgr,
+ struct wl_resource *resource, uint32_t clas, const char *name)
+{
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+ struct ds_tizen_input_devicemgr_client *client_data;
+ struct ds_tizen_input_devicemgr_device *dev;
+ bool inited = false;
+
+ ds_inf("Init generator. name:%s", name);
+
+ if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) {
+ dev = tz_devicemgr->devices.kbd;
+ ret = tz_devicemgr_create_device(dev, clas, name);
+ if (ret == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
+ inited = true;
+ tz_devicemgr->devices.kbd->ref++;
+ }
+ if (dev->created) {
+ wl_signal_emit(&tz_devicemgr->backend->events.new_input,
+ dev->input_device);
+ }
+ }
+ if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE) {
+ dev = tz_devicemgr->devices.ptr;
+ ret = tz_devicemgr_create_device(dev, clas, name);
+ if (ret == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
+ inited = true;
+ tz_devicemgr->devices.ptr->ref++;
+ }
+ if (dev->created) {
+ wl_signal_emit(&tz_devicemgr->backend->events.new_input,
+ dev->input_device);
+ }
+ }
+ if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN) {
+ dev = tz_devicemgr->devices.touch;
+ ret = tz_devicemgr_create_device(dev, clas, name);
+ if (ret == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
+ inited = true;
+ tz_devicemgr->devices.touch->ref++;
+ }
+ if (dev->created) {
+ wl_signal_emit(&tz_devicemgr->backend->events.new_input,
+ dev->input_device);
+ }
+ }
+
+ if (inited) {
+ wl_list_for_each(client_data, &tz_devicemgr->clients, link) {
+ if (client_data->resource == resource) {
+ if (client_data->init == false) {
+ client_data->init = true;
+ client_data->clas = clas;
+ }
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int
+tz_devicemgr_deinit_generator(struct ds_tizen_input_devicemgr *tz_devicemgr,
+ struct wl_resource *resource)
+{
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+ struct ds_tizen_input_devicemgr_client *client_data;
+ struct ds_tizen_input_devicemgr_device *dev;
+ uint32_t clas = 0;
+ int i = 0;
+ bool res;
+
+ ds_inf("Deinit generator.");
+ wl_list_for_each(client_data, &tz_devicemgr->clients, link) {
+ if (client_data->resource == resource) {
+ if (client_data->init == true) {
+ client_data->init = false;
+ clas = client_data->clas;
+ break;
+ } else {
+ return ret;
+ }
+ }
+ }
+ if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) {
+ dev = tz_devicemgr->devices.kbd;
+ dev->ref--;
+ if (dev->ref<= 0) {
+ dev->ref = 0;
+ tz_devicemgr_pressed_keys_cleanup(tz_devicemgr);
+
+ if (dev->created) {
+ tz_devicemgr_device_close(dev);
+ dev->created = false;
+ }
+ free(dev->name);
+ dev->name = NULL;
+ }
+ }
+ if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE) {
+ dev = tz_devicemgr->devices.ptr;
+ dev->ref--;
+ if (dev->ref <= 0) {
+ dev->ref = 0;
+ while(dev->mouse.pressed)
+ {
+ if (dev->mouse.pressed & (1 << i))
+ {
+ res = tz_devicemgr_generate_mouse_button(dev->input_device,
+ i + 1, false);
+ if (!res) break;
+ dev->mouse.pressed &= ~(1 << i);
+ }
+ i++;
+ if (i >= TIZEN_INPUT_DEVICEMGR_MAX_BTN) break;
+ }
+
+ if (dev->created)
+ {
+ tz_devicemgr_device_close(dev);
+ dev->created = false;
+ }
+ free(dev->name);
+ dev->name = NULL;
+ }
+ }
+ if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN) {
+ dev = tz_devicemgr->devices.touch;
+ dev->ref--;
+ if (dev->ref <= 0) {
+ dev->ref = 0;
+ while(dev->touch.pressed)
+ {
+ if (dev->touch.pressed & (1 << i))
+ {
+ res = tz_devicemgr_generate_touch_up(dev->input_device,
+ i);
+ if (!res) break;
+ dev->touch.pressed &= ~(1 << i);
+ }
+ i++;
+ if (i >= tz_devicemgr->touch_max_count) break;
+ }
+
+ if (dev->created)
+ {
+ tz_devicemgr_device_close(dev);
+ dev->created = false;
+ }
+ free(dev->name);
+ dev->name = NULL;
+ }
+ }
+
+ return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+}
+
+static int
+tz_devicemgr_keyname_to_keycode(struct wl_list *list, const char *name)
+{
+ struct ds_tizen_input_devicemgr_keymap_data *data;
+
+ if (!wl_list_empty(list)) {
+ wl_list_for_each(data, list, link) {
+ if (!strcmp(data->name, name)) {
+ return data->keycode;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static bool
+tz_devicemgr_generate_key(struct ds_input_device *device, int keycode,
+ int pressed)
+{
+ struct ds_event_keyboard_key ds_event;
+ struct timeval time;
+ unsigned int timestamp;
+ struct ds_keyboard *kbd;
+
+ kbd = ds_input_device_get_keyboard(device);
+ if (!kbd) {
+ ds_err("No ds_keyboard to notify event");
+ return false;
+ }
+
+ gettimeofday(&time, NULL);
+ timestamp = time.tv_sec * 1000 + time.tv_usec / 1000;
+
+ ds_event.time_msec = timestamp;
+ ds_event.keycode = keycode - 8;
+ if (pressed)
+ ds_event.state = WL_KEYBOARD_KEY_STATE_PRESSED;
+ else
+ ds_event.state = WL_KEYBOARD_KEY_STATE_RELEASED;
+
+ ds_inf("Generate key. kbd:%p, key:%d, state:%s", kbd, ds_event.keycode,
+ (ds_event.state == WL_KEYBOARD_KEY_STATE_PRESSED) ?
+ "PRESSED" : "RELEASED");
+
+ ds_keyboard_notify_key(kbd, &ds_event);
+
+ return true;
+}
+
+static bool
+tz_devicemgr_pressed_keys_update(struct ds_tizen_input_devicemgr *tz_devicemgr,
+ int keycode, bool pressed)
+{
+ struct ds_tizen_input_devicemgr_key_info *key, *tmp;
+
+ if (pressed) {
+ key = calloc(1, sizeof(*key));
+ if (!key) {
+ ds_err("Failed to alloc keydata memory.\n");
+ return false;
+ }
+ key->keycode = keycode;
+ wl_list_init(&key->link);
+ wl_list_insert(&tz_devicemgr->devices.kbd->key.pressed, &key->link);
+ }
+ else {
+ wl_list_for_each_safe(key, tmp, &tz_devicemgr->devices.kbd->key.pressed, link) {
+ if (key->keycode == keycode) {
+ wl_list_remove(&key->link);
+ free(key);
+ break;
+ }
+ }
+ }
+
+ ds_inf("Update pressed keys. length: %d, keycode:%d, pressed:%d",
+ wl_list_length(&tz_devicemgr->devices.kbd->key.pressed), keycode, pressed);
+
+ return true;
+}
+
+static void
+tz_devicemgr_pressed_keys_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr)
+{
+ struct ds_tizen_input_devicemgr_key_info *keydata, *tmp;
+
+ ds_inf("Clean up the kbd.pressed_keys. length: %d",
+ wl_list_length(&tz_devicemgr->devices.kbd->key.pressed));
+
+ wl_list_for_each_safe(keydata, tmp, &tz_devicemgr->devices.kbd->key.pressed, link) {
+ if (tz_devicemgr->devices.kbd)
+ tz_devicemgr_generate_key(tz_devicemgr->devices.kbd->input_device,
+ keydata->keycode, false);
+ wl_list_remove(&keydata->link);
+ free(keydata);
+ }
+}
+
+static void
+tz_devicemgr_keymap_list_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr)
+{
+ struct ds_tizen_input_devicemgr_keymap_data *keymap, *tmp;
+
+ ds_inf("Clean up the keymap_list. length: %d",
+ wl_list_length(&tz_devicemgr->keymap_list));
+
+ wl_list_for_each_safe(keymap, tmp, &tz_devicemgr->keymap_list, link) {
+ free(keymap->name);
+ wl_list_remove(&keymap->link);
+ free(keymap);
+ }
+}
+
+static bool
+tz_devicemgr_generate_touch_move(struct ds_input_device *device, double x, double y,
+ uint32_t finger)
+{
+ struct ds_event_touch_motion ds_event;
+ struct timeval time;
+ unsigned int timestamp;
+ struct ds_touch *touch;
+
+ touch = ds_input_device_get_touch(device);
+ if (!touch) {
+ ds_err("No ds_touch to notify event");
+ return false;
+ }
+
+ gettimeofday(&time, NULL);
+ timestamp = time.tv_sec * 1000 + time.tv_usec / 1000;
+
+ ds_event.time_msec = timestamp;
+ ds_event.id = finger;
+ ds_event.x = x;
+ ds_event.y = y;
+ ds_inf("Generate touch motion. touch:%p, id:%d (%d, %d)", touch, ds_event.id, x, y);
+
+ wl_signal_emit(&touch->events.motion, &ds_event);
+
+ return true;
+}
+
+static bool
+tz_devicemgr_generate_touch_down(struct ds_input_device *device, double x, double y,
+ uint32_t finger)
+{
+ struct ds_event_touch_down ds_event;
+ struct timeval time;
+ unsigned int timestamp;
+ struct ds_touch *touch;
+
+ touch = ds_input_device_get_touch(device);
+ if (!touch) {
+ ds_err("No ds_touch to notify event");
+ return false;
+ }
+
+ gettimeofday(&time, NULL);
+ timestamp = time.tv_sec * 1000 + time.tv_usec / 1000;
+
+ ds_event.time_msec = timestamp;
+ ds_event.id = finger;
+ ds_event.x = x;
+ ds_event.y = y;
+ ds_inf("Generate touch down. touch:%p, id:%d (%d, %d)", touch, ds_event.id, x, y);
+
+ wl_signal_emit(&touch->events.down, &ds_event);
+
+ return true;
+}
+
+static bool
+tz_devicemgr_generate_touch_up(struct ds_input_device *device, uint32_t finger)
+{
+ struct ds_event_touch_up ds_event;
+ struct timeval time;
+ unsigned int timestamp;
+ struct ds_touch *touch;
+
+ touch = ds_input_device_get_touch(device);
+ if (!touch) {
+ ds_err("No ds_touch to notify event");
+ return false;
+ }
+
+ gettimeofday(&time, NULL);
+ timestamp = time.tv_sec * 1000 + time.tv_usec / 1000;
+
+ ds_event.time_msec = timestamp;
+ ds_event.id = finger;
+ ds_inf("Generate touch up. touch:%p, id:%d", touch, ds_event.id);
+
+ wl_signal_emit(&touch->events.up, &ds_event);
+
+ return true;
+}
+
+static bool
+tz_devicemgr_generate_mouse_move(struct ds_input_device *device, double x, double y)
+{
+ struct ds_event_pointer_motion ds_event;
+ struct timeval time;
+ unsigned int timestamp;
+ struct ds_pointer *pointer;
+
+ pointer = ds_input_device_get_pointer(device);
+ if (!pointer) {
+ ds_err("No ds_pointer to notify event");
+ return false;
+ }
+
+ gettimeofday(&time, NULL);
+ timestamp = time.tv_sec * 1000 + time.tv_usec / 1000;
+
+ ds_event.time_msec = timestamp;
+ ds_event.delta_x = x;
+ ds_event.delta_y = y;
+ ds_inf("Generate mouse motion. pointer:%p, x:%f, y:%f", pointer, ds_event.delta_x, ds_event.delta_y);
+
+ wl_signal_emit(&pointer->events.motion, &ds_event);
+
+ return true;
+}
+
+static bool
+tz_devicemgr_generate_mouse_button(struct ds_input_device *device, uint32_t button, bool state)
+{
+ struct ds_event_pointer_button ds_event;
+ struct timeval time;
+ unsigned int timestamp;
+ struct ds_pointer *pointer;
+
+ pointer = ds_input_device_get_pointer(device);
+ if (!pointer) {
+ ds_err("No ds_pointer to notify event");
+ return false;
+ }
+
+ gettimeofday(&time, NULL);
+ timestamp = time.tv_sec * 1000 + time.tv_usec / 1000;
+
+ ds_event.time_msec = timestamp;
+ ds_event.button = button;
+ if (state)
+ ds_event.state = DS_BUTTON_PRESSED;
+ else
+ ds_event.state = DS_BUTTON_RELEASED;
+ ds_inf("Generate mouse button. pointer:%p, button:%d, state:%s", pointer, ds_event.button, state ? "PRESSED" : "RELEASED");
+
+ wl_signal_emit(&pointer->events.button, &ds_event);
+
+ return true;
+}
+
+static void
+devicemgr_keyboard_grab_iface_enter(struct ds_seat_keyboard_grab *grab,
+ struct ds_surface *surface, uint32_t keycodes[],
+ size_t num_keycodes, struct ds_keyboard_modifiers *modifiers)
+{
+ ds_inf("devicemgr. keyboard_grab_iface_enter");
+}
+
+static void
+devicemgr_keyboard_grab_iface_clear_focus(struct ds_seat_keyboard_grab *grab)
+{
+ ds_inf("devicemgr. keyboard_grab_iface_clear_focus");
+}
+
+static void
+tz_devicemgr_blocked_keys_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr)
+{
+ struct ds_tizen_input_devicemgr_key_info *keydata, *tmp;
+
+ ds_inf("Clean up the blocked keys. length: %d",
+ wl_list_length(&tz_devicemgr->blocked_keys));
+
+ wl_list_for_each_safe(keydata, tmp, &tz_devicemgr->blocked_keys, link) {
+ wl_list_remove(&keydata->link);
+ free(keydata);
+ }
+}
+
+static void
+devicemgr_keyboard_grab_iface_key(struct ds_seat_keyboard_grab *grab,
+ uint32_t time_msec, uint32_t key, uint32_t state)
+{
+ struct ds_tizen_input_devicemgr *devicemgr;
+ struct ds_tizen_input_devicemgr_key_info *keydata, *tmp;
+ bool key_blocked = false;
+
+ ds_inf("devicemgr. keyboard_grab_iface_key");
+
+ devicemgr = ds_seat_keyboard_grab_get_data(grab);
+ if (!devicemgr->block_resource) {
+ if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
+ goto finish;
+ }
+ else {
+ wl_list_for_each_safe(keydata, tmp, &devicemgr->blocked_keys, link) {
+ if (keydata->keycode == (int)key) {
+ wl_list_remove(&keydata->link);
+ free(keydata);
+ key_blocked = true;
+ break;
+ }
+ }
+ if (wl_list_empty(&devicemgr->blocked_keys)) {
+ tz_devicemgr_ungrab_keyboard(devicemgr);
+ }
+ if (key_blocked) {
+ goto finish;
+ }
+ }
+ }
+
+ if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
+ keydata = calloc(1, sizeof (*keydata));
+ if (!keydata)
+ goto finish;
+ keydata->keycode = key;
+ wl_list_init(&keydata->link);
+ wl_list_insert(&devicemgr->blocked_keys, &keydata->link);
+ key_blocked = true;
+ }
+ else {
+ if (wl_list_empty(&devicemgr->blocked_keys))
+ goto finish;
+ wl_list_for_each_safe(keydata, tmp, &devicemgr->blocked_keys, link) {
+ if (keydata->keycode == (int)key) {
+ wl_list_remove(&keydata->link);
+ free(keydata);
+ key_blocked = true;
+ }
+ }
+ }
+
+finish:
+ if (!key_blocked)
+ ds_inf("block key event: (%d %s)\n", key, (state ? "press" : "release"));
+}
+
+static void
+devicemgr_modifiers_grab_iface_key(struct ds_seat_keyboard_grab *grab,
+ struct ds_keyboard_modifiers *modifiers)
+{
+ ds_inf("devicemgr. modifiers_grab_iface_key");
+}
+
+static void
+devicemgr_cancel_grab_iface_key(struct ds_seat_keyboard_grab *grab)
+{
+ ds_inf("devicemgr. cancel_grab_iface_key");
+}
+
+static const struct ds_keyboard_grab_interface devicemgr_keyboard_grab_iface = {
+ .enter = devicemgr_keyboard_grab_iface_enter,
+ .clear_focus = devicemgr_keyboard_grab_iface_clear_focus,
+ .key = devicemgr_keyboard_grab_iface_key,
+ .modifiers = devicemgr_modifiers_grab_iface_key,
+ .cancel = devicemgr_cancel_grab_iface_key,
+};
+
+static void
+tz_devicemgr_grab_keyboard(struct ds_tizen_input_devicemgr *tz_devicemgr)
+{
+ ds_seat_keyboard_start_grab(tz_devicemgr->seat, tz_devicemgr->grab);
+}
+
+static void
+tz_devicemgr_ungrab_keyboard(struct ds_tizen_input_devicemgr *tz_devicemgr)
+{
+ ds_seat_keyboard_end_grab(tz_devicemgr->seat);
+}
+
+static void
+tz_devicemgr_ungrab_keyboard_check(struct ds_tizen_input_devicemgr *tz_devicemgr)
+{
+ if (wl_list_empty(&tz_devicemgr->blocked_keys))
+ tz_devicemgr_ungrab_keyboard(tz_devicemgr);
+
+ tz_devicemgr->block_resource = NULL;
+}
+
+static bool
+devicemgr_add_timer(struct ds_tizen_input_devicemgr *tz_devicemgr,
+ wl_event_loop_timer_func_t func, int time)
+{
+ struct wl_event_loop *event_loop;
+
+ event_loop = wl_display_get_event_loop(tz_devicemgr->backend->display);
+ if (!event_loop) {
+ ds_err("Failed to get event_loop from display: %p",
+ tz_devicemgr->backend->display);
+ return false;
+ }
+
+ tz_devicemgr->timer = wl_event_loop_add_timer(event_loop, func,
+ tz_devicemgr);
+ if (!tz_devicemgr->timer) {
+ ds_err("Failed to timer");
+ return false;
+ }
+ wl_event_source_timer_update(tz_devicemgr->timer, time);
+
+ return true;
+}
+
+static int
+devicemgr_block_timer(void *data)
+{
+ struct ds_tizen_input_devicemgr *devicemgr = data;
+
+ tizen_input_device_manager_send_block_expired(devicemgr->block_resource);
+
+ tz_devicemgr_ungrab_keyboard_check(devicemgr);
+
+ wl_event_source_remove(devicemgr->timer);
+ devicemgr->timer = NULL;
+
+ return 1;
+}
+
+static void
+device_manager_handle_block_events(struct wl_client *client,
+ struct wl_resource *resource, uint32_t serial, uint32_t clas,
+ uint32_t duration)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+ bool res;
+
+ tz_devicemgr = wl_resource_get_user_data(resource);
+
+ if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
+ TIZEN_PRIV_INPUT_BLOCK)) {
+ ds_err("No permission to input generate");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
+ goto finish;
+ }
+
+ if (clas != TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) {
+ ds_err("only support keyboard device. (requested: 0x%x)\n", clas);
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+ goto finish;
+ }
+
+ if(tz_devicemgr->block_resource) {
+ ds_err("currently the input system is already blocked\n");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+ goto finish;
+ }
+
+ res = devicemgr_add_timer(tz_devicemgr, devicemgr_block_timer, duration);
+ if (!res) {
+ ds_err("Failed to add a timer\n");
+ goto finish;
+ }
+
+ tz_devicemgr_grab_keyboard(tz_devicemgr);
+ tz_devicemgr->block_resource = resource;
+ ds_inf("Block events. clas: %d, duration:%d", clas, duration);
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+finish:
+ tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+device_manager_handle_unblock_events(struct wl_client *client,
+ struct wl_resource *resource, uint32_t serial)
+{
+ struct ds_tizen_input_devicemgr *tz_devicemgr;
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+
+ tz_devicemgr = wl_resource_get_user_data(resource);
+
+ if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
+ TIZEN_PRIV_INPUT_BLOCK)) {
+ ds_err("No permission to input generate");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
+ goto finish;
+ }
+
+ if (tz_devicemgr->block_resource != resource) {
+ ds_err("currently the input system is blocked by another resource");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+ goto finish;
+ }
+
+ tz_devicemgr_ungrab_keyboard_check(tz_devicemgr);
+ tz_devicemgr->block_resource = NULL;
+ ds_inf("Unblock events.");
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+ if (tz_devicemgr->timer) {
+ wl_event_source_remove(tz_devicemgr->timer);
+ tz_devicemgr->timer = NULL;
+ }
+
+finish:
+ tizen_input_device_manager_send_error(resource, ret);
+}
+