From 6352c4116e2746ea0bd1f1f18398bba225037863 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Tue, 7 Jun 2022 19:38:39 +0900 Subject: [PATCH] devicemgr: implement libds-tizen-input-devicemgr Change-Id: I7b5d45cd96122bb4f5d7926bd6d3d830475f5696 --- include/libds-tizen/input-devicemgr.h | 40 + include/libds/input_device.h | 3 + include/libds/interfaces/backend.h | 3 +- packaging/libds.spec | 30 + src/clients/input-generator.c | 540 +++++++++++ src/clients/meson.build | 15 + src/clients/simple-tbm.c | 84 +- src/examples/meson.build | 1 + src/examples/tinyds-tdm-libinput.c | 141 ++- src/libds-tizen/backend/tdm/backend.c | 2 +- src/libds-tizen/input-devicemgr/input-devicemgr.c | 1063 +++++++++++++++++++++ src/libds-tizen/input-devicemgr/input-devicemgr.h | 59 ++ src/libds-tizen/input-devicemgr/meson.build | 30 + src/libds-tizen/meson.build | 1 + src/libds/backend.c | 2 + src/libds/backend/libinput/backend.c | 4 +- src/libds/backend/libinput/input.c | 2 + src/libds/backend/wayland/backend.c | 2 +- src/libds/input_device.c | 9 + src/libds/seat/seat_keyboard.c | 2 +- 20 files changed, 2018 insertions(+), 15 deletions(-) create mode 100644 include/libds-tizen/input-devicemgr.h create mode 100644 src/clients/input-generator.c create mode 100644 src/libds-tizen/input-devicemgr/input-devicemgr.c create mode 100644 src/libds-tizen/input-devicemgr/input-devicemgr.h create mode 100644 src/libds-tizen/input-devicemgr/meson.build diff --git a/include/libds-tizen/input-devicemgr.h b/include/libds-tizen/input-devicemgr.h new file mode 100644 index 0000000..a9ed808 --- /dev/null +++ b/include/libds-tizen/input-devicemgr.h @@ -0,0 +1,40 @@ +#ifndef LIBDS_TIZEN_INPUT_DEVICEMGR_H +#define LIBDS_TIZEN_INPUT_DEVICEMGR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tizen_input_devicemgr; +struct ds_backend; +struct ds_seat; + +struct ds_tizen_input_devicemgr_keymap_data +{ + char *name; + int keycode; + + struct wl_list link; +}; + +struct ds_tizen_input_devicemgr * +ds_tizen_input_devicemgr_create(struct ds_backend *backend, + struct ds_seat *seat); + +void +ds_tizen_input_devicemgr_add_destroy_listener( + struct ds_tizen_input_devicemgr *devicemgr, + struct wl_listener *listener); + +bool +ds_tizen_input_devicemgr_set_keymap_list( + struct ds_tizen_input_devicemgr *devicemgr, + struct wl_list *list); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/libds/input_device.h b/include/libds/input_device.h index 1a3652b..55aabbd 100644 --- a/include/libds/input_device.h +++ b/include/libds/input_device.h @@ -25,6 +25,9 @@ enum ds_input_device_type enum ds_input_device_type ds_input_device_get_type(struct ds_input_device *dev); +const char * +ds_input_device_get_name(struct ds_input_device *dev); + struct ds_pointer * ds_input_device_get_pointer(struct ds_input_device *dev); diff --git a/include/libds/interfaces/backend.h b/include/libds/interfaces/backend.h index bad37a0..55a2475 100644 --- a/include/libds/interfaces/backend.h +++ b/include/libds/interfaces/backend.h @@ -29,7 +29,8 @@ struct ds_backend }; void -ds_backend_init(struct ds_backend *backend, const struct ds_backend_interface *iface); +ds_backend_init(struct ds_backend *backend, struct wl_display *display, + const struct ds_backend_interface *iface); void ds_backend_finish(struct ds_backend *backend); diff --git a/packaging/libds.spec b/packaging/libds.spec index 6260ed2..f53efa9 100644 --- a/packaging/libds.spec +++ b/packaging/libds.spec @@ -12,6 +12,7 @@ BuildRequires: pkgconfig(wayland-server) BuildRequires: pkgconfig(wayland-client) BuildRequires: pkgconfig(wayland-protocols) BuildRequires: pkgconfig(tizen-extension-server) +BuildRequires: pkgconfig(tizen-extension-client) BuildRequires: pkgconfig(pixman-1) BuildRequires: pkgconfig(libdrm) BuildRequires: pkgconfig(xkbcommon) @@ -59,6 +60,20 @@ Group: Development/Libraries %description tizen-keyrouter-devel Keyrouter Development package for Wayland Compositor Library +%package tizen-input-devicemgr +Summary: Library for tizen input devicemgr +Group: Development/Libraries + +%description tizen-input-devicemgr +Library for tizen input devicemgr + +%package tizen-input-devicemgr-devel +Summary: Development package for tizen input devicemgr +Group: Development/Libraries + +%description tizen-input-devicemgr-devel +Development package for tizen input devicemgr + %prep %setup -q cp %{SOURCE1001} . @@ -110,6 +125,7 @@ ninja -C builddir install %{_bindir}/ds-simple-shm-shell %{_bindir}/tinyds-tdm-dpms %{_bindir}/ds-simple-dpms +%{_bindir}/input-generator %files tizen-keyrouter %manifest %{name}.manifest @@ -124,3 +140,17 @@ ninja -C builddir install %{_includedir}/libds-tizen/keyrouter.h %{_libdir}/pkgconfig/libds-tizen-keyrouter.pc %{_libdir}/libds-tizen-keyrouter.so + +%files tizen-input-devicemgr +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_libdir}/libds-tizen-input-devicemgr.so.* + +%files tizen-input-devicemgr-devel +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_includedir}/libds-tizen/input-devicemgr.h +%{_libdir}/pkgconfig/libds-tizen-input-devicemgr.pc +%{_libdir}/libds-tizen-input-devicemgr.so diff --git a/src/clients/input-generator.c b/src/clients/input-generator.c new file mode 100644 index 0000000..f61e84b --- /dev/null +++ b/src/clients/input-generator.c @@ -0,0 +1,540 @@ +#include +#include +#include +#include +#include + +#include +#include + +#define MAX_STR 1024 +#define SIZE_EPOLL 16 + +enum enum_key_type +{ + KEY_UP = 0, + KEY_DOWN, + KEY_ALL +}; + +enum enum_touch_type +{ + TOUCH_BEGIN = 0, + TOUCH_UPDATE, + TOUCH_END, + TOUCH_ALL +}; + +struct display +{ + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + + struct tizen_input_device_manager *devicemgr; + enum tizen_input_device_manager_clas clas; + struct wl_event_queue *queue; + + int run; + int fd_epoll; + int fd_display; + + int request_notified; + int init; + + int enable_log; +}; + +struct display data_wl; + +static void +usage(void) +{ + printf(" Supported commands: init (Initialize input generator)\n"); + printf(" : deinit (Deinitialize input generator)\n"); + printf(" : key (Generate key events)\n"); + printf(" : touch (Generate touch events)\n"); + printf(" : help (Print this help text)\n"); + printf(" : q/quit (Quit program)\n"); + printf(" : log (Print detailed logs)\n"); + printf("init {device type}\n"); + printf(" : device type:\n"); + printf(" - default: all\n"); + printf(" - key/keyboard: keyboard\n"); + printf(" - touch: touch screen\n"); + printf(" - all: all of devices\n"); + printf(" : ex> init keyboard / init\n"); + printf("\n"); + printf("deinit\n"); + printf(" : ex> deinit\n"); + printf("\n"); + printf("key [keyname] {pressed}\n"); + printf(" : pressed:\n"); + printf(" - default: down&up pair\n"); + printf(" - key down: 1\n"); + printf(" - key up: 0\n"); + printf(" : ex> key XF86Back 1\n"); + printf("\n"); + printf("touch {index} {type} {x} {y}\n"); + printf(" : index:\n"); + printf(" - default: first finger(0)\n"); + printf(" - first finger is 0\n"); + printf(" : type:\n"); + printf(" - default: generate sample touch events\n"); + printf(" - touch begin: 1\n"); + printf(" - touch update: 2\n"); + printf(" - touch end: 3\n"); + printf(" : x/y:\n"); + printf(" - default: 0\n"); + printf(" : ex> touch / touch 0 1 100 100\n"); + printf("\n"); +} + +static void +init_input_generator(enum tizen_input_device_manager_clas clas) +{ + if (data_wl.init) { + printf("Already init input generator\n"); + return; + } + + tizen_input_device_manager_init_generator(data_wl.devicemgr, clas); + + while (data_wl.request_notified == -1) + wl_display_dispatch_queue(data_wl.display, data_wl.queue); + + if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + data_wl.init = 1; + printf("Success to init input generator\n"); + } else { + printf("Failed to init input generator: %d\n", data_wl.request_notified); + } + + data_wl.clas = clas; + data_wl.request_notified = -1; +} + +static void +deinit_input_generator(void) +{ + if (!data_wl.init) { + printf("input generator is not initialized\n"); + return; + } + + tizen_input_device_manager_deinit_generator(data_wl.devicemgr, data_wl.clas); + + while (data_wl.request_notified == -1) + wl_display_dispatch_queue(data_wl.display, data_wl.queue); + + if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + data_wl.init = 0; + printf("Success to deinit input generator\n"); + } else { + printf("Failed to deinit input generator: %d\n", data_wl.request_notified); + } + + data_wl.request_notified = -1; +} + +static void +input_generator_key(char *name, int type) +{ + tizen_input_device_manager_generate_key(data_wl.devicemgr, name, !!type); + + while (data_wl.request_notified == -1) + wl_display_dispatch_queue(data_wl.display, data_wl.queue); + + if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + if (data_wl.enable_log) { + printf("Success to generate key: %s key %s\n", name, type?"down":"up"); + } + } else { + printf("Failed to generate %s key %s: %d\n", name, type?"down":"up", data_wl.request_notified); + } + + data_wl.request_notified = -1; +} + +static void +key_generate(char *name, int type) +{ + printf("name: %s, type: %d\n", name, type); + + if (!data_wl.init) { + printf("Input genrator is not initialized\n"); + return; + } + + if (!name) { + printf("Type which key is generated\n"); + return; + } + + if (type == KEY_ALL) { + input_generator_key(name, 1); + input_generator_key(name, 0); + } else { + input_generator_key(name, !!type); + } +} + +static char * +touch_type_string_get(int type) +{ + switch (type) { + case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN: + return "begin"; + case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE: + return "update"; + case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END: + return "end"; + default: + return "Unknown"; + } +} + +static void +input_generator_touch(int idx, int type, int x, int y) +{ + tizen_input_device_manager_generate_touch(data_wl.devicemgr, type, x, y, idx); + + while (data_wl.request_notified == -1) + wl_display_dispatch_queue(data_wl.display, data_wl.queue); + + if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + if (data_wl.enable_log) { + printf("Success to generate touch: %d finger %s on (%d, %d)\n", idx, touch_type_string_get(type), x, y); + } + } else { + printf("Failed to generate touch(%d finger %s on (%d, %d)): %d\n", idx, touch_type_string_get(type), x, y, data_wl.request_notified); + } + + data_wl.request_notified = -1; +} + +static void +touch_generate(int idx, int type, int x, int y) +{ + if (!data_wl.init) { + printf("Input genrator is not initialized\n"); + return; + } + + if (type == TOUCH_ALL) { + input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 100, 100); + input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 200, 200); + input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 300, 300); + + input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 110, 110); + input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 210, 210); + input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 310, 310); + + input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 120, 120); + input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 220, 220); + input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 320, 320); + + input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 120, 120); + input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 220, 220); + input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 320, 320); + } else { + input_generator_touch(idx, type, x, y); + } +} + +static void +stdin_read(void) +{ + int c; + char buf[MAX_STR] = {0, }, *tmp, *buf_ptr, key_name[MAX_STR] = {0, }; + int count = 0; + int key_type = KEY_ALL, touch_idx = 0, touch_type = TOUCH_ALL, touch_x = 0, touch_y = 0; + + while ((c = getchar()) != EOF) { + if (c == '\n') break; + if (count >= MAX_STR) break; + + buf[count] = c; + count++; + } + + count = 0; + tmp = strtok_r(buf, " ", &buf_ptr); + if (!tmp) return; + + if (!strncmp(tmp, "init", sizeof("init"))) { + while (tmp) { + tmp = strtok_r(NULL, " ", &buf_ptr); + if (tmp) { + switch (count) { + case 0: + if (!strncmp("keyboard", tmp, MAX_STR-1)) + init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD); + else if (!strncmp("touch", tmp, MAX_STR-1)) + init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN); + break; + default: + break; + } + } + count++; + } + } else if (!strncmp(tmp, "deinit", sizeof("deinit"))) { + deinit_input_generator(); + } else if (!strncmp(tmp, "key", sizeof("key"))) { + while (tmp) { + tmp = strtok_r(NULL, " ", &buf_ptr); + if (tmp) { + switch (count) { + case 0: + strncpy(key_name, tmp, MAX_STR-1); + break; + case 1: + key_type = atoi(tmp); + break; + default: + break; + } + } + count++; + } + key_generate(key_name, key_type); + } else if (!strncmp(tmp, "touch", sizeof("touch"))) { + while (tmp) { + tmp = strtok_r(NULL, " ", &buf_ptr); + if (tmp) { + switch (count) { + case 0: + touch_idx = atoi(tmp); + break; + case 1: + touch_type = atoi(tmp); + break; + case 2: + touch_x = atoi(tmp); + break; + case 3: + touch_y = atoi(tmp); + break; + default: + break; + } + } + count++; + } + touch_generate(touch_idx, touch_type, touch_x, touch_y); + } else if (!strncmp(buf, "q", MAX_STR) || !strncmp(buf, "quit", MAX_STR)) { + data_wl.run = 0; + } else if (!strncmp(buf, "help", MAX_STR)) { + usage(); + } else if (!strncmp(buf, "log", MAX_STR)) { + if (data_wl.enable_log) + printf("Disable detailed logs\n"); + else + printf("Enable detailed logs\n"); + + data_wl.enable_log = !data_wl.enable_log; + } else { + printf("Invalid arguments\n"); + usage(); + } +} + +static void +input_device_manager_handle_error(void *data, + struct tizen_input_device_manager *tizen_input_device_manager, + uint32_t errorcode) +{ + if (data_wl.enable_log) + printf("errorcode: %d\n", errorcode); + data_wl.request_notified = errorcode; +} + +static const struct tizen_input_device_manager_listener _input_device_manager_listener = +{ + .device_add = NULL, + .device_remove = NULL, + .error = input_device_manager_handle_error, + .block_expired = NULL, +}; + +static void +registry_handle_global(void * data, struct wl_registry * registry, uint32_t id, + const char * interface, uint32_t version) +{ + if (strcmp(interface, "wl_compositor") == 0) { + data_wl.compositor = wl_registry_bind(registry, id, + &wl_compositor_interface, version); + if (!data_wl.compositor) { + printf("Failed to bind compositor."); + return; + } + if (data_wl.enable_log) + printf("Success to bind compositor."); + } else if (strcmp(interface, "tizen_input_device_manager") == 0) { + data_wl.devicemgr = wl_registry_bind(registry, id, + &tizen_input_device_manager_interface, version); + if (!data_wl.devicemgr) { + printf("Failed to bind input device manager"); + return; + } + if (data_wl.enable_log) + printf("Success to bind tizen input device manager."); + tizen_input_device_manager_add_listener(data_wl.devicemgr, + &_input_device_manager_listener, data_wl.display); + } +} + +static void +registry_handle_global_remove(void * data, struct wl_registry * registry, uint32_t id) +{ + if (data_wl.enable_log) + printf("registry is removed. id: %d !\n", id); +} + +static const struct wl_registry_listener _registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +static int +wayland_init(void) +{ + memset(&data_wl, 0, sizeof(struct display)); + data_wl.request_notified = -1; + + data_wl.display = wl_display_connect(NULL); + if (!data_wl.display) { + printf("Failed to connect wayland display\n"); + return 0; + } + + data_wl.queue = wl_display_create_queue(data_wl.display); + if (!data_wl.queue) { + printf("Failed to create queue\n"); + return 0; + } + + data_wl.registry = wl_display_get_registry(data_wl.display); + if (!data_wl.registry) { + printf("Failed to get registry\n"); + return 0; + } + + wl_proxy_set_queue((struct wl_proxy*)data_wl.registry, data_wl.queue); + wl_registry_add_listener(data_wl.registry, &_registry_listener, NULL); + + if (wl_display_dispatch_queue(data_wl.display, data_wl.queue) == -1) { + printf("Failed to dispatch display\n"); + return 0; + } + if (wl_display_roundtrip_queue(data_wl.display, data_wl.queue) == -1) { + printf("Failed to roundtrip display\n"); + return 0; + } + + return 1; +} + +static void +wayland_deinit(void) +{ + if (data_wl.enable_log) + printf("Shutdown wayland system\n"); + + if (data_wl.init) deinit_input_generator(); + + if (data_wl.queue) wl_event_queue_destroy(data_wl.queue); + if (data_wl.devicemgr) tizen_input_device_manager_destroy(data_wl.devicemgr); + if (data_wl.display) { + wl_registry_destroy(data_wl.registry); + wl_display_flush(data_wl.display); + wl_display_disconnect(data_wl.display); + } +} + +static int +epoll_init(void) +{ + struct epoll_event ep[2]; + + data_wl.fd_epoll = epoll_create(SIZE_EPOLL); + if (data_wl.fd_epoll <= 0) { + printf("Failed to epoll create: %d\n", SIZE_EPOLL); + return 0; + } + + data_wl.fd_display = wl_display_get_fd(data_wl.display); + + memset(ep, 0, sizeof(struct epoll_event)*2); + + ep[0].events = EPOLLIN | EPOLLERR | EPOLLHUP; + ep[0].data.fd = data_wl.fd_display; + epoll_ctl(data_wl.fd_epoll, EPOLL_CTL_ADD, data_wl.fd_display, &ep[0]); + ep[1].events = EPOLLIN | EPOLLERR | EPOLLHUP; + ep[1].data.fd = STDIN_FILENO; + epoll_ctl(data_wl.fd_epoll, EPOLL_CTL_ADD, 0, &ep[1]); + + return 1; +} + +static void +mainloop(void) +{ + struct epoll_event ep[SIZE_EPOLL]; + int res, count, i; + + res = epoll_init(); + if (!res) { + printf("Failed to init epoll\n"); + return; + } + + data_wl.run = 1; + while (data_wl.run) { + res = wl_display_dispatch_queue_pending(data_wl.display, data_wl.queue); + if (res < 0) { + printf("Failed to dispatch pending. result: %d\n", res); + data_wl.run = 0; + break; + } + res = wl_display_flush(data_wl.display); + if (res < 0) { + printf("Failed to flush display. result: %d\n", res); + data_wl.run = 0; + break; + } + + count = epoll_wait(data_wl.fd_epoll, ep, SIZE_EPOLL, -1); + for (i = 0; i < count; i++) { + if (ep[i].events & EPOLLIN) { + if (ep[i].data.fd == data_wl.fd_display) { + wl_display_dispatch_queue(data_wl.display, data_wl.queue); + } else { + stdin_read(); + } + } + if (ep[i].events & EPOLLERR) { + data_wl.run = 0; + } + if (ep[i].events & EPOLLHUP) { + data_wl.run = 0; + } + } + } +} + +int +main(int argc, char **argv) +{ + int res; + + res = wayland_init(); + if (!res) return 0; + + mainloop(); + + wayland_deinit(); + + return 0; +} diff --git a/src/clients/meson.build b/src/clients/meson.build index 6fcd3f8..ba09b32 100644 --- a/src/clients/meson.build +++ b/src/clients/meson.build @@ -12,6 +12,7 @@ executable('ds-simple-shm-shell', wayland_tbm_client = dependency('wayland-tbm-client', required: false) libtbm = dependency('libtbm', required: false) +tizen_extension_client = dependency('tizen-extension-client', required: true) if not wayland_tbm_client.found() or not libtbm.found() subdir_done() @@ -22,6 +23,7 @@ simple_tbm_deps = [ dependency('wayland-client', required: true), wayland_tbm_client, libtbm, + tizen_extension_client, ] protocols = { @@ -65,3 +67,16 @@ executable('ds-simple-dpms', install_dir: libds_bindir, install: true, ) + +input_generator_files = ['input-generator.c'] +input_generator_deps = [ + dependency('wayland-client', required: true), + tizen_extension_client, +] + +executable('input-generator', + input_generator_files, + dependencies: input_generator_deps, + install_dir: libds_bindir, + install: true, +) diff --git a/src/clients/simple-tbm.c b/src/clients/simple-tbm.c index 4fd9847..c82349f 100644 --- a/src/clients/simple-tbm.c +++ b/src/clients/simple-tbm.c @@ -38,6 +38,7 @@ #include #include #include "xdg-shell-client-protocol.h" +#include static uint64_t buffer_info_key; #define BUFFER_INFO_KEY (unsigned long)(&buffer_info_key) @@ -51,6 +52,10 @@ struct display { struct wl_seat *seat; struct wayland_tbm_client *wl_tbm; bool has_xrgb; + + struct tizen_input_device_manager *devicemgr; + int notified; + bool blocked; }; struct window { @@ -385,12 +390,43 @@ static void touch_handle_down(void *data, struct wl_touch *wl_touch, { fprintf(stderr, "touch_handle_down id:%d, x:%d, y:%d\n", id, wl_fixed_to_int(x), wl_fixed_to_int(y)); + + struct display *d = data; + + tizen_input_device_manager_block_events(d->devicemgr, 0, TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD, 50000); + + while (d->notified == -1) + wl_display_roundtrip(d->display); + + if (d->notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + printf("Success to block keyboard events\n"); + } else { + printf("Failed to block keyboard events: %d\n", d->notified); + } + d->notified = -1; + d->blocked = true; } static void touch_handle_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id) { fprintf(stderr, "touch_handle_up id:%d\n", id); + + struct display *d = data; + + if (!d->blocked) return; + tizen_input_device_manager_unblock_events(d->devicemgr, 0); + + while (d->notified == -1) + wl_display_roundtrip(d->display); + + if (d->notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + printf("Success to unblock keyboard events\n"); + } else { + printf("Failed to unblock keyboard events: %d\n", d->notified); + } + d->notified = -1; + d->blocked = false; } static void touch_handle_motion(void *data, struct wl_touch *wl_touch, @@ -446,9 +482,9 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - fprintf(stderr, "keyboard_handle_key: PRESSED\n"); + fprintf(stderr, "keyboard_handle_key: key:%d, PRESSED\n", key); } else { - fprintf(stderr, "keyboard_handle_key: RELEASED\n"); + fprintf(stderr, "keyboard_handle_key: key:%d, RELEASED\n", key); } } @@ -464,6 +500,7 @@ static struct wl_keyboard_listener keyboard_listener = { static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { + struct display *d = data; if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) { struct wl_keyboard *keyboard = wl_seat_get_keyboard(wl_seat); wl_keyboard_add_listener(keyboard, &keyboard_listener, NULL); @@ -476,7 +513,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, } if ((caps & WL_SEAT_CAPABILITY_TOUCH)) { struct wl_touch *touch = wl_seat_get_touch(wl_seat); - wl_touch_add_listener(touch, &touch_listener, NULL); + wl_touch_add_listener(touch, &touch_listener, d); fprintf(stderr, "seat_handle_capabilities: touch\n"); } } @@ -493,6 +530,31 @@ const struct wl_seat_listener seat_listener = { }; static void +input_device_manager_handle_error(void *data, + struct tizen_input_device_manager *tizen_input_device_manager, + uint32_t errorcode) +{ + struct display *d = data; + fprintf(stderr, "errorcode: %d\n", errorcode); + d->notified = errorcode; +} + +static void +input_device_manager_handle_block_expired(void *data, + struct tizen_input_device_manager *tizen_input_device_manager) +{ + fprintf(stderr, "block expired\n"); +} + +static const struct tizen_input_device_manager_listener _input_device_manager_listener = +{ + .device_add = NULL, + .device_remove = NULL, + .error = input_device_manager_handle_error, + .block_expired = input_device_manager_handle_block_expired, +}; + +static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { @@ -515,7 +577,13 @@ registry_handle_global(void *data, struct wl_registry *registry, id, &wl_seat_interface, 7); wl_seat_add_listener(d->seat, &seat_listener, d); fprintf(stderr, "wl_seat bound!\n"); - } + } else if (strcmp(interface, "tizen_input_device_manager") == 0) { + d->devicemgr = wl_registry_bind(registry, + id, &tizen_input_device_manager_interface, version); + tizen_input_device_manager_add_listener(d->devicemgr, + &_input_device_manager_listener, d); + fprintf(stderr, "tizen input device manager bound!\n"); + } } static void @@ -605,12 +673,20 @@ create_display(void) exit(1); } + display->notified = -1; + return display; } static void destroy_display(struct display *display) { + if (display->seat) + wl_seat_destroy(display->seat); + + if (display->devicemgr) + tizen_input_device_manager_destroy(display->devicemgr); + if (display->shm) wl_shm_destroy(display->shm); diff --git a/src/examples/meson.build b/src/examples/meson.build index aad893e..eb9ae29 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -76,6 +76,7 @@ if get_option('tizen') tinyds_tdm_libinput_files, dependencies: [ common_deps, + dep_libds_tizen_input_devicemgr, dependency('pixman-1', required: true), dependency('threads', required: true), ], diff --git a/src/examples/tinyds-tdm-libinput.c b/src/examples/tinyds-tdm-libinput.c index f4e9319..5634707 100644 --- a/src/examples/tinyds-tdm-libinput.c +++ b/src/examples/tinyds-tdm-libinput.c @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include #define USE_TDM_BUFFER_QUEUE @@ -36,6 +39,7 @@ #include "pixman-helper.h" #define TINYDS_UNUSED __attribute__((unused)) +struct tinyds_keyboard; struct tinyds_output { @@ -73,6 +77,7 @@ struct tinyds_server struct ds_seat *seat; uint32_t seat_caps; double output_x, output_y; + struct ds_tizen_input_devicemgr *devicemgr; struct tinyds_output *output; struct wl_event_source *stdin_source; @@ -82,6 +87,8 @@ struct tinyds_server struct wl_listener new_output; struct wl_listener new_input; struct wl_listener new_xdg_surface; + + struct tinyds_keyboard *keyboard; }; struct tinyds_view @@ -206,9 +213,18 @@ view_handle_xdg_surface_map(struct wl_listener *listener, void *data TINYDS_UNUSED) { struct tinyds_view *view; - + struct ds_keyboard *keyboard; view = wl_container_of(listener, view, xdg_surface_map); view->mapped = true; + + if (!view->server->keyboard) return; + keyboard = ds_input_device_get_keyboard(view->server->keyboard->dev); + if (keyboard != NULL) { + ds_seat_keyboard_notify_enter(view->server->seat, + ds_xdg_surface_get_surface(view->xdg_surface), + keyboard->keycodes, keyboard->num_keycodes, + &keyboard->modifiers); + } } static void @@ -373,6 +389,59 @@ backend_handle_new_input(struct wl_listener *listener, void *data) ds_seat_set_capabilities(server->seat, server->seat_caps); } +static void +devicemgr_add_keymap_data(struct wl_list *list, const char *name, int keycode) +{ + struct ds_tizen_input_devicemgr_keymap_data *data; + + data = calloc(1, sizeof *data); + if (!data) { + ds_err("Failed to alloc memory\n"); + return; + } + + data->name = strdup(name); + data->keycode = keycode; + + wl_list_insert(list, &data->link); +} + +static void +devicemgr_remove_keymap_data(struct wl_list *list, int keycode) +{ + struct ds_tizen_input_devicemgr_keymap_data *data, *tmp; + + wl_list_for_each_safe(data, tmp, list, link) { + if (data->keycode == keycode) { + wl_list_remove(&data->link); + free(data); + } + } +} + +static void +devicemgr_set_keymap(struct ds_tizen_input_devicemgr *devicemgr) +{ + struct wl_list keymap_list; + bool res; + + wl_list_init(&keymap_list); + + devicemgr_add_keymap_data(&keymap_list, "XF86VolumeRaise", 455); + devicemgr_add_keymap_data(&keymap_list, "XF86VolumeLower", 456); + devicemgr_add_keymap_data(&keymap_list, "XF86LightOn", 457); + devicemgr_add_keymap_data(&keymap_list, "XF86LightOff", 458); + + res = ds_tizen_input_devicemgr_set_keymap_list(devicemgr, &keymap_list); + if (!res) + ds_inf("Failed to set keymap"); + + devicemgr_remove_keymap_data(&keymap_list, 455); + devicemgr_remove_keymap_data(&keymap_list, 456); + devicemgr_remove_keymap_data(&keymap_list, 457); + devicemgr_remove_keymap_data(&keymap_list, 458); +} + static bool init_server(struct tinyds_server *server, struct wl_display *display) { @@ -388,8 +457,10 @@ init_server(struct tinyds_server *server, struct wl_display *display) return false; server->input_backend = ds_libinput_backend_create(display); - if (!server->input_backend) + if (!server->input_backend) { + ds_backend_destroy(server->backend); return false; + } server->new_output.notify = backend_handle_new_output; ds_backend_add_new_output_listener(server->backend, @@ -419,6 +490,13 @@ init_server(struct tinyds_server *server, struct wl_display *display) goto err; server->seat_caps = 0; + server->devicemgr = ds_tizen_input_devicemgr_create( + server->input_backend, server->seat); + if (!server->devicemgr) { + goto err; + } + + devicemgr_set_keymap(server->devicemgr); return true; err: @@ -683,14 +761,35 @@ keyboard_handle_device_destroy(struct wl_listener *listener, void *data) wl_list_remove(&kbd->destroy.link); wl_list_remove(&kbd->key.link); + kbd->server->keyboard = NULL; + free(kbd); } +static bool +server_handle_keybinding(struct tinyds_server *server, xkb_keysym_t sym) +{ + switch (sym) { + case XKB_KEY_BackSpace: + wl_display_terminate(server->display); + break; + default: + return false; + } + + return true; +} + static void keyboard_handle_key(struct wl_listener *listener, void *data) { struct tinyds_keyboard *kbd; struct ds_event_keyboard_key *event = data; + struct ds_keyboard *ds_keyboard; + struct xkb_state *xkb_state; + const xkb_keysym_t *syms; + int nsyms; + bool handled = false; kbd = wl_container_of(listener, kbd, key); @@ -698,14 +797,32 @@ keyboard_handle_key(struct wl_listener *listener, void *data) "update_state(%d)", kbd->dev, event->keycode, event->state, event->time_msec, event->update_state); - //TODO: - //ds_seat_keyboard_notify_key() + + ds_keyboard = ds_input_device_get_keyboard(kbd->dev); + + if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + xkb_state = ds_keyboard_get_xkb_state(ds_keyboard); + if (xkb_state) { + nsyms = xkb_state_key_get_syms(xkb_state, event->keycode + 8, + &syms); + for (int i = 0; i < nsyms; i++) { + handled = server_handle_keybinding(kbd->server, syms[i]); + } + } + } + + if (!handled) { + ds_seat_keyboard_notify_key(kbd->server->seat, event->time_msec, + event->keycode, event->state); + } } static void server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev) { struct tinyds_keyboard *kbd; + struct xkb_context *context; + struct xkb_keymap *keymap; kbd = calloc(1, sizeof *kbd); assert(kbd); @@ -713,12 +830,28 @@ server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev) kbd->dev = dev; kbd->server = server; + context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + keymap = xkb_keymap_new_from_names(context, NULL, + XKB_KEYMAP_COMPILE_NO_FLAGS); + + if (!keymap) { + ds_err("Failed to compile keymap"); + xkb_context_unref(context); + } + + ds_keyboard_set_keymap(ds_input_device_get_keyboard(dev), keymap); + + xkb_keymap_unref(keymap); + xkb_context_unref(context); + kbd->destroy.notify = keyboard_handle_device_destroy; ds_input_device_add_destroy_listener(dev, &kbd->destroy); kbd->key.notify = keyboard_handle_key; ds_keyboard_add_key_listener(ds_input_device_get_keyboard(dev), &kbd->key); + server->keyboard = kbd; + ds_inf("Keyboard(%p) added", kbd); } diff --git a/src/libds-tizen/backend/tdm/backend.c b/src/libds-tizen/backend/tdm/backend.c index e756ac1..21fb025 100644 --- a/src/libds-tizen/backend/tdm/backend.c +++ b/src/libds-tizen/backend/tdm/backend.c @@ -25,7 +25,7 @@ ds_tdm_backend_create(struct wl_display *display) if (!tdm) return NULL; - ds_backend_init(&tdm->base, &tdm_backend_iface); + ds_backend_init(&tdm->base, display, &tdm_backend_iface); tdm->wl_display = display; tdm->clock = CLOCK_MONOTONIC; // FIXME diff --git a/src/libds-tizen/input-devicemgr/input-devicemgr.c b/src/libds-tizen/input-devicemgr/input-devicemgr.c new file mode 100644 index 0000000..84700d7 --- /dev/null +++ b/src/libds-tizen/input-devicemgr/input-devicemgr.c @@ -0,0 +1,1063 @@ +#include +#include // gettimeofday() +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "input-devicemgr.h" +#include "src/libds/seat.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" + +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_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, 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_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->grab = calloc(1, sizeof(struct ds_seat_keyboard_grab)); + if (!tz_devicemgr->grab) + { + goto err_grab; + } + + tz_devicemgr->grab->iface = &devicemgr_keyboard_grab_iface; + tz_devicemgr->grab->seat = tz_devicemgr->seat; + tz_devicemgr->grab->data = tz_devicemgr; + + wl_signal_init(&tz_devicemgr->events.destroy); + wl_list_init(&tz_devicemgr->clients); + wl_list_init(&tz_devicemgr->pressed_keys); + 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.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; +} + +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); + + 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.kbd); + free(tz_devicemgr->grab); + 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, backend_destroy); + + wl_list_remove(&tz_devicemgr->seat_destroy.link); + wl_list_init(&tz_devicemgr->seat_destroy.link); + tz_devicemgr->seat = 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"); + tz_devicemgr->devices.kbd->input_device = dev; + } + else if (dev_type == DS_INPUT_DEVICE_POINTER) { + //TODO: assign input_device 'dev' to devices.ptr + } + else if (dev_type == DS_INPUT_DEVICE_TOUCH) { + //TODO: assign input_device 'dev' to devices.ptr + } +} + +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 = NULL, + .generate_touch = NULL, + .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; + } + + 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; + } + + ret = tz_devicemgr_init_generator(tz_devicemgr, resource, + "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; + } + + 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; + } + + ret = tz_devicemgr_init_generator(tz_devicemgr, resource, + 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) +{ + 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; + } + + 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; + } + + 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 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; + + tz_devicemgr = wl_resource_get_user_data(resource); + + 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_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 int +tz_devicemgr_init_generator(struct ds_tizen_input_devicemgr *tz_devicemgr, + struct wl_resource *resource, 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 *kbd; + + ds_inf("Init generator. name:%s", name); + + kbd = tz_devicemgr->devices.kbd; + if (strlen(kbd->name) > 0) { + ds_inf("devices.kbd already has name. name:%s", kbd->name); + return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE; + } + + if (kbd->input_device) { + ds_inf("devices.kbd is already set. name:%s", + ds_input_device_get_name(kbd->input_device)); + return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE; + } + + //input_device create + kbd->input_device = calloc(1, sizeof(struct ds_input_device)); + if(!kbd->input_device) { + ds_err("Failed to create input device !\n"); + return ret; + } + + ds_input_device_init(kbd->input_device, DS_INPUT_DEVICE_KEYBOARD, + &input_device_iface, name, -1, -1); + kbd->input_device->keyboard = create_ds_keyboard(); + + wl_signal_emit(&tz_devicemgr->backend->events.new_input, + kbd->input_device); + + kbd->created = true; + strncpy(kbd->name, name, UINPUT_MAX_NAME_SIZE); + + wl_list_for_each(client_data, &tz_devicemgr->clients, link) { + if (client_data->resource == resource) { + if (client_data->init == false) { + client_data->init = true; + tz_devicemgr->ref++; + } + break; + } + } + + ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE; + + return ret; +} + +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->pressed_keys, &key->link); + } + else { + wl_list_for_each_safe(key, tmp, &tz_devicemgr->pressed_keys, 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->pressed_keys), 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 pressed_keys. length: %d", + wl_list_length(&tz_devicemgr->pressed_keys)); + + wl_list_for_each_safe(keydata, tmp, &tz_devicemgr->pressed_keys, 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 void +tz_devicemgr_keyboard_close(struct ds_tizen_input_devicemgr *tz_devicemgr) +{ + if (!tz_devicemgr->devices.kbd->input_device) return; + ds_input_device_destroy(tz_devicemgr->devices.kbd->input_device); + tz_devicemgr->devices.kbd->input_device = NULL; + tz_devicemgr->devices.kbd->created = false; +} + +static int +tz_devicemgr_deinit_generator(struct ds_tizen_input_devicemgr *tz_devicemgr, + struct wl_resource *resource) +{ + int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE; + struct ds_tizen_input_devicemgr_client *client_data; + + 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; + tz_devicemgr->ref--; + if (tz_devicemgr->ref < 0) tz_devicemgr->ref = 0; + break; + } else { + return ret; + } + } + } + + if (tz_devicemgr->ref <= 0) { + tz_devicemgr_pressed_keys_cleanup(tz_devicemgr); + + if (!tz_devicemgr->devices.kbd) + return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE; + + if (tz_devicemgr->devices.kbd->created) + tz_devicemgr_keyboard_close(tz_devicemgr); + memset(tz_devicemgr->devices.kbd->name, 0, UINPUT_MAX_NAME_SIZE); + } + + return ret; +} + +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 = grab->data; + struct ds_tizen_input_devicemgr_key_info *keydata, *tmp; + bool key_blocked = false; + + ds_inf("devicemgr. keyboard_grab_iface_key"); + + 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); +} \ No newline at end of file diff --git a/src/libds-tizen/input-devicemgr/input-devicemgr.h b/src/libds-tizen/input-devicemgr/input-devicemgr.h new file mode 100644 index 0000000..8418b16 --- /dev/null +++ b/src/libds-tizen/input-devicemgr/input-devicemgr.h @@ -0,0 +1,59 @@ +#ifndef DS_TIZEN_DEVICEMGR_H +#define DS_TIZEN_DEVICEMGR_H + +#include +#include +#include +#include +#include "libds/interfaces/input_device.h" +#include + +struct ds_tizen_input_devicemgr_device { + char name[UINPUT_MAX_NAME_SIZE + 1]; + struct ds_input_device *input_device; + bool created; +}; + +struct ds_tizen_input_devicemgr { + struct wl_global *global; + struct wl_display *display; + struct ds_backend *backend; + struct ds_seat *seat; + + struct { + struct wl_signal destroy; + } events; + + struct wl_listener new_input; + struct wl_listener backend_destroy; + struct wl_listener seat_destroy; + struct { + struct ds_tizen_input_devicemgr_device *kbd; + struct ds_tizen_input_devicemgr_device *ptr; + struct ds_tizen_input_devicemgr_device *touch; + } devices; + + struct wl_list clients; + int ref; + + struct wl_list pressed_keys; + struct wl_list keymap_list; + + struct wl_list blocked_keys; + struct wl_resource *block_resource; + struct wl_event_source *timer; + struct ds_seat_keyboard_grab *grab; +}; + +struct ds_tizen_input_devicemgr_client { + struct wl_resource *resource; + bool init; + struct wl_list link; // ds_tizen_input_devicemgr::clients +}; + +struct ds_tizen_input_devicemgr_key_info { + int keycode; + struct wl_list link; // ds_tizen_input_devicemgr::pressed_keys; +}; + +#endif diff --git a/src/libds-tizen/input-devicemgr/meson.build b/src/libds-tizen/input-devicemgr/meson.build new file mode 100644 index 0000000..30924a4 --- /dev/null +++ b/src/libds-tizen/input-devicemgr/meson.build @@ -0,0 +1,30 @@ +libds_tizen_input_devicemgr_files = [ + 'input-devicemgr.c', +] + +libds_tizen_input_devicemgr_deps = [ + dep_libds, + dep_libds_tizen, + dependency('tizen-extension-server', required: true), +] + +lib_libds_tizen_input_devicemgr = shared_library('ds-tizen-input-devicemgr', libds_tizen_input_devicemgr_files, + dependencies: libds_tizen_input_devicemgr_deps, + include_directories: [ common_inc, include_directories('.'), include_directories('..') ], + version: meson.project_version(), + install: true +) + +dep_libds_tizen_input_devicemgr = declare_dependency( + link_with: lib_libds_tizen_input_devicemgr, + dependencies: libds_tizen_input_devicemgr_deps, + include_directories: [ common_inc, include_directories('.') ], +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(lib_libds_tizen_input_devicemgr, + version: meson.project_version(), + filebase: 'libds-tizen-input-devicemgr', + name: 'libds-tizen-input-devicemgr', + description: 'tizen input devicemgr extension of libds-tizen for tizen platform', +) diff --git a/src/libds-tizen/meson.build b/src/libds-tizen/meson.build index 6779a72..8c7673b 100644 --- a/src/libds-tizen/meson.build +++ b/src/libds-tizen/meson.build @@ -38,4 +38,5 @@ pkgconfig.generate(lib_libds_tizen, ) subdir('keyrouter') +subdir('input-devicemgr') diff --git a/src/libds/backend.c b/src/libds/backend.c index 641374a..dee97ca 100644 --- a/src/libds/backend.c +++ b/src/libds/backend.c @@ -50,9 +50,11 @@ ds_backend_add_new_input_listener(struct ds_backend *backend, void ds_backend_init(struct ds_backend *backend, + struct wl_display *display, const struct ds_backend_interface *iface) { backend->iface = iface; + backend->display = display; wl_signal_init(&backend->events.destroy); wl_signal_init(&backend->events.new_output); wl_signal_init(&backend->events.new_input); diff --git a/src/libds/backend/libinput/backend.c b/src/libds/backend/libinput/backend.c index b6dc4f1..b7e1bc4 100644 --- a/src/libds/backend/libinput/backend.c +++ b/src/libds/backend/libinput/backend.c @@ -25,7 +25,7 @@ ds_libinput_backend_create(struct wl_display *display) return NULL; } - ds_backend_init(&libinput_backend->base, &libinput_backend_interface); + ds_backend_init(&libinput_backend->base, display, &libinput_backend_interface); libinput_backend->display = display; wl_list_init(&libinput_backend->devices); @@ -52,9 +52,7 @@ void destroy_libinput_input_device(struct ds_libinput_input_device *dev) { ds_input_device_destroy(&dev->base); - libinput_device_unref(dev->handle); wl_list_remove(&dev->link); - free(dev); } static void diff --git a/src/libds/backend/libinput/input.c b/src/libds/backend/libinput/input.c index 2457a06..b6e943f 100644 --- a/src/libds/backend/libinput/input.c +++ b/src/libds/backend/libinput/input.c @@ -25,6 +25,8 @@ input_device_iface_destroy(struct ds_input_device *ds_dev) dev = get_libinput_input_device_from_input_device(ds_dev); + libinput_device_unref(dev->handle); + free(dev); } diff --git a/src/libds/backend/wayland/backend.c b/src/libds/backend/wayland/backend.c index 5719e09..fd663f4 100644 --- a/src/libds/backend/wayland/backend.c +++ b/src/libds/backend/wayland/backend.c @@ -33,7 +33,7 @@ ds_wl_backend_create(struct wl_display *display, const char *server_name) return NULL; } - ds_backend_init(&wl_backend->base, &wl_backend_interface); + ds_backend_init(&wl_backend->base, display, &wl_backend_interface); wl_backend->display = display; wl_list_init(&wl_backend->buffers); diff --git a/src/libds/input_device.c b/src/libds/input_device.c index ad18e71..534bced 100644 --- a/src/libds/input_device.c +++ b/src/libds/input_device.c @@ -15,6 +15,12 @@ ds_input_device_get_type(struct ds_input_device *dev) return dev->type; } +WL_EXPORT const char * +ds_input_device_get_name(struct ds_input_device *dev) +{ + return dev->name; +} + WL_EXPORT struct ds_pointer * ds_input_device_get_pointer(struct ds_input_device *dev) { @@ -81,6 +87,9 @@ ds_input_device_destroy(struct ds_input_device *dev) case DS_INPUT_DEVICE_KEYBOARD: ds_keyboard_destroy(dev->keyboard); break; + case DS_INPUT_DEVICE_TOUCH: + ds_touch_destroy(dev->touch); + break; default: ds_err("Warning: leaking memory %p %p %d", dev->_device, dev, dev->type); diff --git a/src/libds/seat/seat_keyboard.c b/src/libds/seat/seat_keyboard.c index 381e2d6..8931a5c 100644 --- a/src/libds/seat/seat_keyboard.c +++ b/src/libds/seat/seat_keyboard.c @@ -362,7 +362,7 @@ seat_client_send_keyboard_leave_raw(struct ds_seat_client *seat_client, struct wl_resource *resource; uint32_t serial; - serial = wl_display_next_serial(seat_client->seat->display); + serial = wl_display_next_serial(wl_client_get_display(seat_client->wl_client)); wl_resource_for_each(resource, &seat_client->keyboards) { wl_keyboard_send_leave(resource, serial, ds_surface_get_wl_resource(surface)); -- 2.7.4