From 60ea1f4373e6ceb6eb99ef2dd7699a7468a098e0 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Mon, 4 Jul 2022 19:23:19 +0900 Subject: [PATCH 01/16] change file names and folder names use the underbar instead of a hyphen when you name files and folders. Change-Id: I72c903fef3f5e2dc4fbc4df09524b7215c211685 --- examples/tinyds-tdm-dpms.c | 2 +- examples/tinyds-tdm-hwc.c | 2 +- examples/tinyds-tdm-libinput.c | 4 +- examples/tinyds-tdm.c | 2 +- include/libds-tizen/input-devicemgr.h | 44 - include/libds-tizen/tbm-server.h | 33 - packaging/libds-tizen.spec | 4 +- src/backend/tdm/tdm_output_hwc.c | 2 +- src/input-devicemgr/input-devicemgr.c | 1551 --------------------------------- src/input-devicemgr/input-devicemgr.h | 78 -- src/input-devicemgr/meson.build | 32 - src/meson.build | 4 +- src/tbm-server/meson.build | 32 - src/tbm-server/pixel_format.c | 61 -- src/tbm-server/pixel_format.h | 10 - src/tbm-server/tbm-server.c | 268 ------ src/tbm-server/tbm-server.h | 34 - tests/meson.build | 8 +- tests/test-backend.c | 80 -- tests/test-compositor.c | 63 -- tests/test-subsurface.c | 211 ----- tests/test-surface.c | 162 ---- 22 files changed, 14 insertions(+), 2673 deletions(-) delete mode 100644 include/libds-tizen/input-devicemgr.h delete mode 100644 include/libds-tizen/tbm-server.h delete mode 100644 src/input-devicemgr/input-devicemgr.c delete mode 100644 src/input-devicemgr/input-devicemgr.h delete mode 100644 src/input-devicemgr/meson.build delete mode 100644 src/tbm-server/meson.build delete mode 100644 src/tbm-server/pixel_format.c delete mode 100644 src/tbm-server/pixel_format.h delete mode 100644 src/tbm-server/tbm-server.c delete mode 100644 src/tbm-server/tbm-server.h delete mode 100644 tests/test-backend.c delete mode 100644 tests/test-compositor.c delete mode 100644 tests/test-subsurface.c delete mode 100644 tests/test-surface.c diff --git a/examples/tinyds-tdm-dpms.c b/examples/tinyds-tdm-dpms.c index ab34297..dc32e8f 100644 --- a/examples/tinyds-tdm-dpms.c +++ b/examples/tinyds-tdm-dpms.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #define USE_TDM_BUFFER_QUEUE diff --git a/examples/tinyds-tdm-hwc.c b/examples/tinyds-tdm-hwc.c index 762fe07..46925f1 100644 --- a/examples/tinyds-tdm-hwc.c +++ b/examples/tinyds-tdm-hwc.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #define USE_TDM_BUFFER_QUEUE diff --git a/examples/tinyds-tdm-libinput.c b/examples/tinyds-tdm-libinput.c index 809f8cf..b1974f1 100644 --- a/examples/tinyds-tdm-libinput.c +++ b/examples/tinyds-tdm-libinput.c @@ -16,14 +16,14 @@ #include #include #include -#include +#include #include #include #include #include #include -#include +#include #include #include diff --git a/examples/tinyds-tdm.c b/examples/tinyds-tdm.c index 57b502c..4bc08f1 100644 --- a/examples/tinyds-tdm.c +++ b/examples/tinyds-tdm.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #define USE_TDM_BUFFER_QUEUE diff --git a/include/libds-tizen/input-devicemgr.h b/include/libds-tizen/input-devicemgr.h deleted file mode 100644 index fc1060e..0000000 --- a/include/libds-tizen/input-devicemgr.h +++ /dev/null @@ -1,44 +0,0 @@ -#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); - -bool -ds_tizen_input_devicemgr_set_output_width_height( - struct ds_tizen_input_devicemgr *devicemgr, - uint32_t width, uint32_t height); -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/libds-tizen/tbm-server.h b/include/libds-tizen/tbm-server.h deleted file mode 100644 index 6e3b148..0000000 --- a/include/libds-tizen/tbm-server.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef LIBDS_TIZEN_TBM_SERVER_H -#define LIBDS_TIZEN_TBM_SERVER_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct ds_tbm_server; - -struct ds_tbm_client_buffer; - -struct ds_tbm_server * -ds_tbm_server_create(struct wl_display *display); - -void -ds_tbm_server_add_destroy_listener(struct ds_tbm_server *tbm, - struct wl_listener *listener); - -struct ds_tbm_client_buffer * -ds_tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer); - -tbm_surface_h -ds_tbm_client_buffer_get_tbm_surface(struct ds_tbm_client_buffer *buffer); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index f2702ee..fe34941 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -181,7 +181,7 @@ ninja -C builddir install %manifest %{name}.manifest %defattr(-,root,root,-) %license LICENSE -%{_includedir}/libds-tizen/tbm-server.h +%{_includedir}/libds-tizen/tbm_server.h %{_libdir}/pkgconfig/libds-tizen-tbm-server.pc %{_libdir}/libds-tizen-tbm-server.so @@ -209,7 +209,7 @@ ninja -C builddir install %manifest %{name}.manifest %defattr(-,root,root,-) %license LICENSE -%{_includedir}/libds-tizen/input-devicemgr.h +%{_includedir}/libds-tizen/input_devicemgr.h %{_libdir}/pkgconfig/libds-tizen-input-devicemgr.pc %{_libdir}/libds-tizen-input-devicemgr.so %{_bindir}/tinyds-tdm-libinput diff --git a/src/backend/tdm/tdm_output_hwc.c b/src/backend/tdm/tdm_output_hwc.c index e66b5fa..48aef1d 100644 --- a/src/backend/tdm/tdm_output_hwc.c +++ b/src/backend/tdm/tdm_output_hwc.c @@ -4,7 +4,7 @@ #include #include -#include +#include #include "tdm_internal.h" diff --git a/src/input-devicemgr/input-devicemgr.c b/src/input-devicemgr/input-devicemgr.c deleted file mode 100644 index b3fc567..0000000 --- a/src/input-devicemgr/input-devicemgr.c +++ /dev/null @@ -1,1551 +0,0 @@ -#include -#include // gettimeofday() -#include -#include -#include -#include -#include -#include -#include - -#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); -} - diff --git a/src/input-devicemgr/input-devicemgr.h b/src/input-devicemgr/input-devicemgr.h deleted file mode 100644 index a4428ee..0000000 --- a/src/input-devicemgr/input-devicemgr.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef DS_TIZEN_DEVICEMGR_H -#define DS_TIZEN_DEVICEMGR_H - -#include -#include -#include -#include -#include -#include - -struct ds_tizen_input_devicemgr_device { - char *name; - struct ds_input_device *input_device; - int ref; - - bool created; - - struct { - struct wl_list pressed; - } key; - - struct { - unsigned int pressed; - } touch; - - struct { - unsigned int pressed; - } mouse; -}; - -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; - - 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; - int touch_max_count; - - struct { - uint32_t width; - uint32_t height; - } output; -}; - -struct ds_tizen_input_devicemgr_client { - struct wl_resource *resource; - bool init; - uint32_t clas; - 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/input-devicemgr/meson.build b/src/input-devicemgr/meson.build deleted file mode 100644 index 4616f6f..0000000 --- a/src/input-devicemgr/meson.build +++ /dev/null @@ -1,32 +0,0 @@ -libds_tizen_input_devicemgr_files = [ - tizen_security_files, - 'input-devicemgr.c', -] - -libds_tizen_input_devicemgr_deps = [ - deps_libds_tizen, - deps_tizen_security, - dependency('tizen-extension-server', required: true), - dependency('xkbcommon', 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 -) - -deps_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/meson.build b/src/meson.build index b4b92f5..46d807d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -28,8 +28,8 @@ deps_tizen_security = [ ] subdir('allocator') -subdir('tbm-server') +subdir('tbm_server') subdir('backend') subdir('keyrouter') -subdir('input-devicemgr') +subdir('input_devicemgr') subdir('dpms') diff --git a/src/tbm-server/meson.build b/src/tbm-server/meson.build deleted file mode 100644 index ced06a4..0000000 --- a/src/tbm-server/meson.build +++ /dev/null @@ -1,32 +0,0 @@ -libds_tizen_tbm_server_files = [ - 'pixel_format.c', - 'tbm-server.c', -] - -libds_tizen_tbm_server_deps = [ - deps_libds_tizen, - dependency('libdrm', required: true), - dependency('libtbm', required: true), - dependency('wayland-tbm-server', required: true), -] - -lib_libds_tizen_tbm_server = shared_library('ds-tizen-tbm-server', libds_tizen_tbm_server_files, - dependencies: libds_tizen_tbm_server_deps, - include_directories: [ common_inc, include_directories('.'), include_directories('..') ], - version: meson.project_version(), - install: true -) - -deps_libds_tizen_tbm_server = declare_dependency( - link_with: lib_libds_tizen_tbm_server, - dependencies: libds_tizen_tbm_server_deps, - include_directories: [ common_inc, include_directories('.') ], -) - -pkgconfig = import('pkgconfig') -pkgconfig.generate(lib_libds_tizen_tbm_server, - version: meson.project_version(), - filebase: 'libds-tizen-tbm-server', - name: 'libds-tizen-tbm-server', - description: 'wayland-tbm extension of libds-tizen for tizen platform', -) diff --git a/src/tbm-server/pixel_format.c b/src/tbm-server/pixel_format.c deleted file mode 100644 index 030f211..0000000 --- a/src/tbm-server/pixel_format.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include - -#include -#include "pixel_format.h" - -#ifdef ARRAY_LENGTH -#undef ARRAY_LENGTH -#endif - -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - -struct ds_tbm_format -{ - uint32_t drm_format; - uint32_t tbm_format; -}; - -static const struct ds_tbm_format formats[] = -{ - { - .drm_format = DRM_FORMAT_ARGB8888, - .tbm_format = TBM_FORMAT_ARGB8888, - }, - { - .drm_format = DRM_FORMAT_XRGB8888, - .tbm_format = TBM_FORMAT_XRGB8888, - }, - /* TODO more format */ -}; - -uint32_t -convert_drm_format_to_tbm(uint32_t fmt) -{ - size_t i; - - for (i = 0; i < ARRAY_LENGTH(formats); i++) { - if (formats[i].drm_format == fmt) - return formats[i].tbm_format; - } - - ds_err("DRM format 0x%"PRIX32" has no TBM equivalent", fmt); - - return 0; -} - -uint32_t -convert_tbm_format_to_drm(uint32_t fmt) -{ - size_t i; - - for (i = 0; i < ARRAY_LENGTH(formats); i++) { - if (formats[i].tbm_format == fmt) - return formats[i].drm_format; - } - - ds_err("TBM format 0x%"PRIX32" has no DRM equivalent", fmt); - - return 0; -} diff --git a/src/tbm-server/pixel_format.h b/src/tbm-server/pixel_format.h deleted file mode 100644 index a63d096..0000000 --- a/src/tbm-server/pixel_format.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef DS_TIZEN_PIXEL_FORMAT_H -#define DS_TIZEN_PIXEL_FORMAT_H - -#include - -uint32_t convert_drm_format_to_tbm(uint32_t fmt); - -uint32_t convert_tbm_format_to_drm(uint32_t fmt); - -#endif diff --git a/src/tbm-server/tbm-server.c b/src/tbm-server/tbm-server.c deleted file mode 100644 index 9dde248..0000000 --- a/src/tbm-server/tbm-server.c +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include -#include - -#include - -#include -#include "pixel_format.h" -#include "tbm-server.h" - -static const struct ds_buffer_resource_interface tbm_buffer_resource_iface; -static const struct ds_buffer_interface tbm_client_buffer_iface; - -static void tbm_server_handle_display_destroy(struct wl_listener *listener, - void *data); - -WL_EXPORT struct ds_tbm_server * -ds_tbm_server_create(struct wl_display *display) -{ - struct ds_tbm_server *tbm; - tbm_bufmgr bufmgr; - - tbm = calloc(1, sizeof *tbm); - if (!tbm) - return NULL; - - wl_signal_init(&tbm->events.destroy); - - tbm->wl_tbm = wayland_tbm_server_init(display, NULL, -1, 0); - if (!tbm->wl_tbm) { - goto err_wl_tbm; - } - - bufmgr = wayland_tbm_server_get_bufmgr(tbm->wl_tbm); - if (!bufmgr) { - goto err_bind; - } - - if (!tbm_bufmgr_bind_native_display(bufmgr, (void *)display)) { - goto err_bind; - } - - tbm->display_destroy.notify = tbm_server_handle_display_destroy; - wl_display_add_destroy_listener(display, &tbm->display_destroy); - - ds_buffer_register_resource_interface(&tbm_buffer_resource_iface); - - return tbm; - -err_bind: - wayland_tbm_server_deinit(tbm->wl_tbm); -err_wl_tbm: - free(tbm); - - return NULL; -} - -WL_EXPORT void -ds_tbm_server_add_destroy_listener(struct ds_tbm_server *tbm, - struct wl_listener *listener) -{ - wl_signal_add(&tbm->events.destroy, listener); -} - -WL_EXPORT struct ds_tbm_client_buffer * -ds_tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) -{ - if (ds_buffer->iface != &tbm_client_buffer_iface) - return NULL; - return (struct ds_tbm_client_buffer *)ds_buffer; -} - -WL_EXPORT tbm_surface_h -ds_tbm_client_buffer_get_tbm_surface(struct ds_tbm_client_buffer *buffer) -{ - if (buffer->base.iface != &tbm_client_buffer_iface) - return NULL; - return buffer->surface; -} - -static void -tbm_server_handle_display_destroy(struct wl_listener *listener, void *data) -{ - struct ds_tbm_server *tbm; - - tbm = wl_container_of(listener, tbm, display_destroy); - - wl_signal_emit(&tbm->events.destroy, tbm); - - wayland_tbm_server_deinit(tbm->wl_tbm); - free(tbm); -} - -static void -tbm_client_buffer_handle_release(struct wl_listener *listener, void *data) -{ - struct ds_tbm_client_buffer *buffer; - - buffer = wl_container_of(listener, buffer, buffer_release); - if (buffer->resource) - wl_buffer_send_release(buffer->resource); -} - -static void -tbm_client_buffer_handle_resource_destroy(struct wl_listener *listener, - void *data) -{ - struct ds_tbm_client_buffer *buffer; - - buffer = wl_container_of(listener, buffer, resource_destroy); - - buffer->resource = NULL; - buffer->surface = NULL; - wl_list_remove(&buffer->resource_destroy.link); - wl_list_init(&buffer->resource_destroy.link); - - ds_buffer_drop(&buffer->base); -} - -static struct ds_tbm_client_buffer * -tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) -{ - assert(ds_buffer->iface == &tbm_client_buffer_iface); - return (struct ds_tbm_client_buffer *)ds_buffer; -} - -static void -tbm_client_buffer_iface_destroy(struct ds_buffer *ds_buffer) -{ - struct ds_tbm_client_buffer *buffer; - - buffer = tbm_client_buffer_from_buffer(ds_buffer); - - ds_inf("Destroy TBM client buffer(%p)", buffer); - - wl_list_remove(&buffer->resource_destroy.link); - wl_list_remove(&buffer->buffer_release.link); - free(buffer); -} - -static bool -tbm_client_buffer_iface_begin_data_ptr_access(struct ds_buffer *ds_buffer, - enum ds_buffer_data_ptr_access_flag flags, void **data, - uint32_t *format, size_t *stride) -{ - struct ds_tbm_client_buffer *buffer; - tbm_surface_info_s info; - tbm_bo_access_option op = TBM_OPTION_NONE; - int err; - - buffer = tbm_client_buffer_from_buffer(ds_buffer); - - if (flags & DS_BUFFER_DATA_PTR_ACCESS_READ) - op |= TBM_OPTION_READ; - - if (flags & DS_BUFFER_DATA_PTR_ACCESS_WRITE) - op |= TBM_OPTION_WRITE; - - err = tbm_surface_map(buffer->surface, op, &info); - if (err != TBM_SURFACE_ERROR_NONE) { - ds_err("Failed tbm_surface_map()"); - return false; - } - - *format = convert_tbm_format_to_drm(buffer->format); - *stride = info.planes[0].stride; - *data = info.planes[0].ptr; - - return true; -} - -static void -tbm_client_buffer_iface_end_ptr_access(struct ds_buffer *ds_buffer) -{ - struct ds_tbm_client_buffer *buffer; - - buffer = tbm_client_buffer_from_buffer(ds_buffer); - - tbm_surface_unmap(buffer->surface); -} - -static const struct ds_buffer_interface tbm_client_buffer_iface = { - .destroy = tbm_client_buffer_iface_destroy, - .begin_data_ptr_access = tbm_client_buffer_iface_begin_data_ptr_access, - .end_data_ptr_access = tbm_client_buffer_iface_end_ptr_access, -}; - -static struct ds_tbm_client_buffer * -tbm_client_buffer_create(struct wl_resource *resource) -{ - struct ds_tbm_client_buffer *buffer; - tbm_surface_h surface; - int32_t width, height; - - surface = wayland_tbm_server_get_surface(NULL, resource); - if (!surface) { - ds_err("Could not get tbm_surface from wl_resource@%d", - wl_resource_get_id(resource)); - return NULL; - } - - width = tbm_surface_get_width(surface); - height = tbm_surface_get_height(surface); - - buffer = calloc(1, sizeof *buffer); - if (!buffer) - return NULL; - - ds_buffer_init(&buffer->base, &tbm_client_buffer_iface, width, height); - - buffer->resource = resource; - buffer->surface = surface; - buffer->format = tbm_surface_get_format(surface); - - buffer->buffer_release.notify = tbm_client_buffer_handle_release; - ds_buffer_add_release_listener(&buffer->base, &buffer->buffer_release); - - buffer->resource_destroy.notify = - tbm_client_buffer_handle_resource_destroy; - wl_resource_add_destroy_listener(resource, &buffer->resource_destroy); - - ds_inf("TBM client buffer(%p) created", buffer); - - return buffer; -} - -static struct ds_tbm_client_buffer * -tbm_client_buffer_get_or_create(struct wl_resource *resource) -{ - struct ds_tbm_client_buffer *buffer; - struct wl_listener *resource_destroy_listener; - - resource_destroy_listener = wl_resource_get_destroy_listener(resource, - tbm_client_buffer_handle_resource_destroy);; - if (resource_destroy_listener) { - buffer = wl_container_of(resource_destroy_listener, - buffer, resource_destroy); - return buffer; - } - - return tbm_client_buffer_create(resource); -} - -static bool -tbm_buffer_resource_iface_is_instance(struct wl_resource *resource) -{ - return !!wayland_tbm_server_get_surface(NULL, resource); -} - -static struct ds_buffer * -tbm_buffer_resource_iface_from_resource(struct wl_resource *resource) -{ - struct ds_tbm_client_buffer *buffer; - - buffer = tbm_client_buffer_get_or_create(resource); - if (!buffer) { - ds_err("Could not get or create ds_tbm_client_buffer"); - return NULL; - } - - return &buffer->base; -} - -static const struct ds_buffer_resource_interface tbm_buffer_resource_iface = { - .name = "tbm", - .is_instance = tbm_buffer_resource_iface_is_instance, - .from_resource = tbm_buffer_resource_iface_from_resource, -}; diff --git a/src/tbm-server/tbm-server.h b/src/tbm-server/tbm-server.h deleted file mode 100644 index 58e391b..0000000 --- a/src/tbm-server/tbm-server.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef DS_TIZEN_TBM_SERVER_H -#define DS_TIZEN_TBM_SERVER_H - -#include -#include -#include -#include - -struct ds_tbm_server -{ - struct wayland_tbm_server *wl_tbm; - - struct wl_listener display_destroy; - - struct { - struct wl_signal destroy; - } events; -}; - -struct ds_tbm_client_buffer -{ - struct ds_buffer base; - - tbm_surface_h surface; - struct wl_resource *resource; - - struct wl_listener buffer_release; - struct wl_listener resource_destroy; - - uint32_t format; - size_t stride; -}; - -#endif diff --git a/tests/meson.build b/tests/meson.build index dae7875..324c760 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,12 +1,12 @@ tests = [ - { 'name': 'test-compositor' }, - { 'name': 'test-backend' }, + { 'name': 'test_compositor' }, + { 'name': 'test_backend' }, { - 'name': 'test-surface', + 'name': 'test_surface', 'deps': [ dependency('wayland-client') ], }, { - 'name': 'test-subsurface', + 'name': 'test_subsurface', 'deps': [ dependency('wayland-client') ], }, ] diff --git a/tests/test-backend.c b/tests/test-backend.c deleted file mode 100644 index 69417b6..0000000 --- a/tests/test-backend.c +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include - -#include -#include - -static struct ds_backend * -create_possible_wl_backend(struct wl_display *display) -{ - struct ds_backend *backend; - char wl_name[512]; - - for (int i = 0; i < 5; i++) { - snprintf(wl_name, sizeof wl_name, "wayland-%d", i); - backend = ds_wl_backend_create(display, wl_name); - if (backend) - break; - } - - return backend; -} - -static void -test_wl_backend_create(void) -{ - struct wl_display *display; - struct ds_backend *backend; - - display = wl_display_create(); - - backend = create_possible_wl_backend(display); - assert(backend); - - ds_backend_destroy(backend); -} - -struct test -{ - struct wl_listener backend_destroy; - bool cb_called; -}; - -static void -cb_backend_destroy(struct wl_listener *listener, void *data) -{ - struct test *test; - - test = wl_container_of(listener, test, backend_destroy); - test->cb_called = true; -} - -static void -test_wl_backend_destroy_signal(void) -{ - struct wl_display *display; - struct ds_backend *backend; - struct test test; - - display = wl_display_create(); - - backend = create_possible_wl_backend(display); - assert(backend); - - test.cb_called = false; - test.backend_destroy.notify = cb_backend_destroy; - ds_backend_add_destroy_listener(backend, &test.backend_destroy); - - wl_display_destroy(display); - assert(test.cb_called); -} - -int -main(void) -{ - test_wl_backend_create(); - test_wl_backend_destroy_signal(); - - return 0; -} diff --git a/tests/test-compositor.c b/tests/test-compositor.c deleted file mode 100644 index b5883a5..0000000 --- a/tests/test-compositor.c +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include - -#include -#include -#include - -static void -test_compositor_create(void) -{ - struct wl_display *display; - struct ds_compositor *compositor; - - display = wl_display_create(); - compositor = ds_compositor_create(display); - assert(compositor); - - wl_display_destroy(display); -} - -struct test -{ - struct wl_listener compositor_destroy; - bool destroyed; -}; - -static void -cb_compositor_destroy(struct wl_listener *listener, void *data) -{ - struct test *test; - - test = wl_container_of(listener, test, compositor_destroy); - test->destroyed = true; -} - -static void -test_compositor_destroy_signal(void) -{ - struct wl_display *display; - struct ds_compositor *compositor; - struct test test; - - display = wl_display_create(); - compositor = ds_compositor_create(display); - assert(compositor); - - test.destroyed = false; - test.compositor_destroy.notify = cb_compositor_destroy; - ds_compositor_add_destroy_listener(compositor, - &test.compositor_destroy); - - wl_display_destroy(display); - assert(test.destroyed == true); -} - -int -main(void) -{ - test_compositor_create(); - test_compositor_destroy_signal(); - - return 0; -} diff --git a/tests/test-subsurface.c b/tests/test-subsurface.c deleted file mode 100644 index 98e830d..0000000 --- a/tests/test-subsurface.c +++ /dev/null @@ -1,211 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -struct server_base -{ - struct wl_display *display; - struct ds_compositor *compositor; - const char *socket; -}; - -const char * -test_server_init(struct server_base *server) -{ - server->display = wl_display_create(); - assert(server->display); - server->compositor = ds_compositor_create(server->display); - assert(server->compositor); - server->socket = wl_display_add_socket_auto(server->display); - assert(server->socket); - - return server->socket; -} - -void -test_server_finish(struct server_base *server) -{ - wl_display_destroy(server->display); -} - -struct client -{ - struct wl_display *display; - struct wl_registry *registry; - struct wl_compositor *compositor; - struct wl_subcompositor *subcompositor; - struct wl_surface *surface; - struct wl_subsurface *subsurface; -}; - -static void -handle_global(void *data, struct wl_registry *registry, uint32_t id, - const char *interface, uint32_t version) -{ - struct client *client = data; - - if (strcmp(interface, "wl_compositor") == 0) { - client->compositor = - wl_registry_bind(registry, id, &wl_compositor_interface, version); - } - else if (strcmp(interface, "wl_subcompositor") == 0) { - client->subcompositor = - wl_registry_bind(registry, id, &wl_subcompositor_interface, version); - } -} - -static const struct wl_registry_listener registry_listener = { - .global = handle_global, -}; - -void -test_client_init(struct client *client, const char *name) -{ - client->display = wl_display_connect(name); - assert(client->display); - client->registry = wl_display_get_registry(client->display); - assert(client->registry); - - wl_registry_add_listener(client->registry, ®istry_listener, client); - - wl_display_roundtrip(client->display); - - assert(client->compositor); - assert(client->subcompositor); -} - -void -test_client_finish(struct client *client) -{ - wl_subcompositor_destroy(client->subcompositor); - wl_compositor_destroy(client->compositor); - wl_registry_destroy(client->registry); - wl_display_disconnect(client->display); -} - -struct test_server -{ - struct server_base base; - bool cb_called; - - struct wl_listener new_surface; - struct wl_listener new_subsurface1; - struct wl_listener new_subsurface2; -}; - -static void -cb_new_subsurface1(struct wl_listener *listener, void *data) -{ - struct ds_subsurface *subsurface = data; - struct test_server *server; - - assert(subsurface); - - server = wl_container_of(listener, server, new_subsurface1); - server->cb_called = true; - wl_display_terminate(server->base.display); -} - -static void -cb_new_subsurface2(struct wl_listener *listener, void *data) -{ - struct ds_subsurface *subsurface = data; - struct test_server *server; - - assert(subsurface); - - server = wl_container_of(listener, server, new_subsurface2); - server->cb_called = true; - wl_display_terminate(server->base.display); -} - -static void -cb_new_surface(struct wl_listener *listener, void *data) -{ - struct ds_surface *surface = data; - struct test_server *server; - - server = wl_container_of(listener, server, new_surface); - if (!server->new_subsurface1.notify) { - server->new_subsurface1.notify = cb_new_subsurface1; - ds_surface_add_new_subsurface_listener(surface, - &server->new_subsurface1); - } - else { - server->new_subsurface2.notify = cb_new_subsurface2; - ds_surface_add_new_subsurface_listener(surface, - &server->new_subsurface2); - } -} - -static void -run_client(const char *name) -{ - struct client client; - - test_client_init(&client, name); - - struct wl_surface *surface = - wl_compositor_create_surface(client.compositor); - - struct wl_surface *child_surface = - wl_compositor_create_surface(client.compositor); - - struct wl_subsurface *subsurface = - wl_subcompositor_get_subsurface(client.subcompositor, - child_surface, surface); - - wl_display_roundtrip(client.display); - - wl_subsurface_destroy(subsurface); - wl_surface_destroy(child_surface); - wl_surface_destroy(surface); - - test_client_finish(&client); -} - -static void -test_subsurface_create(void) -{ - struct test_server server = { - .new_subsurface1 = { .notify = NULL }, - .cb_called = false - }; - pid_t pid; - - const char *socket_name = test_server_init(&server.base); - - pid = fork(); - assert(pid != -1); - - if (pid == 0) { - run_client(socket_name); - exit(0); - } - - server.new_surface.notify = cb_new_surface; - ds_compositor_add_new_surface_listener(server.base.compositor, - &server.new_surface); - - wl_display_run(server.base.display); - - assert(server.cb_called); - - test_server_finish(&server.base); -} - -int -main(void) -{ - test_subsurface_create(); - return 0; -} diff --git a/tests/test-surface.c b/tests/test-surface.c deleted file mode 100644 index eab2b77..0000000 --- a/tests/test-surface.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -struct server_base -{ - struct wl_display *display; - struct ds_compositor *compositor; - const char *socket; -}; - -void -test_server_init(struct server_base *server) -{ - server->display = wl_display_create(); - assert(server->display); - server->compositor = ds_compositor_create(server->display); - assert(server->compositor); - server->socket = wl_display_add_socket_auto(server->display); - assert(server->socket); -} - -void -test_server_finish(struct server_base *server) -{ - wl_display_destroy(server->display); -} - -struct client -{ - struct wl_display *display; - struct wl_registry *registry; - struct wl_compositor *compositor; - struct wl_surface *surface; -}; - -static void -handle_global(void *data, struct wl_registry *registry, uint32_t id, - const char *interface, uint32_t version) -{ - struct client *client = data; - - if (strcmp(interface, "wl_compositor") == 0) { - client->compositor = - wl_registry_bind(registry, id, &wl_compositor_interface, version); - } -} - -static const struct wl_registry_listener registry_listener = { - .global = handle_global, -}; - -void -test_client_init(struct client *client, const char *name) -{ - client->display = wl_display_connect(name); - assert(client->display); - client->registry = wl_display_get_registry(client->display); - assert(client->registry); - - wl_registry_add_listener(client->registry, ®istry_listener, client); - - wl_display_roundtrip(client->display); - - assert(client->compositor); -} - -void -test_client_finish(struct client *client) -{ - wl_compositor_destroy(client->compositor); - wl_registry_destroy(client->registry); - wl_display_disconnect(client->display); -} - -struct test_server { - struct server_base base; - bool cb_called; - - struct wl_listener new_surface; - struct wl_listener surface_destroy; -}; - -static void -cb_surface_destroy(struct wl_listener *listener, void *data) -{ - struct test_server *server; - - server = wl_container_of(listener, server, surface_destroy); - server->cb_called = true; - wl_display_terminate(server->base.display); -} - -static void -cb_new_surface(struct wl_listener *listener, void *data) -{ - struct ds_surface *surface = data; - struct test_server *server; - - server = wl_container_of(listener, server, new_surface); - server->surface_destroy.notify = cb_surface_destroy; - ds_surface_add_destroy_listener(surface, &server->surface_destroy); -} - -static void -run_client(const char *name) -{ - struct client client; - - test_client_init(&client, name); - - struct wl_surface *surface = - wl_compositor_create_surface(client.compositor); - - wl_display_roundtrip(client.display); - - wl_surface_destroy(surface); - - test_client_finish(&client); -} - -static void -test_surface_create_and_destroy(void) -{ - struct test_server server = { .cb_called = false }; - pid_t pid; - - test_server_init(&server.base); - - pid = fork(); - assert(pid != -1); - - if (pid == 0) { - run_client(server.base.socket); - exit(0); - } - - server.new_surface.notify = cb_new_surface; - ds_compositor_add_new_surface_listener(server.base.compositor, - &server.new_surface); - - wl_display_run(server.base.display); - - assert(server.cb_called); - - test_server_finish(&server.base); -} - -int -main(void) -{ - test_surface_create_and_destroy(); - return 0; -} -- 2.7.4 From beaddc72e08eea8791b6d5aed9acec35d01852b9 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Mon, 4 Jul 2022 19:33:18 +0900 Subject: [PATCH 02/16] fix the typo Change-Id: Ie2407006a7d008b8a1c5d32413cf9a64669693e5 --- src/dpms/dpms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dpms/dpms.c b/src/dpms/dpms.c index a85834a..833005f 100644 --- a/src/dpms/dpms.c +++ b/src/dpms/dpms.c @@ -29,7 +29,7 @@ struct ds_tizen_dpms static void dpms_handle_display_destroy(struct wl_listener *listener, void *data); static void dpms_bind(struct wl_client *wl_client, void *data, - uint32_t verison, uint32_t id); + uint32_t version, uint32_t id); WL_EXPORT struct ds_tizen_dpms * ds_tizen_dpms_create(struct wl_display *display) -- 2.7.4 From 0f72718246529b64ae641457786f47d3d5c734e3 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Wed, 6 Jul 2022 14:10:33 +0900 Subject: [PATCH 03/16] add missing files Change-Id: Ifd75994c3ae705441947e2b225adfb08bacc0466 --- include/libds-tizen/input_devicemgr.h | 44 + include/libds-tizen/tbm_server.h | 33 + src/input_devicemgr/input_devicemgr.c | 1551 +++++++++++++++++++++++++++++++++ src/input_devicemgr/input_devicemgr.h | 78 ++ src/input_devicemgr/meson.build | 32 + src/tbm_server/meson.build | 32 + src/tbm_server/pixel_format.c | 61 ++ src/tbm_server/pixel_format.h | 10 + src/tbm_server/tbm_server.c | 268 ++++++ src/tbm_server/tbm_server.h | 34 + tests/test_backend.c | 80 ++ tests/test_compositor.c | 63 ++ tests/test_subsurface.c | 211 +++++ tests/test_surface.c | 162 ++++ 14 files changed, 2659 insertions(+) create mode 100644 include/libds-tizen/input_devicemgr.h create mode 100644 include/libds-tizen/tbm_server.h create mode 100644 src/input_devicemgr/input_devicemgr.c create mode 100644 src/input_devicemgr/input_devicemgr.h create mode 100644 src/input_devicemgr/meson.build create mode 100644 src/tbm_server/meson.build create mode 100644 src/tbm_server/pixel_format.c create mode 100644 src/tbm_server/pixel_format.h create mode 100644 src/tbm_server/tbm_server.c create mode 100644 src/tbm_server/tbm_server.h create mode 100644 tests/test_backend.c create mode 100644 tests/test_compositor.c create mode 100644 tests/test_subsurface.c create mode 100644 tests/test_surface.c diff --git a/include/libds-tizen/input_devicemgr.h b/include/libds-tizen/input_devicemgr.h new file mode 100644 index 0000000..fc1060e --- /dev/null +++ b/include/libds-tizen/input_devicemgr.h @@ -0,0 +1,44 @@ +#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); + +bool +ds_tizen_input_devicemgr_set_output_width_height( + struct ds_tizen_input_devicemgr *devicemgr, + uint32_t width, uint32_t height); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/libds-tizen/tbm_server.h b/include/libds-tizen/tbm_server.h new file mode 100644 index 0000000..6e3b148 --- /dev/null +++ b/include/libds-tizen/tbm_server.h @@ -0,0 +1,33 @@ +#ifndef LIBDS_TIZEN_TBM_SERVER_H +#define LIBDS_TIZEN_TBM_SERVER_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tbm_server; + +struct ds_tbm_client_buffer; + +struct ds_tbm_server * +ds_tbm_server_create(struct wl_display *display); + +void +ds_tbm_server_add_destroy_listener(struct ds_tbm_server *tbm, + struct wl_listener *listener); + +struct ds_tbm_client_buffer * +ds_tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer); + +tbm_surface_h +ds_tbm_client_buffer_get_tbm_surface(struct ds_tbm_client_buffer *buffer); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/input_devicemgr/input_devicemgr.c b/src/input_devicemgr/input_devicemgr.c new file mode 100644 index 0000000..f690fe7 --- /dev/null +++ b/src/input_devicemgr/input_devicemgr.c @@ -0,0 +1,1551 @@ +#include +#include // gettimeofday() +#include +#include +#include +#include +#include +#include +#include + +#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); +} + diff --git a/src/input_devicemgr/input_devicemgr.h b/src/input_devicemgr/input_devicemgr.h new file mode 100644 index 0000000..a4428ee --- /dev/null +++ b/src/input_devicemgr/input_devicemgr.h @@ -0,0 +1,78 @@ +#ifndef DS_TIZEN_DEVICEMGR_H +#define DS_TIZEN_DEVICEMGR_H + +#include +#include +#include +#include +#include +#include + +struct ds_tizen_input_devicemgr_device { + char *name; + struct ds_input_device *input_device; + int ref; + + bool created; + + struct { + struct wl_list pressed; + } key; + + struct { + unsigned int pressed; + } touch; + + struct { + unsigned int pressed; + } mouse; +}; + +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; + + 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; + int touch_max_count; + + struct { + uint32_t width; + uint32_t height; + } output; +}; + +struct ds_tizen_input_devicemgr_client { + struct wl_resource *resource; + bool init; + uint32_t clas; + 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/input_devicemgr/meson.build b/src/input_devicemgr/meson.build new file mode 100644 index 0000000..ea8a94f --- /dev/null +++ b/src/input_devicemgr/meson.build @@ -0,0 +1,32 @@ +libds_tizen_input_devicemgr_files = [ + tizen_security_files, + 'input_devicemgr.c', +] + +libds_tizen_input_devicemgr_deps = [ + deps_libds_tizen, + deps_tizen_security, + dependency('tizen-extension-server', required: true), + dependency('xkbcommon', 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 +) + +deps_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/tbm_server/meson.build b/src/tbm_server/meson.build new file mode 100644 index 0000000..795576a --- /dev/null +++ b/src/tbm_server/meson.build @@ -0,0 +1,32 @@ +libds_tizen_tbm_server_files = [ + 'pixel_format.c', + 'tbm_server.c', +] + +libds_tizen_tbm_server_deps = [ + deps_libds_tizen, + dependency('libdrm', required: true), + dependency('libtbm', required: true), + dependency('wayland-tbm-server', required: true), +] + +lib_libds_tizen_tbm_server = shared_library('ds-tizen-tbm-server', libds_tizen_tbm_server_files, + dependencies: libds_tizen_tbm_server_deps, + include_directories: [ common_inc, include_directories('.'), include_directories('..') ], + version: meson.project_version(), + install: true +) + +deps_libds_tizen_tbm_server = declare_dependency( + link_with: lib_libds_tizen_tbm_server, + dependencies: libds_tizen_tbm_server_deps, + include_directories: [ common_inc, include_directories('.') ], +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(lib_libds_tizen_tbm_server, + version: meson.project_version(), + filebase: 'libds-tizen-tbm-server', + name: 'libds-tizen-tbm-server', + description: 'wayland-tbm extension of libds-tizen for tizen platform', +) diff --git a/src/tbm_server/pixel_format.c b/src/tbm_server/pixel_format.c new file mode 100644 index 0000000..030f211 --- /dev/null +++ b/src/tbm_server/pixel_format.c @@ -0,0 +1,61 @@ +#include +#include +#include + +#include +#include "pixel_format.h" + +#ifdef ARRAY_LENGTH +#undef ARRAY_LENGTH +#endif + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +struct ds_tbm_format +{ + uint32_t drm_format; + uint32_t tbm_format; +}; + +static const struct ds_tbm_format formats[] = +{ + { + .drm_format = DRM_FORMAT_ARGB8888, + .tbm_format = TBM_FORMAT_ARGB8888, + }, + { + .drm_format = DRM_FORMAT_XRGB8888, + .tbm_format = TBM_FORMAT_XRGB8888, + }, + /* TODO more format */ +}; + +uint32_t +convert_drm_format_to_tbm(uint32_t fmt) +{ + size_t i; + + for (i = 0; i < ARRAY_LENGTH(formats); i++) { + if (formats[i].drm_format == fmt) + return formats[i].tbm_format; + } + + ds_err("DRM format 0x%"PRIX32" has no TBM equivalent", fmt); + + return 0; +} + +uint32_t +convert_tbm_format_to_drm(uint32_t fmt) +{ + size_t i; + + for (i = 0; i < ARRAY_LENGTH(formats); i++) { + if (formats[i].tbm_format == fmt) + return formats[i].drm_format; + } + + ds_err("TBM format 0x%"PRIX32" has no DRM equivalent", fmt); + + return 0; +} diff --git a/src/tbm_server/pixel_format.h b/src/tbm_server/pixel_format.h new file mode 100644 index 0000000..a63d096 --- /dev/null +++ b/src/tbm_server/pixel_format.h @@ -0,0 +1,10 @@ +#ifndef DS_TIZEN_PIXEL_FORMAT_H +#define DS_TIZEN_PIXEL_FORMAT_H + +#include + +uint32_t convert_drm_format_to_tbm(uint32_t fmt); + +uint32_t convert_tbm_format_to_drm(uint32_t fmt); + +#endif diff --git a/src/tbm_server/tbm_server.c b/src/tbm_server/tbm_server.c new file mode 100644 index 0000000..0fd25cd --- /dev/null +++ b/src/tbm_server/tbm_server.c @@ -0,0 +1,268 @@ +#include +#include +#include + +#include + +#include +#include "pixel_format.h" +#include "tbm_server.h" + +static const struct ds_buffer_resource_interface tbm_buffer_resource_iface; +static const struct ds_buffer_interface tbm_client_buffer_iface; + +static void tbm_server_handle_display_destroy(struct wl_listener *listener, + void *data); + +WL_EXPORT struct ds_tbm_server * +ds_tbm_server_create(struct wl_display *display) +{ + struct ds_tbm_server *tbm; + tbm_bufmgr bufmgr; + + tbm = calloc(1, sizeof *tbm); + if (!tbm) + return NULL; + + wl_signal_init(&tbm->events.destroy); + + tbm->wl_tbm = wayland_tbm_server_init(display, NULL, -1, 0); + if (!tbm->wl_tbm) { + goto err_wl_tbm; + } + + bufmgr = wayland_tbm_server_get_bufmgr(tbm->wl_tbm); + if (!bufmgr) { + goto err_bind; + } + + if (!tbm_bufmgr_bind_native_display(bufmgr, (void *)display)) { + goto err_bind; + } + + tbm->display_destroy.notify = tbm_server_handle_display_destroy; + wl_display_add_destroy_listener(display, &tbm->display_destroy); + + ds_buffer_register_resource_interface(&tbm_buffer_resource_iface); + + return tbm; + +err_bind: + wayland_tbm_server_deinit(tbm->wl_tbm); +err_wl_tbm: + free(tbm); + + return NULL; +} + +WL_EXPORT void +ds_tbm_server_add_destroy_listener(struct ds_tbm_server *tbm, + struct wl_listener *listener) +{ + wl_signal_add(&tbm->events.destroy, listener); +} + +WL_EXPORT struct ds_tbm_client_buffer * +ds_tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) +{ + if (ds_buffer->iface != &tbm_client_buffer_iface) + return NULL; + return (struct ds_tbm_client_buffer *)ds_buffer; +} + +WL_EXPORT tbm_surface_h +ds_tbm_client_buffer_get_tbm_surface(struct ds_tbm_client_buffer *buffer) +{ + if (buffer->base.iface != &tbm_client_buffer_iface) + return NULL; + return buffer->surface; +} + +static void +tbm_server_handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tbm_server *tbm; + + tbm = wl_container_of(listener, tbm, display_destroy); + + wl_signal_emit(&tbm->events.destroy, tbm); + + wayland_tbm_server_deinit(tbm->wl_tbm); + free(tbm); +} + +static void +tbm_client_buffer_handle_release(struct wl_listener *listener, void *data) +{ + struct ds_tbm_client_buffer *buffer; + + buffer = wl_container_of(listener, buffer, buffer_release); + if (buffer->resource) + wl_buffer_send_release(buffer->resource); +} + +static void +tbm_client_buffer_handle_resource_destroy(struct wl_listener *listener, + void *data) +{ + struct ds_tbm_client_buffer *buffer; + + buffer = wl_container_of(listener, buffer, resource_destroy); + + buffer->resource = NULL; + buffer->surface = NULL; + wl_list_remove(&buffer->resource_destroy.link); + wl_list_init(&buffer->resource_destroy.link); + + ds_buffer_drop(&buffer->base); +} + +static struct ds_tbm_client_buffer * +tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) +{ + assert(ds_buffer->iface == &tbm_client_buffer_iface); + return (struct ds_tbm_client_buffer *)ds_buffer; +} + +static void +tbm_client_buffer_iface_destroy(struct ds_buffer *ds_buffer) +{ + struct ds_tbm_client_buffer *buffer; + + buffer = tbm_client_buffer_from_buffer(ds_buffer); + + ds_inf("Destroy TBM client buffer(%p)", buffer); + + wl_list_remove(&buffer->resource_destroy.link); + wl_list_remove(&buffer->buffer_release.link); + free(buffer); +} + +static bool +tbm_client_buffer_iface_begin_data_ptr_access(struct ds_buffer *ds_buffer, + enum ds_buffer_data_ptr_access_flag flags, void **data, + uint32_t *format, size_t *stride) +{ + struct ds_tbm_client_buffer *buffer; + tbm_surface_info_s info; + tbm_bo_access_option op = TBM_OPTION_NONE; + int err; + + buffer = tbm_client_buffer_from_buffer(ds_buffer); + + if (flags & DS_BUFFER_DATA_PTR_ACCESS_READ) + op |= TBM_OPTION_READ; + + if (flags & DS_BUFFER_DATA_PTR_ACCESS_WRITE) + op |= TBM_OPTION_WRITE; + + err = tbm_surface_map(buffer->surface, op, &info); + if (err != TBM_SURFACE_ERROR_NONE) { + ds_err("Failed tbm_surface_map()"); + return false; + } + + *format = convert_tbm_format_to_drm(buffer->format); + *stride = info.planes[0].stride; + *data = info.planes[0].ptr; + + return true; +} + +static void +tbm_client_buffer_iface_end_ptr_access(struct ds_buffer *ds_buffer) +{ + struct ds_tbm_client_buffer *buffer; + + buffer = tbm_client_buffer_from_buffer(ds_buffer); + + tbm_surface_unmap(buffer->surface); +} + +static const struct ds_buffer_interface tbm_client_buffer_iface = { + .destroy = tbm_client_buffer_iface_destroy, + .begin_data_ptr_access = tbm_client_buffer_iface_begin_data_ptr_access, + .end_data_ptr_access = tbm_client_buffer_iface_end_ptr_access, +}; + +static struct ds_tbm_client_buffer * +tbm_client_buffer_create(struct wl_resource *resource) +{ + struct ds_tbm_client_buffer *buffer; + tbm_surface_h surface; + int32_t width, height; + + surface = wayland_tbm_server_get_surface(NULL, resource); + if (!surface) { + ds_err("Could not get tbm_surface from wl_resource@%d", + wl_resource_get_id(resource)); + return NULL; + } + + width = tbm_surface_get_width(surface); + height = tbm_surface_get_height(surface); + + buffer = calloc(1, sizeof *buffer); + if (!buffer) + return NULL; + + ds_buffer_init(&buffer->base, &tbm_client_buffer_iface, width, height); + + buffer->resource = resource; + buffer->surface = surface; + buffer->format = tbm_surface_get_format(surface); + + buffer->buffer_release.notify = tbm_client_buffer_handle_release; + ds_buffer_add_release_listener(&buffer->base, &buffer->buffer_release); + + buffer->resource_destroy.notify = + tbm_client_buffer_handle_resource_destroy; + wl_resource_add_destroy_listener(resource, &buffer->resource_destroy); + + ds_inf("TBM client buffer(%p) created", buffer); + + return buffer; +} + +static struct ds_tbm_client_buffer * +tbm_client_buffer_get_or_create(struct wl_resource *resource) +{ + struct ds_tbm_client_buffer *buffer; + struct wl_listener *resource_destroy_listener; + + resource_destroy_listener = wl_resource_get_destroy_listener(resource, + tbm_client_buffer_handle_resource_destroy);; + if (resource_destroy_listener) { + buffer = wl_container_of(resource_destroy_listener, + buffer, resource_destroy); + return buffer; + } + + return tbm_client_buffer_create(resource); +} + +static bool +tbm_buffer_resource_iface_is_instance(struct wl_resource *resource) +{ + return !!wayland_tbm_server_get_surface(NULL, resource); +} + +static struct ds_buffer * +tbm_buffer_resource_iface_from_resource(struct wl_resource *resource) +{ + struct ds_tbm_client_buffer *buffer; + + buffer = tbm_client_buffer_get_or_create(resource); + if (!buffer) { + ds_err("Could not get or create ds_tbm_client_buffer"); + return NULL; + } + + return &buffer->base; +} + +static const struct ds_buffer_resource_interface tbm_buffer_resource_iface = { + .name = "tbm", + .is_instance = tbm_buffer_resource_iface_is_instance, + .from_resource = tbm_buffer_resource_iface_from_resource, +}; diff --git a/src/tbm_server/tbm_server.h b/src/tbm_server/tbm_server.h new file mode 100644 index 0000000..58e391b --- /dev/null +++ b/src/tbm_server/tbm_server.h @@ -0,0 +1,34 @@ +#ifndef DS_TIZEN_TBM_SERVER_H +#define DS_TIZEN_TBM_SERVER_H + +#include +#include +#include +#include + +struct ds_tbm_server +{ + struct wayland_tbm_server *wl_tbm; + + struct wl_listener display_destroy; + + struct { + struct wl_signal destroy; + } events; +}; + +struct ds_tbm_client_buffer +{ + struct ds_buffer base; + + tbm_surface_h surface; + struct wl_resource *resource; + + struct wl_listener buffer_release; + struct wl_listener resource_destroy; + + uint32_t format; + size_t stride; +}; + +#endif diff --git a/tests/test_backend.c b/tests/test_backend.c new file mode 100644 index 0000000..69417b6 --- /dev/null +++ b/tests/test_backend.c @@ -0,0 +1,80 @@ +#include +#include +#include + +#include +#include + +static struct ds_backend * +create_possible_wl_backend(struct wl_display *display) +{ + struct ds_backend *backend; + char wl_name[512]; + + for (int i = 0; i < 5; i++) { + snprintf(wl_name, sizeof wl_name, "wayland-%d", i); + backend = ds_wl_backend_create(display, wl_name); + if (backend) + break; + } + + return backend; +} + +static void +test_wl_backend_create(void) +{ + struct wl_display *display; + struct ds_backend *backend; + + display = wl_display_create(); + + backend = create_possible_wl_backend(display); + assert(backend); + + ds_backend_destroy(backend); +} + +struct test +{ + struct wl_listener backend_destroy; + bool cb_called; +}; + +static void +cb_backend_destroy(struct wl_listener *listener, void *data) +{ + struct test *test; + + test = wl_container_of(listener, test, backend_destroy); + test->cb_called = true; +} + +static void +test_wl_backend_destroy_signal(void) +{ + struct wl_display *display; + struct ds_backend *backend; + struct test test; + + display = wl_display_create(); + + backend = create_possible_wl_backend(display); + assert(backend); + + test.cb_called = false; + test.backend_destroy.notify = cb_backend_destroy; + ds_backend_add_destroy_listener(backend, &test.backend_destroy); + + wl_display_destroy(display); + assert(test.cb_called); +} + +int +main(void) +{ + test_wl_backend_create(); + test_wl_backend_destroy_signal(); + + return 0; +} diff --git a/tests/test_compositor.c b/tests/test_compositor.c new file mode 100644 index 0000000..b5883a5 --- /dev/null +++ b/tests/test_compositor.c @@ -0,0 +1,63 @@ +#include +#include + +#include +#include +#include + +static void +test_compositor_create(void) +{ + struct wl_display *display; + struct ds_compositor *compositor; + + display = wl_display_create(); + compositor = ds_compositor_create(display); + assert(compositor); + + wl_display_destroy(display); +} + +struct test +{ + struct wl_listener compositor_destroy; + bool destroyed; +}; + +static void +cb_compositor_destroy(struct wl_listener *listener, void *data) +{ + struct test *test; + + test = wl_container_of(listener, test, compositor_destroy); + test->destroyed = true; +} + +static void +test_compositor_destroy_signal(void) +{ + struct wl_display *display; + struct ds_compositor *compositor; + struct test test; + + display = wl_display_create(); + compositor = ds_compositor_create(display); + assert(compositor); + + test.destroyed = false; + test.compositor_destroy.notify = cb_compositor_destroy; + ds_compositor_add_destroy_listener(compositor, + &test.compositor_destroy); + + wl_display_destroy(display); + assert(test.destroyed == true); +} + +int +main(void) +{ + test_compositor_create(); + test_compositor_destroy_signal(); + + return 0; +} diff --git a/tests/test_subsurface.c b/tests/test_subsurface.c new file mode 100644 index 0000000..98e830d --- /dev/null +++ b/tests/test_subsurface.c @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +struct server_base +{ + struct wl_display *display; + struct ds_compositor *compositor; + const char *socket; +}; + +const char * +test_server_init(struct server_base *server) +{ + server->display = wl_display_create(); + assert(server->display); + server->compositor = ds_compositor_create(server->display); + assert(server->compositor); + server->socket = wl_display_add_socket_auto(server->display); + assert(server->socket); + + return server->socket; +} + +void +test_server_finish(struct server_base *server) +{ + wl_display_destroy(server->display); +} + +struct client +{ + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_subcompositor *subcompositor; + struct wl_surface *surface; + struct wl_subsurface *subsurface; +}; + +static void +handle_global(void *data, struct wl_registry *registry, uint32_t id, + const char *interface, uint32_t version) +{ + struct client *client = data; + + if (strcmp(interface, "wl_compositor") == 0) { + client->compositor = + wl_registry_bind(registry, id, &wl_compositor_interface, version); + } + else if (strcmp(interface, "wl_subcompositor") == 0) { + client->subcompositor = + wl_registry_bind(registry, id, &wl_subcompositor_interface, version); + } +} + +static const struct wl_registry_listener registry_listener = { + .global = handle_global, +}; + +void +test_client_init(struct client *client, const char *name) +{ + client->display = wl_display_connect(name); + assert(client->display); + client->registry = wl_display_get_registry(client->display); + assert(client->registry); + + wl_registry_add_listener(client->registry, ®istry_listener, client); + + wl_display_roundtrip(client->display); + + assert(client->compositor); + assert(client->subcompositor); +} + +void +test_client_finish(struct client *client) +{ + wl_subcompositor_destroy(client->subcompositor); + wl_compositor_destroy(client->compositor); + wl_registry_destroy(client->registry); + wl_display_disconnect(client->display); +} + +struct test_server +{ + struct server_base base; + bool cb_called; + + struct wl_listener new_surface; + struct wl_listener new_subsurface1; + struct wl_listener new_subsurface2; +}; + +static void +cb_new_subsurface1(struct wl_listener *listener, void *data) +{ + struct ds_subsurface *subsurface = data; + struct test_server *server; + + assert(subsurface); + + server = wl_container_of(listener, server, new_subsurface1); + server->cb_called = true; + wl_display_terminate(server->base.display); +} + +static void +cb_new_subsurface2(struct wl_listener *listener, void *data) +{ + struct ds_subsurface *subsurface = data; + struct test_server *server; + + assert(subsurface); + + server = wl_container_of(listener, server, new_subsurface2); + server->cb_called = true; + wl_display_terminate(server->base.display); +} + +static void +cb_new_surface(struct wl_listener *listener, void *data) +{ + struct ds_surface *surface = data; + struct test_server *server; + + server = wl_container_of(listener, server, new_surface); + if (!server->new_subsurface1.notify) { + server->new_subsurface1.notify = cb_new_subsurface1; + ds_surface_add_new_subsurface_listener(surface, + &server->new_subsurface1); + } + else { + server->new_subsurface2.notify = cb_new_subsurface2; + ds_surface_add_new_subsurface_listener(surface, + &server->new_subsurface2); + } +} + +static void +run_client(const char *name) +{ + struct client client; + + test_client_init(&client, name); + + struct wl_surface *surface = + wl_compositor_create_surface(client.compositor); + + struct wl_surface *child_surface = + wl_compositor_create_surface(client.compositor); + + struct wl_subsurface *subsurface = + wl_subcompositor_get_subsurface(client.subcompositor, + child_surface, surface); + + wl_display_roundtrip(client.display); + + wl_subsurface_destroy(subsurface); + wl_surface_destroy(child_surface); + wl_surface_destroy(surface); + + test_client_finish(&client); +} + +static void +test_subsurface_create(void) +{ + struct test_server server = { + .new_subsurface1 = { .notify = NULL }, + .cb_called = false + }; + pid_t pid; + + const char *socket_name = test_server_init(&server.base); + + pid = fork(); + assert(pid != -1); + + if (pid == 0) { + run_client(socket_name); + exit(0); + } + + server.new_surface.notify = cb_new_surface; + ds_compositor_add_new_surface_listener(server.base.compositor, + &server.new_surface); + + wl_display_run(server.base.display); + + assert(server.cb_called); + + test_server_finish(&server.base); +} + +int +main(void) +{ + test_subsurface_create(); + return 0; +} diff --git a/tests/test_surface.c b/tests/test_surface.c new file mode 100644 index 0000000..eab2b77 --- /dev/null +++ b/tests/test_surface.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct server_base +{ + struct wl_display *display; + struct ds_compositor *compositor; + const char *socket; +}; + +void +test_server_init(struct server_base *server) +{ + server->display = wl_display_create(); + assert(server->display); + server->compositor = ds_compositor_create(server->display); + assert(server->compositor); + server->socket = wl_display_add_socket_auto(server->display); + assert(server->socket); +} + +void +test_server_finish(struct server_base *server) +{ + wl_display_destroy(server->display); +} + +struct client +{ + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_surface *surface; +}; + +static void +handle_global(void *data, struct wl_registry *registry, uint32_t id, + const char *interface, uint32_t version) +{ + struct client *client = data; + + if (strcmp(interface, "wl_compositor") == 0) { + client->compositor = + wl_registry_bind(registry, id, &wl_compositor_interface, version); + } +} + +static const struct wl_registry_listener registry_listener = { + .global = handle_global, +}; + +void +test_client_init(struct client *client, const char *name) +{ + client->display = wl_display_connect(name); + assert(client->display); + client->registry = wl_display_get_registry(client->display); + assert(client->registry); + + wl_registry_add_listener(client->registry, ®istry_listener, client); + + wl_display_roundtrip(client->display); + + assert(client->compositor); +} + +void +test_client_finish(struct client *client) +{ + wl_compositor_destroy(client->compositor); + wl_registry_destroy(client->registry); + wl_display_disconnect(client->display); +} + +struct test_server { + struct server_base base; + bool cb_called; + + struct wl_listener new_surface; + struct wl_listener surface_destroy; +}; + +static void +cb_surface_destroy(struct wl_listener *listener, void *data) +{ + struct test_server *server; + + server = wl_container_of(listener, server, surface_destroy); + server->cb_called = true; + wl_display_terminate(server->base.display); +} + +static void +cb_new_surface(struct wl_listener *listener, void *data) +{ + struct ds_surface *surface = data; + struct test_server *server; + + server = wl_container_of(listener, server, new_surface); + server->surface_destroy.notify = cb_surface_destroy; + ds_surface_add_destroy_listener(surface, &server->surface_destroy); +} + +static void +run_client(const char *name) +{ + struct client client; + + test_client_init(&client, name); + + struct wl_surface *surface = + wl_compositor_create_surface(client.compositor); + + wl_display_roundtrip(client.display); + + wl_surface_destroy(surface); + + test_client_finish(&client); +} + +static void +test_surface_create_and_destroy(void) +{ + struct test_server server = { .cb_called = false }; + pid_t pid; + + test_server_init(&server.base); + + pid = fork(); + assert(pid != -1); + + if (pid == 0) { + run_client(server.base.socket); + exit(0); + } + + server.new_surface.notify = cb_new_surface; + ds_compositor_add_new_surface_listener(server.base.compositor, + &server.new_surface); + + wl_display_run(server.base.display); + + assert(server.cb_called); + + test_server_finish(&server.base); +} + +int +main(void) +{ + test_surface_create_and_destroy(); + return 0; +} -- 2.7.4 From f29f6dcedae721cec462af6f1bd8add294a0e585 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Wed, 6 Jul 2022 10:54:44 +0900 Subject: [PATCH 04/16] keyrouter: Replace get_keyroutes() with notify_key() Instead of returning key routes list to the compositor, it will deal with keyboard key events on the behalf of the compositor according to keyrouter extension protocol. Change-Id: I6b7085402c6bb5cad0160f356c327af1467f9726 --- include/libds-tizen/keyrouter.h | 60 +++++++++------------------------ src/keyrouter/keyrouter.c | 74 +++++++++++++++++++++++++++++++++++++---- src/keyrouter/keyrouter.h | 27 ++++++++++++++- src/keyrouter/keyrouter_grab.c | 25 +++++++------- 4 files changed, 122 insertions(+), 64 deletions(-) diff --git a/include/libds-tizen/keyrouter.h b/include/libds-tizen/keyrouter.h index bd47b54..1be7944 100644 --- a/include/libds-tizen/keyrouter.h +++ b/include/libds-tizen/keyrouter.h @@ -2,6 +2,8 @@ #define LIBDS_TIZEN_KEYROUTER_H #include +#include +#include #ifdef __cplusplus extern "C" { @@ -13,39 +15,6 @@ extern "C" { struct ds_tizen_keyrouter; /** - * The information of keyroute - */ -struct ds_tizen_keyroute_info -{ - struct wl_client *wl_client; -}; - -/** - * Keyroute mode of keyroutes returned by ds_tizen_keyrouter_get_keyroutes() - * for a given keycode. - */ -enum ds_tizen_keyroute_mode { - /** - * The keycode is not under any keyroute mode. - * The compositor may send a keycode to a focused wayland cliet as usual. - */ - DS_TIZEN_KEYROUTE_MODE_NONE, - /** - * Exclusive mode means that a given keycode is required to be sent - * exclusively to wayland clients of returned keyroutes. So the compositor - * must not send this keycode to any other wayland clients except for - * returned wayland clients. - */ - DS_TIZEN_KEYROUTE_MODE_EXCLUSIVE, - /** - * The keycode is required to be shared with returned wayland clients. - * The compositor must send the keycode not only to returned wayland - * clients, but also to a focused wayland client. - */ - DS_TIZEN_KEYROUTE_MODE_SHARED, -}; - -/** * Creates a ds_tizen_keyrouter. */ struct ds_tizen_keyrouter * @@ -59,18 +28,21 @@ ds_tizen_keyrouter_add_destroy_listener(struct ds_tizen_keyrouter *keyrouter, struct wl_listener *listener); /** - * Gets keyroutes and mode for a given keycode. - * The compositor must send a keycode to returned wayland clients according to - * the mode. The parameter, topmost_client, should be given to determine whether - * the given topmost_client require a keycode exclusively when one of its - * surfaces is on very top of stack. See tizen_keyrouter protocol in - * tizen-extension.xml for more detail. + * Notify the keyrouter that a key has been pressed on the keyboard. + * This will eventually notify a given seat of key events, and if there is + * no destination to be routed, then it sends key events to the focused one + * automatically. So, if you call this, you don't need to call + * ds_seat_keyboard_notify_key() manually unless you want to do something + * differently. + * The parameter, topmost_surface, should be given for the keyrouter to + * determine whether the given topmost_surface require a keycode exclusively + * when the surface is on very top of stack. + * See tizen_keyrouter protocol in tizen-extension.xml for more detail. */ -enum ds_tizen_keyroute_mode -ds_tizen_keyrouter_get_keyroutes(struct ds_tizen_keyrouter *keyrouter, - int keycode, struct wl_client *topmost_client, - struct wl_array *keyroutes); - +void +ds_tizen_keyrouter_notify_key(struct ds_tizen_keyrouter *keyrouter, + struct ds_seat *seat, struct ds_surface *topmost_surface, + uint32_t time_msec, uint32_t key, uint32_t state); #ifdef __cplusplus } #endif diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index 2e825c6..097f4df 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -29,6 +29,9 @@ static int keyrouter_client_grab_key(struct keyrouter_client *client, int mode, int keycode); static int keyrouter_client_ungrab_key(struct keyrouter_client *client, int keycode); +static void +keyrouter_seat_broadcast_key(struct ds_seat *seat, struct wl_array *keyroutes, + bool with_focus, uint32_t time_msec, uint32_t keycode, uint32_t state); WL_EXPORT struct ds_tizen_keyrouter * ds_tizen_keyrouter_create(struct wl_display *display) @@ -76,13 +79,45 @@ ds_tizen_keyrouter_add_destroy_listener(struct ds_tizen_keyrouter *keyrouter, wl_signal_add(&keyrouter->events.destroy, listener); } -WL_EXPORT enum ds_tizen_keyroute_mode -ds_tizen_keyrouter_get_keyroutes(struct ds_tizen_keyrouter *keyrouter, - int keycode, struct wl_client *topmost_client, - struct wl_array *keyroutes) +WL_EXPORT void +ds_tizen_keyrouter_notify_key(struct ds_tizen_keyrouter *keyrouter, + struct ds_seat *seat, struct ds_surface *topmost_surface, + uint32_t time_msec, uint32_t keycode, uint32_t state) { - return keyrouter_grab_get_keyroutes(&keyrouter->keygrab, - keycode, topmost_client, keyroutes); + struct wl_client *topmost_wl_client = NULL; + struct wl_resource *surface_resource; + struct wl_array keyroutes; + enum keyroute_mode mode; + + wl_array_init(&keyroutes); + + if (topmost_surface) { + surface_resource = ds_surface_get_wl_resource(topmost_surface); + if (surface_resource) { + topmost_wl_client = wl_resource_get_client( + ds_surface_get_wl_resource(topmost_surface)); + } + } + + mode = keyrouter_grab_get_keyroutes(&keyrouter->keygrab, keycode + 8, + topmost_wl_client, &keyroutes); + + if (mode == KEYROUTE_MODE_EXCLUSIVE) { + keyrouter_seat_broadcast_key(seat, &keyroutes, true, + time_msec, keycode, state); + + goto end; + } + + if (mode == KEYROUTE_MODE_SHARED) { + keyrouter_seat_broadcast_key(seat, &keyroutes, false, + time_msec, keycode, state); + } + + ds_seat_keyboard_notify_key(seat, time_msec, keycode, state); + +end: + wl_array_release(&keyroutes); } static void @@ -424,3 +459,30 @@ keyrouter_client_ungrab_key(struct keyrouter_client *client, int keycode) return TIZEN_KEYROUTER_ERROR_NONE; } + +static void +keyrouter_seat_broadcast_key(struct ds_seat *seat, struct wl_array *keyroutes, + bool with_focus, uint32_t time_msec, uint32_t keycode, uint32_t state) +{ + struct ds_seat_client *seat_client, *focused_client; + struct wl_client **wl_client_ptr; + + focused_client = ds_seat_keyboard_get_focused_client(seat); + + wl_array_for_each(wl_client_ptr, keyroutes) { + seat_client = ds_seat_client_for_wl_client(seat, *wl_client_ptr); + if (!seat_client) { + ds_inf("Could not find ds_seat_client for given wl_client(%p)", + *wl_client_ptr); + continue; + } + + if (seat_client == focused_client) { + if (with_focus) + ds_seat_keyboard_notify_key(seat, time_msec, keycode, state); + } + else { + ds_seat_client_send_key(seat_client, time_msec, keycode, state); + } + } +} diff --git a/src/keyrouter/keyrouter.h b/src/keyrouter/keyrouter.h index bea9ab1..bd3faa9 100644 --- a/src/keyrouter/keyrouter.h +++ b/src/keyrouter/keyrouter.h @@ -9,6 +9,31 @@ #define KEYROUTER_MAX_KEYS 512 +/** + * Keyroute mode of keyroutes returned by keyrouter_grab_get_keyroutes() + * for a given keycode. + */ +enum keyroute_mode { + /** + * The keycode is not under any keyroute mode. + * The compositor may send a keycode to a focused wayland cliet as usual. + */ + KEYROUTE_MODE_NONE, + /** + * Exclusive mode means that a given keycode is required to be sent + * exclusively to wayland clients of returned keyroutes. So the compositor + * must not send this keycode to any other wayland clients except for + * returned wayland clients. + */ + KEYROUTE_MODE_EXCLUSIVE, + /** + * The keycode is required to be shared with returned wayland clients. + * The compositor must send the keycode not only to returned wayland + * clients, but also to a focused wayland client. + */ + KEYROUTE_MODE_SHARED, +}; + struct keyroute_info { struct wl_client *wl_client; @@ -92,7 +117,7 @@ int keyrouter_grab_grab_key(struct keyrouter_grab *keygrab, int mode, void keyrouter_grab_ungrab_key(struct keyrouter_grab *keygrab, int mode, int keycode, struct wl_client *wl_client); -enum ds_tizen_keyroute_mode +enum keyroute_mode keyrouter_grab_get_keyroutes(struct keyrouter_grab *keygrab, int keycode, struct wl_client *topmost_client, struct wl_array *keyroutes); diff --git a/src/keyrouter/keyrouter_grab.c b/src/keyrouter/keyrouter_grab.c index fed301b..4f27ea1 100644 --- a/src/keyrouter/keyrouter_grab.c +++ b/src/keyrouter/keyrouter_grab.c @@ -31,7 +31,7 @@ keyrouter_grab_topmost_find(struct keyrouter_grab *keygrab, int keycode, struct wl_client *topmost_client); static bool keyrouter_grab_get_shared_keyroutes(struct keyrouter_grab *keygrab, int keycode, struct wl_array *keyroutes); -static bool keyroutes_add_info(struct wl_array *keyroutes, +static bool keyroutes_add_wl_client(struct wl_array *keyroutes, struct wl_client *wl_client); void @@ -58,7 +58,7 @@ keyrouter_grab_finish(struct keyrouter_grab *keygrab) } } -enum ds_tizen_keyroute_mode +enum keyroute_mode keyrouter_grab_get_keyroutes(struct keyrouter_grab *keygrab, int keycode, struct wl_client *topmost_client, struct wl_array *keyroutes) { @@ -82,16 +82,16 @@ keyrouter_grab_get_keyroutes(struct keyrouter_grab *keygrab, int keycode, goto exclusive_out; if (keyrouter_grab_get_shared_keyroutes(keygrab, keycode, keyroutes)) - return DS_TIZEN_KEYROUTE_MODE_SHARED; + return KEYROUTE_MODE_SHARED; none_out: - return DS_TIZEN_KEYROUTE_MODE_NONE; + return KEYROUTE_MODE_NONE; exclusive_out: - if (!keyroutes_add_info(keyroutes, info->wl_client)) + if (!keyroutes_add_wl_client(keyroutes, info->wl_client)) ds_err("Could not add wl_client to keyroutes"); - return DS_TIZEN_KEYROUTE_MODE_EXCLUSIVE; + return KEYROUTE_MODE_EXCLUSIVE; } int @@ -299,7 +299,7 @@ keyrouter_grab_get_shared_keyroutes(struct keyrouter_grab *keygrab, int count = 0; wl_list_for_each(info, list, link) { - if (!keyroutes_add_info(keyroutes, info->wl_client)) { + if (!keyroutes_add_wl_client(keyroutes, info->wl_client)) { ds_err("Could not prepend wl_client to delivery_list"); continue; } @@ -314,16 +314,15 @@ keyrouter_grab_get_shared_keyroutes(struct keyrouter_grab *keygrab, } static bool -keyroutes_add_info(struct wl_array *keyroutes, - struct wl_client *wl_client) +keyroutes_add_wl_client(struct wl_array *keyroutes, struct wl_client *wl_client) { - struct ds_tizen_keyroute_info *info; + struct wl_client **p; - info = wl_array_add(keyroutes, sizeof *info); - if (!info) + p = wl_array_add(keyroutes, sizeof(struct wl_client *)); + if (!p) return false; - info->wl_client = wl_client; + *p = wl_client; return true; } -- 2.7.4 From c1d56f7d059dc0744fc95f35bec1e60ed46cd332 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Thu, 7 Jul 2022 19:57:35 +0900 Subject: [PATCH 05/16] remove the test files. This test files are useless. Change-Id: I0528e80430c947e1dfcf92f8b71860188d9d0ec5 --- tests/meson.build | 25 ------ tests/test_backend.c | 80 ------------------ tests/test_compositor.c | 63 --------------- tests/test_subsurface.c | 211 ------------------------------------------------ tests/test_surface.c | 162 ------------------------------------- 5 files changed, 541 deletions(-) delete mode 100644 tests/meson.build delete mode 100644 tests/test_backend.c delete mode 100644 tests/test_compositor.c delete mode 100644 tests/test_subsurface.c delete mode 100644 tests/test_surface.c diff --git a/tests/meson.build b/tests/meson.build deleted file mode 100644 index 324c760..0000000 --- a/tests/meson.build +++ /dev/null @@ -1,25 +0,0 @@ -tests = [ - { 'name': 'test_compositor' }, - { 'name': 'test_backend' }, - { - 'name': 'test_surface', - 'deps': [ dependency('wayland-client') ], - }, - { - 'name': 'test_subsurface', - 'deps': [ dependency('wayland-client') ], - }, -] - -foreach t : tests - t_deps = [ deps_libds_tizen ] - t_deps += t.get('deps', []) - - test('libds-tizen-' + t.get('name'), - executable('libds-tizen-' + t.get('name'), t.get('name') + '.c', - dependencies: t_deps , - include_directories: common_inc, - install: false - ) - ) -endforeach diff --git a/tests/test_backend.c b/tests/test_backend.c deleted file mode 100644 index 69417b6..0000000 --- a/tests/test_backend.c +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include - -#include -#include - -static struct ds_backend * -create_possible_wl_backend(struct wl_display *display) -{ - struct ds_backend *backend; - char wl_name[512]; - - for (int i = 0; i < 5; i++) { - snprintf(wl_name, sizeof wl_name, "wayland-%d", i); - backend = ds_wl_backend_create(display, wl_name); - if (backend) - break; - } - - return backend; -} - -static void -test_wl_backend_create(void) -{ - struct wl_display *display; - struct ds_backend *backend; - - display = wl_display_create(); - - backend = create_possible_wl_backend(display); - assert(backend); - - ds_backend_destroy(backend); -} - -struct test -{ - struct wl_listener backend_destroy; - bool cb_called; -}; - -static void -cb_backend_destroy(struct wl_listener *listener, void *data) -{ - struct test *test; - - test = wl_container_of(listener, test, backend_destroy); - test->cb_called = true; -} - -static void -test_wl_backend_destroy_signal(void) -{ - struct wl_display *display; - struct ds_backend *backend; - struct test test; - - display = wl_display_create(); - - backend = create_possible_wl_backend(display); - assert(backend); - - test.cb_called = false; - test.backend_destroy.notify = cb_backend_destroy; - ds_backend_add_destroy_listener(backend, &test.backend_destroy); - - wl_display_destroy(display); - assert(test.cb_called); -} - -int -main(void) -{ - test_wl_backend_create(); - test_wl_backend_destroy_signal(); - - return 0; -} diff --git a/tests/test_compositor.c b/tests/test_compositor.c deleted file mode 100644 index b5883a5..0000000 --- a/tests/test_compositor.c +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include - -#include -#include -#include - -static void -test_compositor_create(void) -{ - struct wl_display *display; - struct ds_compositor *compositor; - - display = wl_display_create(); - compositor = ds_compositor_create(display); - assert(compositor); - - wl_display_destroy(display); -} - -struct test -{ - struct wl_listener compositor_destroy; - bool destroyed; -}; - -static void -cb_compositor_destroy(struct wl_listener *listener, void *data) -{ - struct test *test; - - test = wl_container_of(listener, test, compositor_destroy); - test->destroyed = true; -} - -static void -test_compositor_destroy_signal(void) -{ - struct wl_display *display; - struct ds_compositor *compositor; - struct test test; - - display = wl_display_create(); - compositor = ds_compositor_create(display); - assert(compositor); - - test.destroyed = false; - test.compositor_destroy.notify = cb_compositor_destroy; - ds_compositor_add_destroy_listener(compositor, - &test.compositor_destroy); - - wl_display_destroy(display); - assert(test.destroyed == true); -} - -int -main(void) -{ - test_compositor_create(); - test_compositor_destroy_signal(); - - return 0; -} diff --git a/tests/test_subsurface.c b/tests/test_subsurface.c deleted file mode 100644 index 98e830d..0000000 --- a/tests/test_subsurface.c +++ /dev/null @@ -1,211 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -struct server_base -{ - struct wl_display *display; - struct ds_compositor *compositor; - const char *socket; -}; - -const char * -test_server_init(struct server_base *server) -{ - server->display = wl_display_create(); - assert(server->display); - server->compositor = ds_compositor_create(server->display); - assert(server->compositor); - server->socket = wl_display_add_socket_auto(server->display); - assert(server->socket); - - return server->socket; -} - -void -test_server_finish(struct server_base *server) -{ - wl_display_destroy(server->display); -} - -struct client -{ - struct wl_display *display; - struct wl_registry *registry; - struct wl_compositor *compositor; - struct wl_subcompositor *subcompositor; - struct wl_surface *surface; - struct wl_subsurface *subsurface; -}; - -static void -handle_global(void *data, struct wl_registry *registry, uint32_t id, - const char *interface, uint32_t version) -{ - struct client *client = data; - - if (strcmp(interface, "wl_compositor") == 0) { - client->compositor = - wl_registry_bind(registry, id, &wl_compositor_interface, version); - } - else if (strcmp(interface, "wl_subcompositor") == 0) { - client->subcompositor = - wl_registry_bind(registry, id, &wl_subcompositor_interface, version); - } -} - -static const struct wl_registry_listener registry_listener = { - .global = handle_global, -}; - -void -test_client_init(struct client *client, const char *name) -{ - client->display = wl_display_connect(name); - assert(client->display); - client->registry = wl_display_get_registry(client->display); - assert(client->registry); - - wl_registry_add_listener(client->registry, ®istry_listener, client); - - wl_display_roundtrip(client->display); - - assert(client->compositor); - assert(client->subcompositor); -} - -void -test_client_finish(struct client *client) -{ - wl_subcompositor_destroy(client->subcompositor); - wl_compositor_destroy(client->compositor); - wl_registry_destroy(client->registry); - wl_display_disconnect(client->display); -} - -struct test_server -{ - struct server_base base; - bool cb_called; - - struct wl_listener new_surface; - struct wl_listener new_subsurface1; - struct wl_listener new_subsurface2; -}; - -static void -cb_new_subsurface1(struct wl_listener *listener, void *data) -{ - struct ds_subsurface *subsurface = data; - struct test_server *server; - - assert(subsurface); - - server = wl_container_of(listener, server, new_subsurface1); - server->cb_called = true; - wl_display_terminate(server->base.display); -} - -static void -cb_new_subsurface2(struct wl_listener *listener, void *data) -{ - struct ds_subsurface *subsurface = data; - struct test_server *server; - - assert(subsurface); - - server = wl_container_of(listener, server, new_subsurface2); - server->cb_called = true; - wl_display_terminate(server->base.display); -} - -static void -cb_new_surface(struct wl_listener *listener, void *data) -{ - struct ds_surface *surface = data; - struct test_server *server; - - server = wl_container_of(listener, server, new_surface); - if (!server->new_subsurface1.notify) { - server->new_subsurface1.notify = cb_new_subsurface1; - ds_surface_add_new_subsurface_listener(surface, - &server->new_subsurface1); - } - else { - server->new_subsurface2.notify = cb_new_subsurface2; - ds_surface_add_new_subsurface_listener(surface, - &server->new_subsurface2); - } -} - -static void -run_client(const char *name) -{ - struct client client; - - test_client_init(&client, name); - - struct wl_surface *surface = - wl_compositor_create_surface(client.compositor); - - struct wl_surface *child_surface = - wl_compositor_create_surface(client.compositor); - - struct wl_subsurface *subsurface = - wl_subcompositor_get_subsurface(client.subcompositor, - child_surface, surface); - - wl_display_roundtrip(client.display); - - wl_subsurface_destroy(subsurface); - wl_surface_destroy(child_surface); - wl_surface_destroy(surface); - - test_client_finish(&client); -} - -static void -test_subsurface_create(void) -{ - struct test_server server = { - .new_subsurface1 = { .notify = NULL }, - .cb_called = false - }; - pid_t pid; - - const char *socket_name = test_server_init(&server.base); - - pid = fork(); - assert(pid != -1); - - if (pid == 0) { - run_client(socket_name); - exit(0); - } - - server.new_surface.notify = cb_new_surface; - ds_compositor_add_new_surface_listener(server.base.compositor, - &server.new_surface); - - wl_display_run(server.base.display); - - assert(server.cb_called); - - test_server_finish(&server.base); -} - -int -main(void) -{ - test_subsurface_create(); - return 0; -} diff --git a/tests/test_surface.c b/tests/test_surface.c deleted file mode 100644 index eab2b77..0000000 --- a/tests/test_surface.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -struct server_base -{ - struct wl_display *display; - struct ds_compositor *compositor; - const char *socket; -}; - -void -test_server_init(struct server_base *server) -{ - server->display = wl_display_create(); - assert(server->display); - server->compositor = ds_compositor_create(server->display); - assert(server->compositor); - server->socket = wl_display_add_socket_auto(server->display); - assert(server->socket); -} - -void -test_server_finish(struct server_base *server) -{ - wl_display_destroy(server->display); -} - -struct client -{ - struct wl_display *display; - struct wl_registry *registry; - struct wl_compositor *compositor; - struct wl_surface *surface; -}; - -static void -handle_global(void *data, struct wl_registry *registry, uint32_t id, - const char *interface, uint32_t version) -{ - struct client *client = data; - - if (strcmp(interface, "wl_compositor") == 0) { - client->compositor = - wl_registry_bind(registry, id, &wl_compositor_interface, version); - } -} - -static const struct wl_registry_listener registry_listener = { - .global = handle_global, -}; - -void -test_client_init(struct client *client, const char *name) -{ - client->display = wl_display_connect(name); - assert(client->display); - client->registry = wl_display_get_registry(client->display); - assert(client->registry); - - wl_registry_add_listener(client->registry, ®istry_listener, client); - - wl_display_roundtrip(client->display); - - assert(client->compositor); -} - -void -test_client_finish(struct client *client) -{ - wl_compositor_destroy(client->compositor); - wl_registry_destroy(client->registry); - wl_display_disconnect(client->display); -} - -struct test_server { - struct server_base base; - bool cb_called; - - struct wl_listener new_surface; - struct wl_listener surface_destroy; -}; - -static void -cb_surface_destroy(struct wl_listener *listener, void *data) -{ - struct test_server *server; - - server = wl_container_of(listener, server, surface_destroy); - server->cb_called = true; - wl_display_terminate(server->base.display); -} - -static void -cb_new_surface(struct wl_listener *listener, void *data) -{ - struct ds_surface *surface = data; - struct test_server *server; - - server = wl_container_of(listener, server, new_surface); - server->surface_destroy.notify = cb_surface_destroy; - ds_surface_add_destroy_listener(surface, &server->surface_destroy); -} - -static void -run_client(const char *name) -{ - struct client client; - - test_client_init(&client, name); - - struct wl_surface *surface = - wl_compositor_create_surface(client.compositor); - - wl_display_roundtrip(client.display); - - wl_surface_destroy(surface); - - test_client_finish(&client); -} - -static void -test_surface_create_and_destroy(void) -{ - struct test_server server = { .cb_called = false }; - pid_t pid; - - test_server_init(&server.base); - - pid = fork(); - assert(pid != -1); - - if (pid == 0) { - run_client(server.base.socket); - exit(0); - } - - server.new_surface.notify = cb_new_surface; - ds_compositor_add_new_surface_listener(server.base.compositor, - &server.new_surface); - - wl_display_run(server.base.display); - - assert(server.cb_called); - - test_server_finish(&server.base); -} - -int -main(void) -{ - test_surface_create_and_destroy(); - return 0; -} -- 2.7.4 From f7790557494db83dc62a50b285bed2bce9775a3e Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Fri, 8 Jul 2022 08:08:36 +0900 Subject: [PATCH 06/16] add gtest files Change-Id: I2d2c87aee0a1c842467d04d907f249ce4bd6b57b --- packaging/libds-tizen.spec | 1 + tests/tc_main.cpp | 26 ++++++++++++++++++++++++++ tests/tc_main.h | 12 ++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 tests/tc_main.cpp create mode 100644 tests/tc_main.h diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index fe34941..0ac145b 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -27,6 +27,7 @@ BuildRequires: pkgconfig(tizen-dpms-client) BuildRequires: pkgconfig(cynara-client) BuildRequires: pkgconfig(cynara-session) BuildRequires: pkgconfig(libsmack) +BuildRequires: pkgconfig(gmock) %description Wayland Compositor Library for Tizen diff --git a/tests/tc_main.cpp b/tests/tc_main.cpp new file mode 100644 index 0000000..5e99a34 --- /dev/null +++ b/tests/tc_main.cpp @@ -0,0 +1,26 @@ +#include "gmock/gmock.h" + +int +main(int argc, char **argv) +{ + auto AllTestSuccess = false; + + try { + ::testing::InitGoogleMock(&argc, argv); + ::testing::FLAGS_gtest_death_test_style = "fast"; + } catch (...) { + std::cout << "error while trying to init google tests.\n"; + exit(EXIT_FAILURE); + } + + try { + AllTestSuccess = RUN_ALL_TESTS() == 0 ? true : false; + } catch (const ::testing::internal::GoogleTestFailureException &e) { + AllTestSuccess = false; + std::cout << "GoogleTestFailureException was thrown:" << e.what() + << std::endl; + std::cout << "\n"; + } + + return AllTestSuccess; +} diff --git a/tests/tc_main.h b/tests/tc_main.h new file mode 100644 index 0000000..41e630a --- /dev/null +++ b/tests/tc_main.h @@ -0,0 +1,12 @@ +#ifndef TC_MAIN_H +#define TC_MAIN_H + +#include +#include + +using ::testing::Bool; +using ::testing::Combine; +using ::testing::TestWithParam; +using ::testing::Values; + +#endif -- 2.7.4 From 1508e2530138dda950de00d07692e9dfe607c457 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Fri, 8 Jul 2022 08:09:51 +0900 Subject: [PATCH 07/16] add .clang-format file Change-Id: I988a24843b381135d65b53cb78bd8dfc4d11ce0a --- .clang-format | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..fc9ad87 --- /dev/null +++ b/.clang-format @@ -0,0 +1,102 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: DontAlign +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +# AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: TopLevelDefinitions +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BreakBeforeBraces: Linux +BreakBeforeBinaryOperators: None +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: false +BreakStringLiterals: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + - Regex: '.*' + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: true +IndentGotoLabels: true +IndentPPDirectives: AfterHash +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PointerAlignment: Right +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Latest +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Never +... -- 2.7.4 From 81cb74f424ed1877183b71640bd65e2ce30bd10b Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Fri, 8 Jul 2022 08:11:23 +0900 Subject: [PATCH 08/16] add libds-tizen-allocator-tbm tests Change-Id: I305f0b527ff2b2408f7ce5017cfa8f5107d057fb --- meson.build | 5 +++-- packaging/libds-tizen.spec | 1 + tests/meson.build | 21 ++++++++++++++++++++ tests/tc_allocator_tbm.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 tests/meson.build create mode 100644 tests/tc_allocator_tbm.cpp diff --git a/meson.build b/meson.build index dfe8129..d6804fe 100644 --- a/meson.build +++ b/meson.build @@ -1,9 +1,10 @@ -project('libds_tizen', 'c', +project('libds_tizen', + ['c', 'cpp'], license: 'MIT', version: '0.1.2', default_options: [ 'warning_level=1', - 'c_std=gnu99', + 'c_std=gnu99', 'cpp_std=c++20', 'buildtype=debug' ] ) diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 0ac145b..c5e0623 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -152,6 +152,7 @@ ninja -C builddir install %{_includedir}/libds-tizen/allocator/tbm.h %{_libdir}/pkgconfig/libds-tizen-allocator-tbm.pc %{_libdir}/libds-tizen-allocator-tbm.so +%{_bindir}/libds-tizen-allocator-tbm-tests %files backend-tdm %manifest %{name}.manifest diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000..1d8158c --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,21 @@ +deps_test_common = [ + deps_libds_tizen, + dependency('gmock', required: true), + dependency('wayland-client', required: true), +] + +tc_allocator_tbm_files = [ + 'tc_main.cpp', + 'tc_allocator_tbm.cpp', +] + +executable('libds-tizen-allocator-tbm-tests', + tc_allocator_tbm_files, + dependencies: [ + deps_test_common, + deps_libds_tizen_allocator_tbm, + dependency('libdrm', required: true), + ], + install_dir: libds_tizen_bindir, + install : true +) diff --git a/tests/tc_allocator_tbm.cpp b/tests/tc_allocator_tbm.cpp new file mode 100644 index 0000000..678ad88 --- /dev/null +++ b/tests/tc_allocator_tbm.cpp @@ -0,0 +1,49 @@ +#include "tc_main.h" +#include +#include + +class AllocatorTbmTest : public ::testing::Test +{ + public: + void SetUp(void) override; + void TearDown(void) override; +}; + +void +AllocatorTbmTest::SetUp(void) +{ +} + +void +AllocatorTbmTest::TearDown(void) +{ +} + +TEST_F(AllocatorTbmTest, Create_P) +{ + struct ds_allocator *allocator; + + allocator = ds_tbm_allocator_create(); + EXPECT_TRUE(allocator != NULL); + + ds_allocator_destroy(allocator); +} + +TEST_F(AllocatorTbmTest, GetSurface_P) +{ + struct ds_allocator *allocator; + struct ds_buffer *buffer; + void *tbm_buffer; + + allocator = ds_tbm_allocator_create(); + EXPECT_TRUE(allocator != NULL); + + buffer = + ds_allocator_create_buffer(allocator, 100, 100, DRM_FORMAT_XRGB8888); + EXPECT_TRUE(buffer != NULL); + + tbm_buffer = ds_tbm_buffer_get_surface(buffer); + EXPECT_TRUE(tbm_buffer != NULL); + + ds_allocator_destroy(allocator); +} -- 2.7.4 From fc9c4e058e23ef37d0caa155016a3d6f792c2938 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Tue, 12 Jul 2022 01:26:50 +0900 Subject: [PATCH 09/16] devicemgr: implement pointer_warp Change-Id: Ia3054efdedc15b04b93f4b3e089fa1491c87f981 --- clients/simple-tbm.c | 19 ++++++- examples/tinyds-tdm-libinput.c | 101 ++++++++++++++++++++++++++++++---- include/libds-tizen/input_devicemgr.h | 13 +++++ src/input_devicemgr/input_devicemgr.c | 61 +++++++++++++++++++- src/input_devicemgr/input_devicemgr.h | 1 + 5 files changed, 182 insertions(+), 13 deletions(-) diff --git a/clients/simple-tbm.c b/clients/simple-tbm.c index c82349f..f68fedb 100644 --- a/clients/simple-tbm.c +++ b/clients/simple-tbm.c @@ -56,6 +56,7 @@ struct display { struct tizen_input_device_manager *devicemgr; int notified; bool blocked; + struct wl_surface *entered_surface; }; struct window { @@ -338,8 +339,21 @@ static const struct xdg_wm_base_listener xdg_wm_base_listener = { static void pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + struct display *d = data; + static int warp_x = 0, warp_y = 0; + if (state == WL_POINTER_BUTTON_STATE_PRESSED) { fprintf(stderr, "pointer_handle_button: PRESSED\n"); + + warp_x += 10; + warp_y += 10; + tizen_input_device_manager_pointer_warp(d->devicemgr, + d->entered_surface, + wl_fixed_from_int(warp_x), + wl_fixed_from_int(warp_y)); + fprintf(stderr, "requesting pointer_warp: surface:%p sx: %d sy: %d\n", + d->entered_surface, + warp_x, warp_y); } else { fprintf(stderr, "pointer_handle_button: RELEASED\n"); @@ -350,8 +364,11 @@ static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { + struct display *d = data; + fprintf(stderr, "pointer_handle_enter surface_x:%d, surface_y:%d\n", wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); + d->entered_surface = surface; } static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer, @@ -508,7 +525,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, } if ((caps & WL_SEAT_CAPABILITY_POINTER)) { struct wl_pointer *pointer = wl_seat_get_pointer(wl_seat); - wl_pointer_add_listener(pointer, &pointer_listener, NULL); + wl_pointer_add_listener(pointer, &pointer_listener, d); fprintf(stderr, "seat_handle_capabilities: pointer\n"); } if ((caps & WL_SEAT_CAPABILITY_TOUCH)) { diff --git a/examples/tinyds-tdm-libinput.c b/examples/tinyds-tdm-libinput.c index b1974f1..10c02bb 100644 --- a/examples/tinyds-tdm-libinput.c +++ b/examples/tinyds-tdm-libinput.c @@ -40,6 +40,7 @@ #define TINYDS_UNUSED __attribute__((unused)) struct tinyds_keyboard; +struct tinyds_pointer; struct tinyds_output { @@ -87,8 +88,11 @@ struct tinyds_server struct wl_listener new_output; struct wl_listener new_input; struct wl_listener new_xdg_surface; + struct wl_listener devicemgr_destroy; + struct wl_listener pointer_warp; - struct tinyds_keyboard *keyboard; + struct wl_list keyboards; + struct wl_list pointers; }; struct tinyds_view @@ -119,6 +123,7 @@ struct tinyds_pointer struct wl_listener motion; //relative struct wl_listener button; struct wl_listener frame; + struct wl_list link; //tinyds_server::pointers }; struct tinyds_keyboard @@ -128,6 +133,7 @@ struct tinyds_keyboard struct wl_listener destroy; struct wl_listener key; + struct wl_list link; //tinyds_server::keyboards }; struct tinyds_touch @@ -169,6 +175,10 @@ static void server_add_pointer(struct tinyds_server *server, static void server_add_touch(struct tinyds_server *server, struct ds_input_device *dev); +static struct tinyds_view * +server_view_at(struct tinyds_server *server, double lx, double ly, + double *sx, double *sy); + int main(void) { @@ -214,16 +224,19 @@ view_handle_xdg_surface_map(struct wl_listener *listener, { struct tinyds_view *view; struct ds_keyboard *keyboard; + struct tinyds_keyboard *kbd; 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); + wl_list_for_each(kbd, &view->server->keyboards, link) { + keyboard = ds_input_device_get_keyboard(kbd->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); + return; + } } } @@ -306,6 +319,8 @@ server_new_xdg_surface(struct wl_listener *listener, void *data) view->x = rand() % 1000; view->y = rand() % 500; + + ds_inf("view at (%d, %d)", view->x, view->y); } static void @@ -444,6 +459,55 @@ devicemgr_set_keymap(struct ds_tizen_input_devicemgr *devicemgr) devicemgr_remove_keymap_data(&keymap_list, 458); } +static void +devicemgr_handle_pointer_warp(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct tinyds_pointer *pointer; + struct ds_tizen_input_devicemgr_event_pointer_warp *event = data; + double sx = 0.f, sy = 0.f; + struct tinyds_view *view = NULL; + + server = wl_container_of(listener, server, pointer_warp); + + ds_inf("Pointer warp: surface(%p) x(%.2f) y(%.2f)", event->surface, + event->x, event->y); + + wl_list_for_each(pointer, &server->pointers, link){ + if (!pointer->focused_view) continue; + view = pointer->focused_view; + } + if (!view) return; + + if (event->surface != ds_xdg_surface_get_surface(view->xdg_surface)) { + ds_inf("Pointer is not on the requested surface"); + return; + } + + server->output_x = view->x + (event->x * server->output->width); + server->output_y = view->y + (event->y * server->output->height); + + server_view_at(server, server->output_x, server->output_y, &sx, &sy); + + ds_inf("notify motion: sx:%.2f sy:%.2f, output_x:%.1f, output_y:%.1f", + sx, sy, server->output_x, server->output_y); + + ds_seat_pointer_notify_motion(server->seat, + event->time_msec, sx, sy); +} + +static void +devicemgr_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) +{ + struct tinyds_server *server = + wl_container_of(listener, server, devicemgr_destroy); + + wl_list_remove(&server->devicemgr_destroy.link); + wl_list_remove(&server->pointer_warp.link); + + server->devicemgr = NULL; +} + static bool init_server(struct tinyds_server *server, struct wl_display *display) { @@ -468,6 +532,8 @@ init_server(struct tinyds_server *server, struct wl_display *display) ds_backend_add_new_output_listener(server->backend, &server->new_output); + wl_list_init(&server->keyboards); + wl_list_init(&server->pointers); server->new_input.notify = backend_handle_new_input; ds_backend_add_new_input_listener(server->input_backend, &server->new_input); @@ -499,6 +565,15 @@ init_server(struct tinyds_server *server, struct wl_display *display) } devicemgr_set_keymap(server->devicemgr); + + server->devicemgr_destroy.notify = devicemgr_handle_destroy; + ds_tizen_input_devicemgr_add_destroy_listener(server->devicemgr, + &server->devicemgr_destroy); + + server->pointer_warp.notify = devicemgr_handle_pointer_warp; + ds_tizen_input_devicemgr_add_pointer_warp_listener(server->devicemgr, + &server->pointer_warp); + return true; err: @@ -762,8 +837,7 @@ 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; + wl_list_remove(&kbd->link); free(kbd); } @@ -852,7 +926,7 @@ server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev) kbd->key.notify = keyboard_handle_key; ds_keyboard_add_key_listener(ds_input_device_get_keyboard(dev), &kbd->key); - server->keyboard = kbd; + wl_list_insert(&server->keyboards, &kbd->link); ds_inf("Keyboard(%p) added", kbd); } @@ -1007,6 +1081,7 @@ pointer_handle_device_destroy(struct wl_listener *listener, void *data) wl_list_remove(&pointer->motion.link); wl_list_remove(&pointer->button.link); wl_list_remove(&pointer->frame.link); + wl_list_remove(&pointer->link); free(pointer); } @@ -1123,5 +1198,9 @@ server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev) ds_pointer_add_frame_listener(ds_input_device_get_pointer(dev), &pointer->frame); + pointer->focused_view = NULL; + + wl_list_insert(&server->pointers, &pointer->link); + ds_inf("Pointer(%p) added", pointer); } diff --git a/include/libds-tizen/input_devicemgr.h b/include/libds-tizen/input_devicemgr.h index fc1060e..458d581 100644 --- a/include/libds-tizen/input_devicemgr.h +++ b/include/libds-tizen/input_devicemgr.h @@ -2,6 +2,7 @@ #define LIBDS_TIZEN_INPUT_DEVICEMGR_H #include +#include #ifdef __cplusplus extern "C" { @@ -19,6 +20,13 @@ struct ds_tizen_input_devicemgr_keymap_data struct wl_list link; }; +struct ds_tizen_input_devicemgr_event_pointer_warp +{ + uint32_t time_msec; + struct ds_surface *surface; + double x, y; +}; + struct ds_tizen_input_devicemgr * ds_tizen_input_devicemgr_create(struct ds_backend *backend, struct ds_seat *seat); @@ -28,6 +36,11 @@ ds_tizen_input_devicemgr_add_destroy_listener( struct ds_tizen_input_devicemgr *devicemgr, struct wl_listener *listener); +void +ds_tizen_input_devicemgr_add_pointer_warp_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, diff --git a/src/input_devicemgr/input_devicemgr.c b/src/input_devicemgr/input_devicemgr.c index f690fe7..00c99b0 100644 --- a/src/input_devicemgr/input_devicemgr.c +++ b/src/input_devicemgr/input_devicemgr.c @@ -64,6 +64,10 @@ 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_pointer_warp(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *surface, + wl_fixed_t x, wl_fixed_t y); +static void device_manager_handle_destroy(struct wl_client *client, struct wl_resource *resource); @@ -169,6 +173,7 @@ ds_tizen_input_devicemgr_create(struct ds_backend *backend, } wl_signal_init(&tz_devicemgr->events.destroy); + wl_signal_init(&tz_devicemgr->events.pointer_warp); wl_list_init(&tz_devicemgr->clients); wl_list_init(&tz_devicemgr->devices.kbd->key.pressed); wl_list_init(&tz_devicemgr->keymap_list); @@ -205,6 +210,14 @@ ds_tizen_input_devicemgr_add_destroy_listener( wl_signal_add(&tz_devicemgr->events.destroy, listener); } +WL_EXPORT void +ds_tizen_input_devicemgr_add_pointer_warp_listener( + struct ds_tizen_input_devicemgr *tz_devicemgr, + struct wl_listener *listener) +{ + wl_signal_add(&tz_devicemgr->events.pointer_warp, listener); +} + WL_EXPORT bool ds_tizen_input_devicemgr_set_keymap_list( struct ds_tizen_input_devicemgr *tz_devicemgr, struct wl_list *list) @@ -347,7 +360,7 @@ static const struct tizen_input_device_manager_interface _devicemgr_impl = { .generate_key = device_manager_handle_generate_key, .generate_pointer = device_manager_handle_generate_pointer, .generate_touch = device_manager_handle_generate_touch, - .pointer_warp = NULL, + .pointer_warp = device_manager_handle_pointer_warp, .init_generator_with_name = device_manager_handle_init_generator_with_name, // v2 .destroy = device_manager_handle_destroy, // v3 @@ -767,6 +780,52 @@ finish: } static void +device_manager_handle_pointer_warp(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *surface, + wl_fixed_t x, wl_fixed_t y) +{ + struct ds_tizen_input_devicemgr *tz_devicemgr; + int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES; + int32_t new_x, new_y; + double transformed_x = .0, transformed_y = .0; + struct ds_tizen_input_devicemgr_event_pointer_warp ds_event; + struct timeval time; + unsigned int timestamp; + + tz_devicemgr = wl_resource_get_user_data(resource); + + if (!tz_devicemgr->devices.ptr || + !tz_devicemgr->devices.ptr->input_device) { + ds_err("Pointer device is not initialized\n"); + goto finish; + } + + new_x = wl_fixed_to_int(x); + new_y = wl_fixed_to_int(y); + + if (tz_devicemgr->output.width != 0 && tz_devicemgr->output.height != 0) { + transformed_x = new_x / (double)tz_devicemgr->output.width; + transformed_y = new_y / (double)tz_devicemgr->output.height; + } + + gettimeofday(&time, NULL); + timestamp = time.tv_sec * 1000 + time.tv_usec / 1000; + + ds_event.time_msec = timestamp; + ds_event.surface = ds_surface_from_resource(surface); + ds_event.x = transformed_x; + ds_event.y = transformed_y; + ds_inf("Pointer warp. surface:%p, x:%.2f, y:%.2f", ds_event.surface, + ds_event.x, ds_event.y); + + wl_signal_emit(&tz_devicemgr->events.pointer_warp, &ds_event); + 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) { diff --git a/src/input_devicemgr/input_devicemgr.h b/src/input_devicemgr/input_devicemgr.h index a4428ee..f773fc1 100644 --- a/src/input_devicemgr/input_devicemgr.h +++ b/src/input_devicemgr/input_devicemgr.h @@ -36,6 +36,7 @@ struct ds_tizen_input_devicemgr { struct { struct wl_signal destroy; + struct wl_signal pointer_warp; //ds_tizen_input_devicemgr_event_pointer_warp } events; struct wl_listener new_input; -- 2.7.4 From 776c8e08e66e1f5a354f811462ca074359c76bce Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Thu, 7 Jul 2022 19:28:26 +0900 Subject: [PATCH 10/16] impelement libds-tizen-indicator This is the server implementation for tizen_indicator protocol. Change-Id: I97efef30d5f9e5c540d51b92bcac43808b53951a --- include/libds-tizen/indicator.h | 75 ++++++ packaging/libds-tizen.spec | 29 +++ src/indicator/indicator.c | 499 ++++++++++++++++++++++++++++++++++++++++ src/indicator/meson.build | 29 +++ src/meson.build | 1 + 5 files changed, 633 insertions(+) create mode 100644 include/libds-tizen/indicator.h create mode 100644 src/indicator/indicator.c create mode 100644 src/indicator/meson.build diff --git a/include/libds-tizen/indicator.h b/include/libds-tizen/indicator.h new file mode 100644 index 0000000..69fc82e --- /dev/null +++ b/include/libds-tizen/indicator.h @@ -0,0 +1,75 @@ +#ifndef LIBDS_TIZEN_INDICATOR_H +#define LIBDS_TIZEN_INDICATOR_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tizen_indicator; + +enum ds_tizen_indicator_state +{ + DS_TIZEN_INDICATOR_STATE_UNKNOWN, + DS_TIZEN_INDICATOR_STATE_OFF, + DS_TIZEN_INDICATOR_STATE_ON, +}; + +enum ds_tizen_indicator_opacity_mode +{ + DS_TIZEN_INDICATOR_OPACITY_MODE_UNKNOWN, + DS_TIZEN_INDICATOR_OPACITY_MODE_OPAQUE, + DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSLUCENT, + DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSPARENT, + DS_TIZEN_INDICATOR_OPACITY_MODE_BG_TRANSPARENT, +}; + +enum ds_tizen_indicator_visible_type +{ + DS_TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN, + DS_TIZEN_INDICATOR_VISIBLE_TYPE_SHOWN, +}; + +struct ds_tizen_indicator * +ds_tizen_indicator_create(struct wl_display *display); + +void +ds_tizen_indicator_add_destroy_listener(struct ds_tizen_indicator *indicator, + struct wl_listener *listener); + +void +ds_tizen_indicator_add_change_state_listener( + struct ds_tizen_indicator *indicator, struct wl_listener *listener); + +void +ds_tizen_indicator_add_change_opacity_mode_listener( + struct ds_tizen_indicator *indicator, struct wl_listener *listener); + +void +ds_tizen_indicator_add_change_visible_type_listener( + struct ds_tizen_indicator *indicator, struct wl_listener *listener); + +enum ds_tizen_indicator_state +ds_tizen_indicator_get_state(struct ds_tizen_indicator *indicator, + struct ds_surface *surface); + +enum ds_tizen_indicator_opacity_mode +ds_tizen_indicator_get_opacity_mode(struct ds_tizen_indicator *indicator, + struct ds_surface *surface); + +enum ds_tizen_indicator_visible_type +ds_tizen_indicator_get_visible_type(struct ds_tizen_indicator *indicator, + struct ds_surface *surface); + +void +ds_tizen_indicator_send_flick(struct ds_tizen_indicator *indicator, + struct ds_surface *surface); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index c5e0623..34b918c 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -122,6 +122,21 @@ Group: Development/Libraries %description dpms-devel Development package for tizen dpms +## libds-tizen-indicator +%package indicator +Summary: Library for tizen indicator +Group: Development/Libraries + +%description indicator +Library for tizen indicator + +%package indicator-devel +Summary: Development package for tizen indicator +Group: Development/Libraries + +%description indicator-devel +Development package for tizen indicator + %prep %setup -q cp %{SOURCE1001} . @@ -232,3 +247,17 @@ ninja -C builddir install %{_libdir}/libds-tizen-dpms.so %{_bindir}/tinyds-tdm-dpms %{_bindir}/ds-simple-dpms + +%files indicator +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_libdir}/libds-tizen-indicator.so.* + +%files indicator-devel +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_includedir}/libds-tizen/indicator.h +%{_libdir}/pkgconfig/libds-tizen-indicator.pc +%{_libdir}/libds-tizen-indicator.so diff --git a/src/indicator/indicator.c b/src/indicator/indicator.c new file mode 100644 index 0000000..23f0e9f --- /dev/null +++ b/src/indicator/indicator.c @@ -0,0 +1,499 @@ +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "libds-tizen/indicator.h" + +#define TIZEN_INDICATOR_VERSION 1 + +struct ds_tizen_indicator +{ + struct wl_global *global; + + struct wl_list clients; + + struct wl_listener destroy; + + struct { + struct wl_signal destroy; + struct wl_signal change_state; + struct wl_signal change_opacity_mode; + struct wl_signal change_visible_type; + } events; +}; + +struct ds_tizen_indicator_client +{ + struct ds_tizen_indicator *indicator; + + struct wl_resource *resource; + struct wl_client *wl_client; + + struct wl_list infos; + + struct wl_list link; // ds_tizen_indicator::clients +}; + +struct ds_tizen_indicator_info +{ + struct ds_surface *surface; + + int32_t state; + int32_t opacity_mode; + int32_t visible_type; + + struct wl_list link; // ds_tizen_indicator_client::infos +}; + +static void indicator_handle_display_destroy(struct wl_listener *listener, + void *data); + +static void indicator_bind(struct wl_client *wl_client, void *data, + uint32_t version, uint32_t id); + +static struct ds_tizen_indicator_client *tizen_indicator_find_client( + struct ds_tizen_indicator *indicator, + struct ds_surface *surface); + +static struct ds_tizen_indicator_info *tizen_indicator_find_info( + struct ds_tizen_indicator *indicator, + struct ds_surface *surface); + +static struct ds_tizen_indicator_info *tizen_indicator_client_find_info( + struct ds_tizen_indicator_client *client, + struct ds_surface *surface); + +static struct ds_tizen_indicator_info *tizen_indicator_client_get_info( + struct ds_tizen_indicator_client *client, + struct ds_surface *surface); + +WL_EXPORT struct ds_tizen_indicator * +ds_tizen_indicator_create(struct wl_display *display) +{ + struct ds_tizen_indicator *indicator; + + indicator = calloc(1, sizeof *indicator); + if (!indicator) { + ds_err("calloc() failed."); + return NULL; + } + + indicator->global = wl_global_create(display, &tizen_indicator_interface, + 1, indicator, indicator_bind); + if (!indicator->global) { + ds_err("wl_global_create() failed. tizen_indicator_interface"); + free(indicator); + return NULL; + } + + wl_list_init(&indicator->clients); + + indicator->destroy.notify = indicator_handle_display_destroy; + wl_display_add_destroy_listener(display, &indicator->destroy); + + wl_signal_init(&indicator->events.destroy); + wl_signal_init(&indicator->events.change_state); + wl_signal_init(&indicator->events.change_opacity_mode); + wl_signal_init(&indicator->events.change_visible_type); + + ds_inf("Global created: tizen_indicator(%p)", indicator); + + return indicator; +} + +WL_EXPORT void +ds_tizen_indicator_add_destroy_listener(struct ds_tizen_indicator *indicator, + struct wl_listener *listener) +{ + wl_signal_add(&indicator->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_indicator_add_change_state_listener( + struct ds_tizen_indicator *indicator, struct wl_listener *listener) +{ + wl_signal_add(&indicator->events.change_state, listener); +} + +WL_EXPORT void +ds_tizen_indicator_add_change_opacity_mode_listener( + struct ds_tizen_indicator *indicator, struct wl_listener *listener) +{ + wl_signal_add(&indicator->events.change_opacity_mode, listener); +} + +WL_EXPORT void +ds_tizen_indicator_add_change_visible_type_listener( + struct ds_tizen_indicator *indicator, struct wl_listener *listener) +{ + wl_signal_add(&indicator->events.change_visible_type, listener); +} + +WL_EXPORT enum ds_tizen_indicator_state +ds_tizen_indicator_get_state(struct ds_tizen_indicator *indicator, + struct ds_surface *surface) +{ + struct ds_tizen_indicator_info *info; + + info = tizen_indicator_find_info(indicator, surface); + if (info == NULL) { + ds_err("tizen_indicator: tizen_indicator_find_info() failed."); + return DS_TIZEN_INDICATOR_STATE_UNKNOWN; + } + + return info->state; +} + +WL_EXPORT enum ds_tizen_indicator_opacity_mode +ds_tizen_indicator_get_opacity_mode(struct ds_tizen_indicator *indicator, + struct ds_surface *surface) +{ + struct ds_tizen_indicator_info *info; + + info = tizen_indicator_find_info(indicator, surface); + if (info == NULL) { + ds_err("tizen_indicator: tizen_indicator_find_info() failed."); + return DS_TIZEN_INDICATOR_OPACITY_MODE_UNKNOWN; + } + + return info->opacity_mode; +} + +WL_EXPORT enum ds_tizen_indicator_visible_type +ds_tizen_indicator_get_visible_type(struct ds_tizen_indicator *indicator, + struct ds_surface *surface) +{ + struct ds_tizen_indicator_info *info; + + info = tizen_indicator_find_info(indicator, surface); + if (info == NULL) { + ds_err("tizen_indicator: tizen_indicator_find_info() failed."); + return DS_TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN; + } + + return info->visible_type; +} + +WL_EXPORT void +ds_tizen_indicator_send_flick(struct ds_tizen_indicator *indicator, + struct ds_surface *surface) +{ + struct ds_tizen_indicator_client *client; + + client = tizen_indicator_find_client(indicator, surface); + if (client == NULL) { + ds_err("tizen_indicator: tizen_indicator_find_client() failed."); + return; + } + + tizen_indicator_send_flick(client->resource, + ds_surface_get_wl_resource(surface), 0); +} + +static struct ds_tizen_indicator_client * +tizen_indicator_find_client(struct ds_tizen_indicator *indicator, + struct ds_surface *surface) +{ + struct ds_tizen_indicator_info *info; + struct ds_tizen_indicator_client *client; + + wl_list_for_each(client, &indicator->clients, link) { + info = tizen_indicator_client_find_info(client, surface); + if (info != NULL) + return client; + } + + return NULL; +} + +static struct ds_tizen_indicator_info * +tizen_indicator_find_info(struct ds_tizen_indicator *indicator, + struct ds_surface *surface) +{ + struct ds_tizen_indicator_info *info; + struct ds_tizen_indicator_client *client; + + wl_list_for_each(client, &indicator->clients, link) { + info = tizen_indicator_client_find_info(client, surface); + if (info != NULL) + return info; + } + + return NULL; +} + +static struct ds_tizen_indicator_info * +tizen_indicator_client_find_info(struct ds_tizen_indicator_client *client, + struct ds_surface *surface) +{ + struct ds_tizen_indicator_info *info; + + wl_list_for_each(info, &client->infos, link) { + if (surface == info->surface) + return info; + } + + return NULL; +} + +static struct ds_tizen_indicator_info * +tizen_indicator_client_get_info(struct ds_tizen_indicator_client *client, + struct ds_surface *surface) +{ + struct ds_tizen_indicator_info *info; + + info = tizen_indicator_client_find_info(client, surface); + if (info) + return info; + + info = calloc(1, sizeof *info); + if (info == NULL) { + ds_err("calloc() failed. tizen_indicator"); + return NULL; + } + + info->surface = surface; + + // The initial values of state, opacity_mode and visible_type are not + // each value of enum ds_tizen_indicator_state, + // enum ds_tizen_indicator_opacity_mode and + // enum ds_tizen_indicator_opacity_mode + // because of the first signal emit for change_state signal. + info->state = -1; + info->opacity_mode = -1; + info->visible_type = -1; + + wl_list_insert(&client->infos, &info->link); + + return info; +} + +static void +indicator_handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tizen_indicator *indicator; + + indicator = wl_container_of(listener, indicator, destroy); + + ds_inf("Global destroy: indicator(%p)", indicator); + + wl_signal_emit(&indicator->events.destroy, indicator); + wl_list_remove(&indicator->destroy.link); + wl_global_destroy(indicator->global); + free(indicator); +} + +static void +indicator_handle_destroy(struct wl_client *wl_client, + struct wl_resource *resource) +{ + struct ds_tizen_indicator_client *client; + + client = wl_resource_get_user_data(resource); + + if (!wl_list_empty(&client->infos)) { + ds_err("tizen_indicator was destroyed before children"); + return; + } + + wl_resource_destroy(resource); +} + +static void +indicator_handle_set_state(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + int32_t state) +{ + struct ds_tizen_indicator_client *client; + struct ds_tizen_indicator_info *info; + struct ds_surface *surface; + enum ds_tizen_indicator_state indicator_state; + + ds_inf("tizen_indicator: set_state : state %d", state); + + client = wl_resource_get_user_data(resource); + surface = ds_surface_from_resource(surface_resource); + + info = tizen_indicator_client_get_info(client, surface); + if (info == NULL) { + ds_err("tizen_indicator_client_get_info() failed. tizen_indicator"); + wl_client_post_no_memory(wl_client); + return; + } + + switch (state) { + case TIZEN_INDICATOR_STATE_OFF: + indicator_state = DS_TIZEN_INDICATOR_STATE_OFF; + break; + case TIZEN_INDICATOR_STATE_ON: + indicator_state = DS_TIZEN_INDICATOR_STATE_ON; + break; + default: + indicator_state = DS_TIZEN_INDICATOR_STATE_UNKNOWN; + break; + } + + if (info->state != indicator_state) { + ds_inf("tizen_indicator: surface : %p, change_state : %d -> %d", + surface, info->state, indicator_state); + info->state = indicator_state; + + wl_signal_emit(&client->indicator->events.change_state, surface); + } +} + +static void +indicator_handle_set_opacity_mode(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + int32_t mode) +{ + struct ds_tizen_indicator_client *client; + struct ds_tizen_indicator_info *info; + struct ds_surface *surface; + enum ds_tizen_indicator_opacity_mode opacity_mode; + + ds_inf("tizen_indicator: set_opacity_mode : opacity_mode %d", mode); + + client = wl_resource_get_user_data(resource); + surface = ds_surface_from_resource(surface_resource); + + info = tizen_indicator_client_get_info(client, surface); + if (info == NULL) { + ds_err("tizen_indicator_client_get_info() failed. tizen_indicator"); + wl_client_post_no_memory(wl_client); + return; + } + + switch (mode) { + case TIZEN_INDICATOR_OPACITY_MODE_OPAQUE: + opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_OPAQUE; + break; + case TIZEN_INDICATOR_OPACITY_MODE_TRANSLUCENT: + opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSLUCENT; + break; + case TIZEN_INDICATOR_OPACITY_MODE_TRANSPARENT: + opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSPARENT; + break; + case TIZEN_INDICATOR_OPACITY_MODE_BG_TRANSPARENT: + opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_BG_TRANSPARENT; + break; + default: + opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_UNKNOWN; + break; + } + + if (info->opacity_mode != opacity_mode) { + ds_inf("tizen_indicator: surface : %p, change_opacity_mode : %d -> %d", + surface, info->opacity_mode, opacity_mode); + info->opacity_mode = opacity_mode; + + wl_signal_emit(&client->indicator->events.change_opacity_mode, surface); + } +} + +static void +indicator_handle_set_visible_type(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + int32_t type) +{ + struct ds_tizen_indicator_client *client; + struct ds_tizen_indicator_info *info; + struct ds_surface *surface; + enum ds_tizen_indicator_visible_type visible_type; + + ds_inf("tizen_indicator: set_visible_type : visible_type %d", type); + + client = wl_resource_get_user_data(resource); + surface = ds_surface_from_resource(surface_resource); + + info = tizen_indicator_client_get_info(client, surface); + if (info == NULL) { + ds_err("tizen_indicator_client_get_info() failed. tizen_indicator"); + wl_client_post_no_memory(wl_client); + return; + } + + switch (type) { + case TIZEN_INDICATOR_VISIBLE_TYPE_SHOWN: + visible_type = DS_TIZEN_INDICATOR_VISIBLE_TYPE_SHOWN; + break; + default: + visible_type = DS_TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN; + break; + } + + if (info->visible_type != visible_type) { + ds_inf("tizen_indicator: surface : %p, change_visible_type : %d -> %d", + surface, info->visible_type, visible_type); + info->visible_type = visible_type; + + wl_signal_emit(&client->indicator->events.change_visible_type, surface); + } +} + +static const struct tizen_indicator_interface indicator_impl = +{ + indicator_handle_destroy, + indicator_handle_set_state, + indicator_handle_set_opacity_mode, + indicator_handle_set_visible_type, +}; + +static void +_tizen_indicator_client_handle_destroy(struct wl_resource *resource) +{ + struct ds_tizen_indicator_client *client; + struct ds_tizen_indicator_info *info, *tmp; + + client = wl_resource_get_user_data(resource); + + ds_inf("_tizen_indicator_client_handle_destroy (client:%p)", client); + + wl_list_for_each_safe(info, tmp, &client->infos, link) { + wl_list_remove(&info->link); + free(info); + } + + wl_list_remove(&client->link); + free(client); +} + +static void +indicator_bind(struct wl_client *wl_client, void *data, uint32_t version, + uint32_t id) +{ + struct ds_tizen_indicator *indicator = data; + struct ds_tizen_indicator_client *client; + + client = calloc(1, sizeof *client); + if (client == NULL) { + ds_err("calloc() failed. tizen_indicator"); + wl_client_post_no_memory(wl_client); + return; + } + + ds_inf("tizen_indicator_client binds. (client:%p)", client); + + client->indicator = indicator; + client->wl_client = wl_client; + + wl_list_init(&client->infos); + + client->resource = wl_resource_create(wl_client, &tizen_indicator_interface, + MIN(version, TIZEN_INDICATOR_VERSION), id); + if (client->resource == NULL) { + ds_err("tizen_indicator : wl_resource_create() failed."); + free(client); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(client->resource, &indicator_impl, client, + _tizen_indicator_client_handle_destroy); + + wl_list_insert(&indicator->clients, &client->link); +} diff --git a/src/indicator/meson.build b/src/indicator/meson.build new file mode 100644 index 0000000..a87c690 --- /dev/null +++ b/src/indicator/meson.build @@ -0,0 +1,29 @@ +libds_tizen_indicator_files = [ + 'indicator.c', +] + +libds_tizen_indicator_deps = [ + deps_libds_tizen, + dependency('tizen-extension-server', required: true), +] + +lib_libds_tizen_indicator = shared_library('ds-tizen-indicator', libds_tizen_indicator_files, + dependencies: libds_tizen_indicator_deps, + include_directories: [ common_inc, include_directories('.'), include_directories('..') ], + version: meson.project_version(), + install: true +) + +deps_libds_tizen_indicator = declare_dependency( + link_with: lib_libds_tizen_indicator, + dependencies: libds_tizen_indicator_deps, + include_directories: [ common_inc, include_directories('.') ], +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(lib_libds_tizen_indicator, + version: meson.project_version(), + filebase: 'libds-tizen-indicator', + name: 'libds-tizen-indicator', + description: 'tizen indicator extension of libds-tizen for tizen platform', +) diff --git a/src/meson.build b/src/meson.build index 46d807d..09a7f1a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -33,3 +33,4 @@ subdir('backend') subdir('keyrouter') subdir('input_devicemgr') subdir('dpms') +subdir('indicator') -- 2.7.4 From 477ee0aa51b96b54ad4e63e994c281b36e999c22 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Sun, 10 Jul 2022 13:46:59 +0900 Subject: [PATCH 11/16] add mock client/compositor This is the mock classes for testing request/event interaction between client and server. Change-Id: Ide1366d47f3cae83944520c8459a62bf4d737a1f --- tests/mockclient.cpp | 70 ++++++++++++++++++++++ tests/mockclient.h | 48 +++++++++++++++ tests/mockcompositor.cpp | 149 +++++++++++++++++++++++++++++++++++++++++++++++ tests/mockcompositor.h | 80 +++++++++++++++++++++++++ 4 files changed, 347 insertions(+) create mode 100644 tests/mockclient.cpp create mode 100644 tests/mockclient.h create mode 100644 tests/mockcompositor.cpp create mode 100644 tests/mockcompositor.h diff --git a/tests/mockclient.cpp b/tests/mockclient.cpp new file mode 100644 index 0000000..f9f9581 --- /dev/null +++ b/tests/mockclient.cpp @@ -0,0 +1,70 @@ +/************************************************************************** + * + * Copyright 2022 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: SooChan Lim + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * +**************************************************************************/ + +#include "mockclient.h" +#include + +MockClient::MockClient() +{ + display = wl_display_connect("test-ds-tizen"); + if (!display) + ds_err("wl_display_connect() filed."); + + registry = wl_display_get_registry(display); + if (!registry) + ds_err("wl_display_get_registry() filed."); +} + +MockClient::MockClient(const struct wl_registry_listener *registry_listener, void *data) +{ + int ret; + display = wl_display_connect("test-ds-tizen"); + if (!display) + ds_err("wl_display_connect() filed."); + + registry = wl_display_get_registry(display); + if (!registry) + ds_err("wl_display_get_registry() filed."); + + ret = wl_registry_add_listener(registry, registry_listener, data); + if (ret) + ds_err("wl_registry_add_listener() filed."); + + wl_display_roundtrip(display); +} + +MockClient::~MockClient() +{ + wl_registry_destroy(registry); + wl_display_disconnect(display); +} + +void MockClient::RoundTrip() +{ + wl_display_roundtrip(display); +} \ No newline at end of file diff --git a/tests/mockclient.h b/tests/mockclient.h new file mode 100644 index 0000000..178b9bc --- /dev/null +++ b/tests/mockclient.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Copyright 2022 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: SooChan Lim + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * +**************************************************************************/ + +#ifndef _MOCKCLIENT_H_ +#define _MOCKCLIENT_H_ + +#include +#include + +class MockClient +{ +public: + MockClient(); + MockClient(const struct wl_registry_listener *registry_listener, void *data); + virtual ~MockClient(); + void RoundTrip(); + +private: + struct wl_display *display; + struct wl_registry *registry; +}; + +#endif diff --git a/tests/mockcompositor.cpp b/tests/mockcompositor.cpp new file mode 100644 index 0000000..62fc779 --- /dev/null +++ b/tests/mockcompositor.cpp @@ -0,0 +1,149 @@ +/************************************************************************** + * + * Copyright 2020 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: SooChan Lim + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * +**************************************************************************/ + +#include "mockcompositor.h" +#include + +static void +logger_func(void *user_data, enum wl_protocol_logger_type type, + const struct wl_protocol_logger_message *message) +{ + //Compositor *c = static_cast(user_data); +#if 0 + std::cout << "res:" << wl_resource_get_class(message->resource) << " " + << "op:" << message->message_opcode << " " + << "name:" << message->message->name << "\n"; +#endif +} + +Compositor::Compositor() + : display(wl_display_create()), + loop(wl_display_get_event_loop(display)), + logger(wl_display_add_protocol_logger(display, logger_func, this)) +{ + int ret; + + ret = wl_display_add_socket(display, "test-ds-tizen"); + if (ret != 0) + ds_err("wl_display_add_socket() filed."); + + ret = wl_display_init_shm(display); + if (ret != 0) + ds_err("wl_display_init_shm() filed."); + + compositor = ds_compositor_create(display); + if (compositor == nullptr) + ds_err("ds_compositor_create() filed."); +} + +Compositor::~Compositor () +{ + wl_list *clients = wl_display_get_client_list(display); + wl_client *client = nullptr; + + wl_client_for_each(client, clients) { + wl_client_destroy(client); + } + + wl_protocol_logger_destroy(logger); + wl_display_destroy(display); +} + +void Compositor::DispatchEvents() +{ + /* flush any pending client events */ + wl_display_flush_clients(display); + /* dispatch any pending main loop events */ + wl_event_loop_dispatch(loop, 0); +} + +MockCompositor::MockCompositor() + : compositor(nullptr) +{ + th = std::thread([this](){ + Compositor c; + compositor = &c; + + // mockcompositor is ready + ready = true; + cv.notify_one(); + + while (alive) { + // mockcompositor process the events in every 40 milliseconds + std::this_thread::sleep_for(std::chrono::milliseconds(40)); + Process(); + } + }); + + // wait until the child thread(mockcompositor) is ready + { + std::unique_lock lock(m); + cv.wait(lock, [this]{return ready;}); + } +} + +MockCompositor::MockCompositor(ds_test_setup_func_t setup_func, void *data) + : compositor(nullptr) +{ + th = std::thread([this, setup_func, data](){ + Compositor c; + compositor = &c; + + // call test setup_function + setup_func(data); + + // mockcompositor is ready + ready = true; + cv.notify_one(); + + while (alive) { + // mockcompositor process the events in every 40 milliseconds + std::this_thread::sleep_for(std::chrono::milliseconds(40)); + + Process(); + } + }); + + // wait until the child thread(mockcompositor) is ready + { + std::unique_lock lock(m); + cv.wait(lock, [this]{return ready;}); + } +} + +MockCompositor::~MockCompositor() { + // finish the child thread(mockcompositor). + alive = false; + th.join(); +} + +void MockCompositor::Process() +{ + std::lock_guard lock(m); + compositor->DispatchEvents(); +} diff --git a/tests/mockcompositor.h b/tests/mockcompositor.h new file mode 100644 index 0000000..2b03f46 --- /dev/null +++ b/tests/mockcompositor.h @@ -0,0 +1,80 @@ +/************************************************************************** + * + * Copyright 2020 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: SooChan Lim + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * +**************************************************************************/ + +#ifndef _MOCKCOMPOSITOR_H_ +#define _MOCKCOMPOSITOR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ds_listener test function call +typedef void (*ds_test_setup_func_t)(void *data); + +class Compositor +{ +public: + Compositor(); + ~Compositor(); + void DispatchEvents(); + +public: + struct wl_display *display; + struct wl_event_loop *loop; + struct wl_protocol_logger *logger; + struct ds_compositor *compositor; +}; + +class MockCompositor +{ +public: + MockCompositor(); + MockCompositor(ds_test_setup_func_t setup_func, void *data); + virtual ~MockCompositor(); + + void Process(); + +protected: + Compositor *compositor; + +private: + std::thread th; + std::mutex m; + std::condition_variable cv; + + bool alive = true; + bool ready = false; +}; + +#endif -- 2.7.4 From 5ccdb3a9e3de42970111f84d166e21c1dc55727c Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Sun, 10 Jul 2022 13:48:27 +0900 Subject: [PATCH 12/16] add indicator test cases Change-Id: I6c755aff6ca1764b73289b64991544b26bed08fb --- packaging/libds-tizen.spec | 1 + tests/meson.build | 26 +++ tests/tc_indicator.cpp | 505 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 532 insertions(+) create mode 100644 tests/tc_indicator.cpp diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 34b918c..8935d5d 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -261,3 +261,4 @@ ninja -C builddir install %{_includedir}/libds-tizen/indicator.h %{_libdir}/pkgconfig/libds-tizen-indicator.pc %{_libdir}/libds-tizen-indicator.so +%{_bindir}/libds-tizen-indicator-tests diff --git a/tests/meson.build b/tests/meson.build index 1d8158c..8cff406 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -4,6 +4,12 @@ deps_test_common = [ dependency('wayland-client', required: true), ] +tc_mock_files = [ + 'mockclient.cpp', + 'mockcompositor.cpp' +] + +## allcoator_tbm tests tc_allocator_tbm_files = [ 'tc_main.cpp', 'tc_allocator_tbm.cpp', @@ -19,3 +25,23 @@ executable('libds-tizen-allocator-tbm-tests', install_dir: libds_tizen_bindir, install : true ) + +## indicator tests +tc_indicator_files = [ + 'tc_main.cpp', + 'tc_indicator.cpp', +] + +executable('libds-tizen-indicator-tests', + [ + tc_mock_files, + tc_indicator_files + ], + dependencies: [ + deps_test_common, + deps_libds_tizen_indicator, + dependency('libdrm', required: true), + ], + install_dir: libds_tizen_bindir, + install : true +) diff --git a/tests/tc_indicator.cpp b/tests/tc_indicator.cpp new file mode 100644 index 0000000..c589ef3 --- /dev/null +++ b/tests/tc_indicator.cpp @@ -0,0 +1,505 @@ +#include "tc_main.h" +#include "mockclient.h" +#include "mockcompositor.h" +#include +#include + +class MockIndicatorCompositor : public MockCompositor +{ +public: + MockIndicatorCompositor() + : MockCompositor(&MockIndicatorCompositor::TestSetup, this) + { + ds_inf("%s : this(%p)", __func__, this); + + // initialize the flags to check + bSurfaceDestroyed = false; + + bDestroyed = false; + + bStateOn = false; + bStateOff = false; + + bOpacityModeOpque = false; + bOpacityModeTranslucent = false; + bOpacityModeTransparent = false; + bOpacityModeBgTransparent = false; + + bVisibleTypeHidden = false; + bVisibleTypeShown = false; + } + + ~MockIndicatorCompositor() + { + ds_inf("%s : this(%p)", __func__, this); + } + + static void TestSetup(void *data) + { + MockIndicatorCompositor *mockComp = + static_cast(data); + Compositor *comp = mockComp->compositor; + + ds_inf("%s: mockComp(%p)", __func__, mockComp); + + // new surface listener + mockComp->mNewSurfaceListener.notify = + MockIndicatorCompositor::NewSurfaceCallback; + mockComp->mNewSurfaceListener.parent = mockComp; + ds_compositor_add_new_surface_listener(comp->compositor, + &mockComp->mNewSurfaceListener); + + mockComp->mIndicator = ds_tizen_indicator_create(comp->display); + + // destroy listener + mockComp->mDestroyListener.notify = + MockIndicatorCompositor::DestroyCallback; + mockComp->mDestroyListener.parent = mockComp; + ds_tizen_indicator_add_destroy_listener(mockComp->mIndicator, + &mockComp->mDestroyListener); + + // change_state listener + mockComp->mChangeStateListener.notify = + MockIndicatorCompositor::ChangeStateCallback; + mockComp->mChangeStateListener.parent = mockComp; + ds_tizen_indicator_add_change_state_listener(mockComp->mIndicator, + &mockComp->mChangeStateListener); + + // change_opacity_mode listener + mockComp->mChangeOpacityModeListener.notify = + MockIndicatorCompositor::ChangeOpacityModeCallback; + mockComp->mChangeOpacityModeListener.parent = mockComp; + ds_tizen_indicator_add_change_opacity_mode_listener( + mockComp->mIndicator, + &mockComp->mChangeOpacityModeListener); + + // change_visible_type listener + mockComp->mChangeVisibleTypeListener.notify = + MockIndicatorCompositor::ChangeVisibleTypeCallback; + mockComp->mChangeVisibleTypeListener.parent = mockComp; + ds_tizen_indicator_add_change_visible_type_listener( + mockComp->mIndicator, + &mockComp->mChangeVisibleTypeListener); + } + + static void NewSurfaceCallback(struct wl_listener *listener, void *data) + { + MockIndicatorCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + mockComp->mSurface = surface; + + // del surface listener + mockComp->mDelSurfaceListener.notify = + MockIndicatorCompositor::DelSurfaceCallback; + mockComp->mDelSurfaceListener.parent = mockComp; + ds_surface_add_destroy_listener(surface, + &mockComp->mDelSurfaceListener); + } + + static void DelSurfaceCallback(struct wl_listener *listener, void *data) + { + MockIndicatorCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + if (ds_surface_get_wl_resource(mockComp->mSurface) == + ds_surface_get_wl_resource(surface)) { + ds_inf("%s: surface is deleted.", __func__); + mockComp->bSurfaceDestroyed = true; + } + } + + static void DestroyCallback(struct wl_listener *listener, void *data) + { + ds_inf("%s", __func__); + + MockIndicatorCompositor *mockComp = + reinterpret_cast(listener)->parent; + + mockComp->bDestroyed = true; + } + + static void ChangeStateCallback(struct wl_listener *listener, void *data) + { + ds_inf("%s", __func__); + + MockIndicatorCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + enum ds_tizen_indicator_state state; + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + state = ds_tizen_indicator_get_state(mockComp->mIndicator, + mockComp->mSurface); + + if (state == DS_TIZEN_INDICATOR_STATE_ON) + mockComp->bStateOn = true; + if (state == DS_TIZEN_INDICATOR_STATE_OFF) + mockComp->bStateOff = true; + } + + static void ChangeOpacityModeCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockIndicatorCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + enum ds_tizen_indicator_opacity_mode opacity_mode; + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + opacity_mode = ds_tizen_indicator_get_opacity_mode(mockComp->mIndicator, + mockComp->mSurface); + + if (opacity_mode == DS_TIZEN_INDICATOR_OPACITY_MODE_OPAQUE) + mockComp->bOpacityModeOpque = true; + if (opacity_mode == DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSLUCENT) + mockComp->bOpacityModeTranslucent = true; + if (opacity_mode == DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSPARENT) + mockComp->bOpacityModeTransparent = true; + if (opacity_mode == DS_TIZEN_INDICATOR_OPACITY_MODE_BG_TRANSPARENT) + mockComp->bOpacityModeBgTransparent = true; + } + + static void ChangeVisibleTypeCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockIndicatorCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + enum ds_tizen_indicator_visible_type visible_type; + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + visible_type = ds_tizen_indicator_get_visible_type(mockComp->mIndicator, + mockComp->mSurface); + + if (visible_type == DS_TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN) + mockComp->bVisibleTypeHidden = true; + if (visible_type == DS_TIZEN_INDICATOR_VISIBLE_TYPE_SHOWN) + mockComp->bVisibleTypeShown = true; + } + + void SendFlick() + { + ds_inf("%s", __func__); + + ds_tizen_indicator_send_flick(mIndicator, mSurface); + } + +public: + bool bSurfaceDestroyed; + bool bDestroyed; + bool bStateOn; + bool bStateOff; + bool bOpacityModeOpque; + bool bOpacityModeTranslucent; + bool bOpacityModeTransparent; + bool bOpacityModeBgTransparent; + bool bVisibleTypeHidden; + bool bVisibleTypeShown; + +private: + struct ds_surface *mSurface; + struct NewSurfaceListener : ::wl_listener { + MockIndicatorCompositor *parent; + }; + NewSurfaceListener mNewSurfaceListener; + struct DelSurfaceListener : ::wl_listener { + MockIndicatorCompositor *parent; + }; + NewSurfaceListener mDelSurfaceListener; + + struct ds_tizen_indicator *mIndicator; + struct DestroyListener : ::wl_listener { + MockIndicatorCompositor *parent; + }; + NewSurfaceListener mDestroyListener; + struct ChangeStateListener : ::wl_listener { + MockIndicatorCompositor *parent; + }; + NewSurfaceListener mChangeStateListener; + struct ChangeOpacityModeListener : ::wl_listener { + MockIndicatorCompositor *parent; + }; + NewSurfaceListener mChangeOpacityModeListener; + struct ChangeVisibleTypeListener : ::wl_listener { + MockIndicatorCompositor *parent; + }; + NewSurfaceListener mChangeVisibleTypeListener; +}; + +class MockIndicatorClient : public MockClient +{ +public: + MockIndicatorClient() + : bFlickEvent(false), + compositor_res(nullptr), + tizen_indicator(nullptr) + {} + MockIndicatorClient(const struct wl_registry_listener *listener) + : MockClient(listener, this) + { + ds_inf("%s", __func__); + + bFlickEvent = false; + } + ~MockIndicatorClient() + { + ds_inf("%s", __func__); + } + + void SetWlCompositor(struct wl_compositor *global_res) + { + ds_inf("%s", __func__); + + compositor_res = global_res; + } + + struct wl_compositor *GetWlCompositor() + { + ds_inf("%s", __func__); + + return compositor_res; + } + + void SetTizenIndicator(struct tizen_indicator *global_res) + { + ds_inf("%s", __func__); + + tizen_indicator = global_res; + } + + struct tizen_indicator *GetTizenIndicator() + { + ds_inf("%s", __func__); + + return tizen_indicator; + } + +public: + bool bFlickEvent; + +private: + struct wl_compositor *compositor_res; + struct tizen_indicator *tizen_indicator; +}; + +static void +client_tizen_indicator_cb_flick(void *data, struct tizen_indicator *indicator, + struct wl_surface *surface, int32_t type) +{ + ds_inf("%s", __func__); + + MockIndicatorClient *client = static_cast(data); + + client->bFlickEvent = true; +} + +static const struct tizen_indicator_listener indicator_cb_listener = { + .flick = client_tizen_indicator_cb_flick +}; + +static void +client_registry_cb_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + ds_inf("%s", __func__); + + MockIndicatorClient *client = static_cast(data); + struct wl_compositor *compositor_res; + struct tizen_indicator *tizen_indicator; + + if (!strcmp(interface, "wl_compositor")) { + compositor_res = (struct wl_compositor *)wl_registry_bind(registry, + name, &wl_compositor_interface, 1); + if (compositor_res == nullptr) { + ds_err("wl_registry_bind() failed. wl_compositor resource."); + return; + } + client->SetWlCompositor(compositor_res); + } else if (!strcmp(interface, "tizen_indicator")) { + tizen_indicator = (struct tizen_indicator *)wl_registry_bind(registry, + name, &tizen_indicator_interface, 1); + if (tizen_indicator == nullptr) { + ds_err("wl_registry_bind() failed. tizen_indicator resource."); + return; + } + client->SetTizenIndicator(tizen_indicator); + + tizen_indicator_add_listener(tizen_indicator, &indicator_cb_listener, + client); + } +} + +static void +client_registry_cb_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ + ds_inf("%s", __func__); + + MockIndicatorClient *client = static_cast(data); + struct wl_compositor *compositor_res = client->GetWlCompositor(); + struct tizen_indicator *indicator_res = client->GetTizenIndicator(); + + tizen_indicator_destroy(indicator_res); + wl_compositor_destroy(compositor_res); +} + +static const struct wl_registry_listener registry_listener = { + .global = client_registry_cb_global, + .global_remove = client_registry_cb_global_remove +}; + +class IndicatorTest : public ::testing::Test +{ +public: + void SetUp(void) override; + void TearDown(void) override; + + MockIndicatorCompositor *comp; + MockIndicatorClient *client; + struct wl_compositor *compositor_res; + struct tizen_indicator *indicator_res; + struct wl_surface *surface_res; +}; + +void +IndicatorTest::SetUp(void) +{ + //ds_log_init(DS_DBG, NULL); + + ds_inf("%s", __func__); + + comp = new MockIndicatorCompositor(); + client = new MockIndicatorClient(®istry_listener); + compositor_res = client->GetWlCompositor(); + indicator_res = client->GetTizenIndicator(); + surface_res = wl_compositor_create_surface(compositor_res); + + client->RoundTrip(); +} + +void +IndicatorTest::TearDown(void) +{ + ds_inf("%s", __func__); + + wl_surface_destroy(surface_res); + client->RoundTrip(); + EXPECT_TRUE(comp->bSurfaceDestroyed); + + delete client; + delete comp; +} + + +TEST_F(IndicatorTest, Create_P) +{ + EXPECT_TRUE(true); +} + +TEST_F(IndicatorTest, Req_TizenIndicatorStateOn) +{ + tizen_indicator_set_state(indicator_res, surface_res, + TIZEN_INDICATOR_STATE_ON); + client->RoundTrip(); + EXPECT_TRUE(comp->bStateOn); + EXPECT_FALSE(comp->bStateOff); +} + +TEST_F(IndicatorTest, Req_TizenIndicatorStateOff) +{ + tizen_indicator_set_state(indicator_res, surface_res, + TIZEN_INDICATOR_STATE_OFF); + client->RoundTrip(); + EXPECT_FALSE(comp->bStateOn); + EXPECT_TRUE(comp->bStateOff); +} + +TEST_F(IndicatorTest, Req_TizenIndicatorOpacityModeOpaque) +{ + tizen_indicator_set_opacity_mode(indicator_res, surface_res, + TIZEN_INDICATOR_OPACITY_MODE_OPAQUE); + client->RoundTrip(); + EXPECT_TRUE(comp->bOpacityModeOpque); + EXPECT_FALSE(comp->bOpacityModeTranslucent); + EXPECT_FALSE(comp->bOpacityModeTransparent); + EXPECT_FALSE(comp->bOpacityModeBgTransparent); +} + +TEST_F(IndicatorTest, Req_TizenIndicatorOpacityModeTranslucent) +{ + tizen_indicator_set_opacity_mode(indicator_res, surface_res, + TIZEN_INDICATOR_OPACITY_MODE_TRANSLUCENT); + client->RoundTrip(); + EXPECT_FALSE(comp->bOpacityModeOpque); + EXPECT_TRUE(comp->bOpacityModeTranslucent); + EXPECT_FALSE(comp->bOpacityModeTransparent); + EXPECT_FALSE(comp->bOpacityModeBgTransparent); +} + +TEST_F(IndicatorTest, Req_TizenIndicatorOpacityModeTransparent) +{ + tizen_indicator_set_opacity_mode(indicator_res, surface_res, + TIZEN_INDICATOR_OPACITY_MODE_TRANSPARENT); + client->RoundTrip(); + EXPECT_FALSE(comp->bOpacityModeOpque); + EXPECT_FALSE(comp->bOpacityModeTranslucent); + EXPECT_TRUE(comp->bOpacityModeTransparent); + EXPECT_FALSE(comp->bOpacityModeBgTransparent); +} + +TEST_F(IndicatorTest, Req_TizenIndicatorOpacityModeBgTransparent) +{ + tizen_indicator_set_opacity_mode(indicator_res, surface_res, + TIZEN_INDICATOR_OPACITY_MODE_BG_TRANSPARENT); + client->RoundTrip(); + EXPECT_FALSE(comp->bOpacityModeOpque); + EXPECT_FALSE(comp->bOpacityModeTranslucent); + EXPECT_FALSE(comp->bOpacityModeTransparent); + EXPECT_TRUE(comp->bOpacityModeBgTransparent); +} + +TEST_F(IndicatorTest, Req_TizenIndicatorVisibleTypeHidden) +{ + tizen_indicator_set_visible_type(indicator_res, surface_res, + TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN); + client->RoundTrip(); + EXPECT_TRUE(comp->bVisibleTypeHidden); + EXPECT_FALSE(comp->bVisibleTypeShown); +} + +TEST_F(IndicatorTest, Req_TizenIndicatorVisibleTypeShown) +{ + tizen_indicator_set_visible_type(indicator_res, surface_res, + TIZEN_INDICATOR_VISIBLE_TYPE_SHOWN); + client->RoundTrip(); + EXPECT_FALSE(comp->bVisibleTypeHidden); + EXPECT_TRUE(comp->bVisibleTypeShown); +} + +TEST_F(IndicatorTest, Ev_TizenIndicatorFlick) +{ + tizen_indicator_set_state(indicator_res, surface_res, + TIZEN_INDICATOR_STATE_ON); + client->RoundTrip(); + EXPECT_TRUE(comp->bStateOn); + + comp->SendFlick(); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->bFlickEvent); +} -- 2.7.4 From d63e154e2c3427e6d0f1f4509eaddd99638bff38 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Wed, 20 Jul 2022 16:11:22 +0900 Subject: [PATCH 13/16] impelement libds-tizen-clipboard This is the server implementation for tizen_clipboard protocol. Change-Id: Idb03da717fd867bb9fd31e8bf9878e1006553ada --- include/libds-tizen/clipboard.h | 50 ++++++ packaging/libds-tizen.spec | 29 ++++ src/clipboard/clipboard.c | 366 ++++++++++++++++++++++++++++++++++++++++ src/clipboard/meson.build | 29 ++++ src/meson.build | 1 + 5 files changed, 475 insertions(+) create mode 100644 include/libds-tizen/clipboard.h create mode 100644 src/clipboard/clipboard.c create mode 100644 src/clipboard/meson.build diff --git a/include/libds-tizen/clipboard.h b/include/libds-tizen/clipboard.h new file mode 100644 index 0000000..697c9e7 --- /dev/null +++ b/include/libds-tizen/clipboard.h @@ -0,0 +1,50 @@ +#ifndef LIBDS_TIZEN_CLIPBOARD_H +#define LIBDS_TIZEN_CLIPBOARD_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tizen_clipboard; +struct ds_tizen_clipboard_client; + +struct ds_tizen_clipboard * +ds_tizen_clipboard_create(struct wl_display *display); + +void +ds_tizen_clipboard_add_destroy_listener(struct ds_tizen_clipboard *clipboard, + struct wl_listener *listener); + +void +ds_tizen_clipboard_add_show_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener); + +void +ds_tizen_clipboard_add_hide_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener); + +void +ds_tizen_clipboard_add_set_data_only_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener); + +uint32_t +ds_tizen_clipboard_client_get_data_only( + struct ds_tizen_clipboard_client *client); + +void +ds_tizen_clipboard_send_data_selected(struct ds_tizen_clipboard *clipboard, + struct ds_surface *surface); + +void +ds_tizen_clipboard_client_send_allowed_data_only( + struct ds_tizen_clipboard_client *client, uint32_t allowed); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 8935d5d..bb5c681 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -137,6 +137,21 @@ Group: Development/Libraries %description indicator-devel Development package for tizen indicator +## libds-tizen-clipboard +%package clipboard +Summary: Library for tizen clipboard +Group: Development/Libraries + +%description clipboard +Library for tizen clipboard + +%package clipboard-devel +Summary: Development package for tizen clipboard +Group: Development/Libraries + +%description clipboard-devel +Development package for tizen clipboard + %prep %setup -q cp %{SOURCE1001} . @@ -262,3 +277,17 @@ ninja -C builddir install %{_libdir}/pkgconfig/libds-tizen-indicator.pc %{_libdir}/libds-tizen-indicator.so %{_bindir}/libds-tizen-indicator-tests + +%files clipboard +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_libdir}/libds-tizen-clipboard.so.* + +%files clipboard-devel +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_includedir}/libds-tizen/clipboard.h +%{_libdir}/pkgconfig/libds-tizen-clipboard.pc +%{_libdir}/libds-tizen-clipboard.so diff --git a/src/clipboard/clipboard.c b/src/clipboard/clipboard.c new file mode 100644 index 0000000..bfa9595 --- /dev/null +++ b/src/clipboard/clipboard.c @@ -0,0 +1,366 @@ +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "libds-tizen/clipboard.h" + +#define TIZEN_CLIPBOARD_VERSION 2 + +struct ds_tizen_clipboard +{ + struct wl_global *global; + + struct wl_list clients; + + struct wl_listener destroy; + + struct { + struct wl_signal destroy; + struct wl_signal show; + struct wl_signal hide; + struct wl_signal set_data_only; + } events; +}; + +struct ds_tizen_clipboard_client +{ + struct ds_tizen_clipboard *clipboard; + + struct wl_resource *resource; + struct wl_client *wl_client; + + struct wl_list infos; + + uint32_t data_only; + + struct wl_list link; // ds_tizen_clipboard::clients +}; + +struct ds_tizen_clipboard_info +{ + struct ds_surface *surface; + + struct wl_list link; // ds_tizen_clipboard_client::infos +}; + +static void clipboard_handle_display_destroy(struct wl_listener *listener, + void *data); + +static void clipboard_bind(struct wl_client *wl_client, void *data, + uint32_t version, uint32_t id); + +static struct ds_tizen_clipboard_client *tizen_clipboard_find_client( + struct ds_tizen_clipboard *clipboard, + struct ds_surface *surface); + +static struct ds_tizen_clipboard_info *tizen_clipboard_client_find_info( + struct ds_tizen_clipboard_client *client, + struct ds_surface *surface); + +static struct ds_tizen_clipboard_info *tizen_clipboard_client_get_info( + struct ds_tizen_clipboard_client *client, + struct ds_surface *surface); + +WL_EXPORT struct ds_tizen_clipboard * +ds_tizen_clipboard_create(struct wl_display *display) +{ + struct ds_tizen_clipboard *clipboard; + + clipboard = calloc(1, sizeof *clipboard); + if (!clipboard) { + ds_err("calloc() failed."); + return NULL; + } + + clipboard->global = wl_global_create(display, &tizen_clipboard_interface, + TIZEN_CLIPBOARD_VERSION, clipboard, clipboard_bind); + if (!clipboard->global) { + ds_err("wl_global_create() failed. tizen_clipboard_interface"); + free(clipboard); + return NULL; + } + + wl_list_init(&clipboard->clients); + + clipboard->destroy.notify = clipboard_handle_display_destroy; + wl_display_add_destroy_listener(display, &clipboard->destroy); + + wl_signal_init(&clipboard->events.destroy); + wl_signal_init(&clipboard->events.show); + wl_signal_init(&clipboard->events.hide); + wl_signal_init(&clipboard->events.set_data_only); + + ds_inf("Global created: tizen_clipboard(%p)", clipboard); + + return clipboard; +} + +WL_EXPORT void +ds_tizen_clipboard_add_destroy_listener(struct ds_tizen_clipboard *clipboard, + struct wl_listener *listener) +{ + wl_signal_add(&clipboard->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_clipboard_add_show_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener) +{ + wl_signal_add(&clipboard->events.show, listener); +} + +WL_EXPORT void +ds_tizen_clipboard_add_hide_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener) +{ + wl_signal_add(&clipboard->events.hide, listener); +} + +WL_EXPORT void +ds_tizen_clipboard_add_set_data_only_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener) +{ + wl_signal_add(&clipboard->events.set_data_only, listener); +} + +WL_EXPORT uint32_t +ds_tizen_clipboard_client_get_data_only( + struct ds_tizen_clipboard_client *client) +{ + return client->data_only; +} + +WL_EXPORT void +ds_tizen_clipboard_send_data_selected(struct ds_tizen_clipboard *clipboard, + struct ds_surface *surface) +{ + struct ds_tizen_clipboard_client *client; + + client = tizen_clipboard_find_client(clipboard, surface); + if (client == NULL) { + ds_err("tizen_clipboard: tizen_clipboard_find_client() failed."); + return; + } + + tizen_clipboard_send_data_selected(client->resource, + ds_surface_get_wl_resource(surface)); +} + +WL_EXPORT void +ds_tizen_clipboard_client_send_allowed_data_only( + struct ds_tizen_clipboard_client *client, uint32_t allowed) +{ + tizen_clipboard_send_allowed_data_only(client->resource, allowed); +} + +static struct ds_tizen_clipboard_client * +tizen_clipboard_find_client(struct ds_tizen_clipboard *clipboard, + struct ds_surface *surface) +{ + struct ds_tizen_clipboard_info *info; + struct ds_tizen_clipboard_client *client; + + wl_list_for_each(client, &clipboard->clients, link) { + info = tizen_clipboard_client_find_info(client, surface); + if (info != NULL) + return client; + } + + return NULL; +} + +static struct ds_tizen_clipboard_info * +tizen_clipboard_client_find_info(struct ds_tizen_clipboard_client *client, + struct ds_surface *surface) +{ + struct ds_tizen_clipboard_info *info; + + wl_list_for_each(info, &client->infos, link) { + if (surface == info->surface) + return info; + } + + return NULL; +} + +static struct ds_tizen_clipboard_info * +tizen_clipboard_client_get_info(struct ds_tizen_clipboard_client *client, + struct ds_surface *surface) +{ + struct ds_tizen_clipboard_info *info; + + info = tizen_clipboard_client_find_info(client, surface); + if (info) + return info; + + info = calloc(1, sizeof *info); + if (info == NULL) { + ds_err("calloc() failed. tizen_clipboard"); + return NULL; + } + + info->surface = surface; + + wl_list_insert(&client->infos, &info->link); + + return info; +} + +static void +clipboard_handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tizen_clipboard *clipboard; + + clipboard = wl_container_of(listener, clipboard, destroy); + + ds_inf("Global destroy: clipboard(%p)", clipboard); + + wl_signal_emit(&clipboard->events.destroy, clipboard); + wl_list_remove(&clipboard->destroy.link); + wl_global_destroy(clipboard->global); + free(clipboard); +} + +static void +clipboard_handle_destroy(struct wl_client *wl_client, + struct wl_resource *resource) +{ + struct ds_tizen_clipboard_client *client; + + client = wl_resource_get_user_data(resource); + + if (!wl_list_empty(&client->infos)) { + ds_err("tizen_clipboard was destroyed before children"); + return; + } + + wl_resource_destroy(resource); +} + +static void +clipboard_handle_show(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_clipboard_client *client; + struct ds_tizen_clipboard_info *info; + struct ds_surface *surface; + + ds_inf("tizen_clipboard: show"); + + client = wl_resource_get_user_data(resource); + surface = ds_surface_from_resource(surface_resource); + + info = tizen_clipboard_client_get_info(client, surface); + if (info == NULL) { + ds_err("tizen_clipboard_client_get_info() failed. tizen_clipboard"); + wl_client_post_no_memory(wl_client); + return; + } + + wl_signal_emit(&client->clipboard->events.show, surface); +} + +static void +clipboard_handle_hide(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_clipboard_client *client; + struct ds_tizen_clipboard_info *info; + struct ds_surface *surface; + + ds_inf("tizen_clipboard: hide"); + + client = wl_resource_get_user_data(resource); + surface = ds_surface_from_resource(surface_resource); + + info = tizen_clipboard_client_get_info(client, surface); + if (info == NULL) { + ds_err("tizen_clipboard_client_get_info() failed. tizen_clipboard"); + wl_client_post_no_memory(wl_client); + return; + } + + wl_signal_emit(&client->clipboard->events.hide, surface); +} + +static void +clipboard_handle_set_data_only(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t set) +{ + struct ds_tizen_clipboard_client *client; + + ds_inf("tizen_clipboard: set_data_only. set(%d)", set); + + client = wl_resource_get_user_data(resource); + client->data_only = set; + + wl_signal_emit(&client->clipboard->events.set_data_only, client); +} + +static const struct tizen_clipboard_interface clipboard_impl = +{ + clipboard_handle_destroy, + clipboard_handle_show, + clipboard_handle_hide, + clipboard_handle_set_data_only, +}; + +static void +_tizen_clipboard_client_handle_destroy(struct wl_resource *resource) +{ + struct ds_tizen_clipboard_client *client; + struct ds_tizen_clipboard_info *info, *tmp; + + client = wl_resource_get_user_data(resource); + + ds_inf("_tizen_clipboard_client_handle_destroy (client:%p)", client); + + wl_list_for_each_safe(info, tmp, &client->infos, link) { + wl_list_remove(&info->link); + free(info); + } + + wl_list_remove(&client->link); + free(client); +} + +static void +clipboard_bind(struct wl_client *wl_client, void *data, uint32_t version, + uint32_t id) +{ + struct ds_tizen_clipboard *clipboard = data; + struct ds_tizen_clipboard_client *client; + + client = calloc(1, sizeof *client); + if (client == NULL) { + ds_err("calloc() failed. tizen_clipboard"); + wl_client_post_no_memory(wl_client); + return; + } + + ds_inf("tizen_clipboard_client binds. (client:%p)", client); + + client->clipboard = clipboard; + client->wl_client = wl_client; + + wl_list_init(&client->infos); + + client->resource = wl_resource_create(wl_client, &tizen_clipboard_interface, + MIN(version, TIZEN_CLIPBOARD_VERSION), id); + + if (client->resource == NULL) { + ds_err("tizen_clipboard : wl_resource_create() failed."); + free(client); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(client->resource, &clipboard_impl, client, + _tizen_clipboard_client_handle_destroy); + + wl_list_insert(&clipboard->clients, &client->link); +} diff --git a/src/clipboard/meson.build b/src/clipboard/meson.build new file mode 100644 index 0000000..2889c22 --- /dev/null +++ b/src/clipboard/meson.build @@ -0,0 +1,29 @@ +libds_tizen_clipboard_files = [ + 'clipboard.c', +] + +libds_tizen_clipboard_deps = [ + deps_libds_tizen, + dependency('tizen-extension-server', required: true), +] + +lib_libds_tizen_clipboard = shared_library('ds-tizen-clipboard', libds_tizen_clipboard_files, + dependencies: libds_tizen_clipboard_deps, + include_directories: [ common_inc, include_directories('.'), include_directories('..') ], + version: meson.project_version(), + install: true +) + +deps_libds_tizen_clipboard = declare_dependency( + link_with: lib_libds_tizen_clipboard, + dependencies: libds_tizen_clipboard_deps, + include_directories: [ common_inc, include_directories('.') ], +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(lib_libds_tizen_clipboard, + version: meson.project_version(), + filebase: 'libds-tizen-clipboard', + name: 'libds-tizen-clipboard', + description: 'tizen clipboard extension of libds-tizen for tizen platform', +) diff --git a/src/meson.build b/src/meson.build index 09a7f1a..73c169c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -34,3 +34,4 @@ subdir('keyrouter') subdir('input_devicemgr') subdir('dpms') subdir('indicator') +subdir('clipboard') -- 2.7.4 From 80dd61f50c67535a2093118e8c9102063204ea7f Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Wed, 20 Jul 2022 17:13:47 +0900 Subject: [PATCH 14/16] add test cases for ds_tizen_clipboard These are unit testcases. Change-Id: I17d0d392c3c8af7041fe93752b5facb6be7e41b5 --- packaging/libds-tizen.spec | 1 + tests/meson.build | 20 ++ tests/tc_clipboard.cpp | 457 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 478 insertions(+) create mode 100644 tests/tc_clipboard.cpp diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index bb5c681..16e6ce7 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -291,3 +291,4 @@ ninja -C builddir install %{_includedir}/libds-tizen/clipboard.h %{_libdir}/pkgconfig/libds-tizen-clipboard.pc %{_libdir}/libds-tizen-clipboard.so +%{_bindir}/libds-tizen-clipboard-tests diff --git a/tests/meson.build b/tests/meson.build index 8cff406..eb8d221 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -45,3 +45,23 @@ executable('libds-tizen-indicator-tests', install_dir: libds_tizen_bindir, install : true ) + +## clipboard tests +tc_clipboard_files = [ + 'tc_main.cpp', + 'tc_clipboard.cpp', +] + +executable('libds-tizen-clipboard-tests', + [ + tc_mock_files, + tc_clipboard_files + ], + dependencies: [ + deps_test_common, + deps_libds_tizen_clipboard, + dependency('libdrm', required: true), + ], + install_dir: libds_tizen_bindir, + install : true +) diff --git a/tests/tc_clipboard.cpp b/tests/tc_clipboard.cpp new file mode 100644 index 0000000..710495a --- /dev/null +++ b/tests/tc_clipboard.cpp @@ -0,0 +1,457 @@ +#include "tc_main.h" +#include "mockclient.h" +#include "mockcompositor.h" +#include +#include + +#define TIZEN_CLIPBOARD_VERSION 2 + +class MockClipboardCompositor : public MockCompositor +{ +public: + MockClipboardCompositor() + : MockCompositor(&MockClipboardCompositor::TestSetup, this) + { + ds_inf("%s : this(%p)", __func__, this); + + // initialize the flags to check + bSurfaceDestroyed = false; + + bDestroyed = false; + bShow = false; + bHide = false; + mSetDataOnly = 0; + + mAllowed = 0; + } + + ~MockClipboardCompositor() + { + ds_inf("%s : this(%p)", __func__, this); + } + + static void TestSetup(void *data) + { + MockClipboardCompositor *mockComp = + static_cast(data); + Compositor *comp = mockComp->compositor; + + ds_inf("%s: mockComp(%p)", __func__, mockComp); + + // new surface listener + mockComp->mNewSurfaceListener.notify = + MockClipboardCompositor::NewSurfaceCallback; + mockComp->mNewSurfaceListener.parent = mockComp; + ds_compositor_add_new_surface_listener(comp->compositor, + &mockComp->mNewSurfaceListener); + + mockComp->mClipboard = ds_tizen_clipboard_create(comp->display); + + // destroy listener + mockComp->mDestroyListener.notify = + MockClipboardCompositor::DestroyCallback; + mockComp->mDestroyListener.parent = mockComp; + ds_tizen_clipboard_add_destroy_listener(mockComp->mClipboard, + &mockComp->mDestroyListener); + + // show listener + mockComp->mShowListener.notify = + MockClipboardCompositor::ShowCallback; + mockComp->mShowListener.parent = mockComp; + ds_tizen_clipboard_add_show_listener(mockComp->mClipboard, + &mockComp->mShowListener); + + // hide listener + mockComp->mHideListener.notify = + MockClipboardCompositor::HideCallback; + mockComp->mHideListener.parent = mockComp; + ds_tizen_clipboard_add_hide_listener( + mockComp->mClipboard, + &mockComp->mHideListener); + + // set_data_only listener + mockComp->mSetDataOnlyListener.notify = + MockClipboardCompositor::SetDataOnlyCallback; + mockComp->mSetDataOnlyListener.parent = mockComp; + ds_tizen_clipboard_add_set_data_only_listener( + mockComp->mClipboard, + &mockComp->mSetDataOnlyListener); + } + + static void NewSurfaceCallback(struct wl_listener *listener, void *data) + { + MockClipboardCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + mockComp->mSurface = surface; + + // del surface listener + mockComp->mDelSurfaceListener.notify = + MockClipboardCompositor::DelSurfaceCallback; + mockComp->mDelSurfaceListener.parent = mockComp; + ds_surface_add_destroy_listener(surface, + &mockComp->mDelSurfaceListener); + } + + static void DelSurfaceCallback(struct wl_listener *listener, void *data) + { + MockClipboardCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + if (ds_surface_get_wl_resource(mockComp->mSurface) == + ds_surface_get_wl_resource(surface)) { + ds_inf("%s: surface is deleted.", __func__); + mockComp->bSurfaceDestroyed = true; + } + } + + static void DestroyCallback(struct wl_listener *listener, void *data) + { + ds_inf("%s", __func__); + + MockClipboardCompositor *mockComp = + reinterpret_cast(listener)->parent; + + mockComp->bDestroyed = true; + } + + static void ShowCallback(struct wl_listener *listener, void *data) + { + ds_inf("%s", __func__); + + MockClipboardCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + mockComp->bShow = true; + } + + static void HideCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockClipboardCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + mockComp->bHide = true; + } + + static void SetDataOnlyCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockClipboardCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_clipboard_client *client = + static_cast(data); + + ds_inf("%s: mockComp(%p), client(%p)", __func__, mockComp, client); + + mockComp->mSetDataOnly = + ds_tizen_clipboard_client_get_data_only(client); + + ds_tizen_clipboard_client_send_allowed_data_only(client, + mockComp->mAllowed); + } + + void SendDataSelected() + { + ds_inf("%s", __func__); + + ds_tizen_clipboard_send_data_selected(mClipboard, mSurface); + } + + void SetAllowedDataOnly(uint32_t allowed) + { + ds_inf("%s", __func__); + + mAllowed = allowed; + } + +public: + bool bSurfaceDestroyed; + bool bDestroyed; + bool bShow; + bool bHide; + uint32_t mSetDataOnly; + + uint32_t mAllowed; + +private: + struct ds_surface *mSurface; + struct NewSurfaceListener : ::wl_listener { + MockClipboardCompositor *parent; + }; + NewSurfaceListener mNewSurfaceListener; + struct DelSurfaceListener : ::wl_listener { + MockClipboardCompositor *parent; + }; + DelSurfaceListener mDelSurfaceListener; + + struct ds_tizen_clipboard *mClipboard; + struct DestroyListener : ::wl_listener { + MockClipboardCompositor *parent; + }; + DestroyListener mDestroyListener; + struct ShowListener : ::wl_listener { + MockClipboardCompositor *parent; + }; + ShowListener mShowListener; + struct HideListener : ::wl_listener { + MockClipboardCompositor *parent; + }; + HideListener mHideListener; + struct SetDataOnlyListener : ::wl_listener { + MockClipboardCompositor *parent; + }; + SetDataOnlyListener mSetDataOnlyListener; +}; + +class MockClipboardClient : public MockClient +{ +public: + MockClipboardClient() + : bDataSelectedEvent(false), + mAllowedDataOnly(0), + compositor_res(nullptr), + tizen_clipboard(nullptr) + {} + MockClipboardClient(const struct wl_registry_listener *listener) + : MockClient(listener, this) + { + ds_inf("%s", __func__); + + bDataSelectedEvent = false; + mAllowedDataOnly = 0; + } + ~MockClipboardClient() + { + ds_inf("%s", __func__); + } + + void SetWlCompositor(struct wl_compositor *global_res) + { + ds_inf("%s", __func__); + + compositor_res = global_res; + } + + struct wl_compositor *GetWlCompositor() + { + ds_inf("%s", __func__); + + return compositor_res; + } + + void SetTizenClipboard(struct tizen_clipboard *global_res) + { + ds_inf("%s", __func__); + + tizen_clipboard = global_res; + } + + struct tizen_clipboard *GetTizenClipboard() + { + ds_inf("%s", __func__); + + return tizen_clipboard; + } + +public: + bool bDataSelectedEvent; + uint32_t mAllowedDataOnly; + +private: + struct wl_compositor *compositor_res; + struct tizen_clipboard *tizen_clipboard; +}; + +static void +client_tizen_clipboard_cb_data_selected(void *data, + struct tizen_clipboard *clipboard, struct wl_surface *surface) +{ + ds_inf("%s", __func__); + + MockClipboardClient *client = static_cast(data); + + client->bDataSelectedEvent = true; +} + +static void +client_tizen_clipboard_cb_allowed_data_only(void *data, + struct tizen_clipboard *clipboard, uint32_t allowed) +{ + ds_inf("%s", __func__); + + MockClipboardClient *client = static_cast(data); + + client->mAllowedDataOnly = allowed; +} + +static const struct tizen_clipboard_listener clipboard_cb_listener = { + .data_selected = client_tizen_clipboard_cb_data_selected, + .allowed_data_only = client_tizen_clipboard_cb_allowed_data_only +}; + +static void +client_registry_cb_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + ds_inf("%s", __func__); + + MockClipboardClient *client = static_cast(data); + struct wl_compositor *compositor_res; + struct tizen_clipboard *tizen_clipboard; + + if (!strcmp(interface, "wl_compositor")) { + compositor_res = (struct wl_compositor *)wl_registry_bind(registry, + name, &wl_compositor_interface, 1); + if (compositor_res == nullptr) { + ds_err("wl_registry_bind() failed. wl_compositor resource."); + return; + } + client->SetWlCompositor(compositor_res); + } else if (!strcmp(interface, "tizen_clipboard")) { + tizen_clipboard = (struct tizen_clipboard *)wl_registry_bind(registry, + name, &tizen_clipboard_interface, TIZEN_CLIPBOARD_VERSION); + if (tizen_clipboard == nullptr) { + ds_err("wl_registry_bind() failed. tizen_clipboard resource."); + return; + } + client->SetTizenClipboard(tizen_clipboard); + + tizen_clipboard_add_listener(tizen_clipboard, &clipboard_cb_listener, + client); + } +} + +static void +client_registry_cb_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ + ds_inf("%s", __func__); + + MockClipboardClient *client = static_cast(data); + struct wl_compositor *compositor_res = client->GetWlCompositor(); + struct tizen_clipboard *clipboard_res = client->GetTizenClipboard(); + + tizen_clipboard_destroy(clipboard_res); + wl_compositor_destroy(compositor_res); +} + +static const struct wl_registry_listener registry_listener = { + .global = client_registry_cb_global, + .global_remove = client_registry_cb_global_remove +}; + +class ClipboardTest : public ::testing::Test +{ +public: + void SetUp(void) override; + void TearDown(void) override; + + MockClipboardCompositor *comp; + MockClipboardClient *client; + struct wl_compositor *compositor_res; + struct tizen_clipboard *clipboard_res; + struct wl_surface *surface_res; +}; + +void +ClipboardTest::SetUp(void) +{ + //ds_log_init(DS_DBG, NULL); + + ds_inf("%s", __func__); + + comp = new MockClipboardCompositor(); + client = new MockClipboardClient(®istry_listener); + compositor_res = client->GetWlCompositor(); + clipboard_res = client->GetTizenClipboard(); + surface_res = wl_compositor_create_surface(compositor_res); + + client->RoundTrip(); +} + +void +ClipboardTest::TearDown(void) +{ + ds_inf("%s", __func__); + + wl_surface_destroy(surface_res); + client->RoundTrip(); + EXPECT_TRUE(comp->bSurfaceDestroyed); + + delete client; + delete comp; +} + +TEST_F(ClipboardTest, Create_P) +{ + EXPECT_TRUE(true); +} + +TEST_F(ClipboardTest, Req_TizenClipboardShow) +{ + tizen_clipboard_show(clipboard_res, surface_res); + client->RoundTrip(); + EXPECT_TRUE(comp->bShow); + EXPECT_FALSE(comp->bHide); +} + +TEST_F(ClipboardTest, Req_TizenClipboardHide) +{ + tizen_clipboard_hide(clipboard_res, surface_res); + client->RoundTrip(); + EXPECT_FALSE(comp->bShow); + EXPECT_TRUE(comp->bHide); +} + +TEST_F(ClipboardTest, Req_TizenClipboardSetDataOnly) +{ + tizen_clipboard_set_data_only(clipboard_res, 1); + client->RoundTrip(); + EXPECT_TRUE(comp->mSetDataOnly == 1); +} + +TEST_F(ClipboardTest, Ev_TizenClipboardDataSelected) +{ + tizen_clipboard_show(clipboard_res, surface_res); + client->RoundTrip(); + EXPECT_TRUE(comp->bShow); + + comp->SendDataSelected(); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->bDataSelectedEvent); +} + +TEST_F(ClipboardTest, Ev_TizenClipboardAllowedDataOnly) +{ + // set the value of allowed to be 1 at compositor + comp->SetAllowedDataOnly(1); + + // send a client's request + tizen_clipboard_set_data_only(clipboard_res, 1); + client->RoundTrip(); + EXPECT_TRUE(comp->mSetDataOnly); + + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->mAllowedDataOnly == 1); +} -- 2.7.4 From e9c16b49a848b2f7ee81c38907d85da975916a3e Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Thu, 21 Jul 2022 08:27:35 +0900 Subject: [PATCH 15/16] fix the typo Change-Id: I8a9325b59e7f6cf4e372554bde71386ca9d15514 --- tests/tc_indicator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/tc_indicator.cpp b/tests/tc_indicator.cpp index c589ef3..7585496 100644 --- a/tests/tc_indicator.cpp +++ b/tests/tc_indicator.cpp @@ -219,25 +219,25 @@ private: struct DelSurfaceListener : ::wl_listener { MockIndicatorCompositor *parent; }; - NewSurfaceListener mDelSurfaceListener; + DelSurfaceListener mDelSurfaceListener; struct ds_tizen_indicator *mIndicator; struct DestroyListener : ::wl_listener { MockIndicatorCompositor *parent; }; - NewSurfaceListener mDestroyListener; + DestroyListener mDestroyListener; struct ChangeStateListener : ::wl_listener { MockIndicatorCompositor *parent; }; - NewSurfaceListener mChangeStateListener; + ChangeStateListener mChangeStateListener; struct ChangeOpacityModeListener : ::wl_listener { MockIndicatorCompositor *parent; }; - NewSurfaceListener mChangeOpacityModeListener; + ChangeOpacityModeListener mChangeOpacityModeListener; struct ChangeVisibleTypeListener : ::wl_listener { MockIndicatorCompositor *parent; }; - NewSurfaceListener mChangeVisibleTypeListener; + ChangeVisibleTypeListener mChangeVisibleTypeListener; }; class MockIndicatorClient : public MockClient -- 2.7.4 From 6413a0a4cdd781569f759eaf5f3c8ab6b586d81c Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Thu, 21 Jul 2022 08:30:20 +0900 Subject: [PATCH 16/16] indicator: create and bind global resource with version info Change-Id: Iaa20162c9a2d6a918e72e5071f7f7d809902f33e --- src/indicator/indicator.c | 2 +- tests/tc_indicator.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/indicator/indicator.c b/src/indicator/indicator.c index 23f0e9f..b08dae5 100644 --- a/src/indicator/indicator.c +++ b/src/indicator/indicator.c @@ -83,7 +83,7 @@ ds_tizen_indicator_create(struct wl_display *display) } indicator->global = wl_global_create(display, &tizen_indicator_interface, - 1, indicator, indicator_bind); + TIZEN_INDICATOR_VERSION, indicator, indicator_bind); if (!indicator->global) { ds_err("wl_global_create() failed. tizen_indicator_interface"); free(indicator); diff --git a/tests/tc_indicator.cpp b/tests/tc_indicator.cpp index 7585496..837aa3a 100644 --- a/tests/tc_indicator.cpp +++ b/tests/tc_indicator.cpp @@ -4,6 +4,7 @@ #include #include +#define TIZEN_INDICATOR_VERSION 1 class MockIndicatorCompositor : public MockCompositor { public: @@ -331,7 +332,7 @@ client_registry_cb_global(void *data, struct wl_registry *registry, client->SetWlCompositor(compositor_res); } else if (!strcmp(interface, "tizen_indicator")) { tizen_indicator = (struct tizen_indicator *)wl_registry_bind(registry, - name, &tizen_indicator_interface, 1); + name, &tizen_indicator_interface, TIZEN_INDICATOR_VERSION); if (tizen_indicator == nullptr) { ds_err("wl_registry_bind() failed. tizen_indicator resource."); return; -- 2.7.4