From 5af8f0152be3f2aaf5543e8c3098d1e6014c2638 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Wed, 8 Jun 2022 16:25:42 +0900 Subject: [PATCH 01/16] keyrouter: Properly test for allocation failure Instead of testing the return of the function just called, it was testing something already checked earlier. Change-Id: Ibaa7884360afaa195d843bc90588e3af85caf0d0 --- src/keyrouter/keyrouter_grab.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keyrouter/keyrouter_grab.c b/src/keyrouter/keyrouter_grab.c index 5009985..6af0c85 100644 --- a/src/keyrouter/keyrouter_grab.c +++ b/src/keyrouter/keyrouter_grab.c @@ -300,7 +300,7 @@ keyrouter_grab_create(void) /* FIXME: Who defined max keycode? */ keyrouter_grab->hard_keys = calloc(KEYROUTER_MAX_KEYS, sizeof(struct ds_tizen_keyrouter_grabbed)); - if (keyrouter_grab == NULL) { + if (keyrouter_grab->hard_keys == NULL) { ds_err("Failed to allocate memory."); free(keyrouter_grab); return NULL; -- 2.7.4 From 7861c6486a134b77b0a5000dcc42f6b6e5c373a9 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Wed, 8 Jun 2022 16:43:12 +0900 Subject: [PATCH 02/16] keyrouter: Fix illegally finishing tizen_security Do not finish tizen_security if the initialization's been failed. Change-Id: Iee1a6eb973a8513c97aaf27a5b40e2d60c8f1f32 --- src/keyrouter/keyrouter.c | 9 ++++++--- src/keyrouter/keyrouter.h | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index cba286e..991c1f3 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -32,7 +32,8 @@ keyrouter_handle_display_destroy(struct wl_listener *listener, void *data) wl_signal_emit(&keyrouter->events.destroy, keyrouter); - tizen_security_finish(); + if (keyrouter->security_initialized) + tizen_security_finish(); free(keyrouter->opts); @@ -79,8 +80,10 @@ ds_tizen_keyrouter_create(struct wl_display *display) keyrouter_options_set(keyrouter); - if (!tizen_security_init()) { - ds_inf("tizen_security_init() is not sucessful. keyrouter works without security."); + keyrouter->security_initialized = tizen_security_init(); + if (!keyrouter->security_initialized) { + ds_inf("tizen_security_init() is not sucessful. " + "keyrouter works without security."); } ds_inf("Global created: ds_tizen_keyrouter(%p)", keyrouter); diff --git a/src/keyrouter/keyrouter.h b/src/keyrouter/keyrouter.h index ffbb3cd..3d88346 100644 --- a/src/keyrouter/keyrouter.h +++ b/src/keyrouter/keyrouter.h @@ -56,6 +56,8 @@ struct ds_tizen_keyrouter struct ds_tizen_keyrouter_key_options *opts; struct ds_tizen_keyrouter_grab *keyrouter_grab; + + bool security_initialized; }; struct ds_tizen_keyrouter_client -- 2.7.4 From 1a9fb7038826375139cc3574926f407058b40d1c Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Wed, 8 Jun 2022 16:53:16 +0900 Subject: [PATCH 03/16] keyrouter: Add missing assignment The member variable 'keyrouter' of ds_tizen_keyrouter_client is referred throughout the file, but it's never been assigned. Change-Id: I7db736c88c89026433da5c1621f249593b402125 --- src/keyrouter/keyrouter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index 991c1f3..2e95e48 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -344,6 +344,7 @@ keyrouter_bind(struct wl_client *client, void *data, uint32_t version, return; } + keyrouter_client->keyrouter = keyrouter; keyrouter_client->resource = wl_resource_create(client, &tizen_keyrouter_interface, MIN(version, 2), id); if (keyrouter_client->resource == NULL) { -- 2.7.4 From 72a88cda5d0ab7eceae7eaebf66fa1bfb9c52372 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Wed, 8 Jun 2022 17:07:24 +0900 Subject: [PATCH 04/16] input-devicemgr: add input-devicemgr in build scripts Change-Id: I5fde58ecbf1187b561349f593521a25961535b7e --- clients/meson.build | 24 ++++++++++----------- examples/meson.build | 21 +++++++++--------- packaging/libds-tizen.spec | 40 ++++++++++++++++++----------------- src/input-devicemgr/input-devicemgr.c | 21 ++++++++---------- src/input-devicemgr/input-devicemgr.h | 2 +- src/meson.build | 2 +- 6 files changed, 55 insertions(+), 55 deletions(-) diff --git a/clients/meson.build b/clients/meson.build index 5d80f18..c97e3ad 100644 --- a/clients/meson.build +++ b/clients/meson.build @@ -56,15 +56,15 @@ executable('ds-simple-dpms', install: true, ) -# input_generator_files = ['input-generator.c'] -# input_generator_deps = [ -# dependency('wayland-client', required: true), -# tizen_extension_client, -# ] -# -# executable('input-generator', -# input_generator_files, -# dependencies: input_generator_deps, -# install_dir: libds_tizen_bindir, -# install: true, -# ) +input_generator_files = ['input-generator.c'] +input_generator_deps = [ + dependency('wayland-client', required: true), + tizen_extension_client, +] + +executable('input-generator', + input_generator_files, + dependencies: input_generator_deps, + install_dir: libds_tizen_bindir, + install: true, +) diff --git a/examples/meson.build b/examples/meson.build index 5917f02..d9233fb 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -35,16 +35,17 @@ tinyds_tdm_libinput_files = [ 'tinyds-tdm-renderer.c', ] -#executable('tinyds-tdm-libinput', -# tinyds_tdm_libinput_files, -# dependencies: [ -# common_deps, -# dependency('pixman-1', required: true), -# dependency('threads', required: true), -# ], -# install_dir: libds_tizen_bindir, -# install : true -#) +executable('tinyds-tdm-libinput', + tinyds_tdm_libinput_files, + dependencies: [ + common_deps, + dep_libds_tizen_input_devicemgr, + dependency('pixman-1', required: true), + dependency('threads', required: true), + ], + install_dir: libds_tizen_bindir, + install : true +) executable('tinyds-tdm-dpms', 'tinyds-tdm-dpms.c', diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 5c8e2a9..c2e0180 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -53,18 +53,18 @@ Group: Development/Libraries %description keyrouter-devel Keyrouter Development package for Wayland Compositor Library -%package tizen-input-devicemgr +%package input-devicemgr Summary: Library for tizen input devicemgr Group: Development/Libraries -%description tizen-input-devicemgr +%description input-devicemgr Library for tizen input devicemgr -%package tizen-input-devicemgr-devel +%package input-devicemgr-devel Summary: Development package for tizen input devicemgr Group: Development/Libraries -%description tizen-input-devicemgr-devel +%description input-devicemgr-devel Development package for tizen input devicemgr %prep @@ -102,6 +102,8 @@ ninja -C builddir install %{_bindir}/ds-simple-tbm %{_bindir}/tinyds-tdm-dpms %{_bindir}/ds-simple-dpms +%{_bindir}/tinyds-tdm-libinput +%{_bindir}/input-generator %files keyrouter %manifest %{name}.manifest @@ -117,18 +119,18 @@ ninja -C builddir install %{_libdir}/pkgconfig/libds-tizen-keyrouter.pc %{_libdir}/libds-tizen-keyrouter.so -# %files input-devicemgr -# %manifest %{name}.manifest -# %defattr(-,root,root,-) -# %license LICENSE -# %{_libdir}/libds-tizen-input-devicemgr.so.* -# -# %files input-devicemgr-devel -# %manifest %{name}.manifest -# %defattr(-,root,root,-) -# %license LICENSE -# %{_includedir}/libds-tizen/input-devicemgr.h -# %{_libdir}/pkgconfig/libds-tizen-input-devicemgr.pc -# %{_libdir}/libds-tizen-input-devicemgr.so -# %{_bindir}/tinyds-tdm-libinput -# %{_bindir}/input-generator +%files input-devicemgr +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_libdir}/libds-tizen-input-devicemgr.so.* + +%files input-devicemgr-devel +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_includedir}/libds-tizen/input-devicemgr.h +%{_libdir}/pkgconfig/libds-tizen-input-devicemgr.pc +%{_libdir}/libds-tizen-input-devicemgr.so +%{_bindir}/tinyds-tdm-libinput +%{_bindir}/input-generator diff --git a/src/input-devicemgr/input-devicemgr.c b/src/input-devicemgr/input-devicemgr.c index 84700d7..3e69d0e 100644 --- a/src/input-devicemgr/input-devicemgr.c +++ b/src/input-devicemgr/input-devicemgr.c @@ -5,11 +5,9 @@ #include #include #include -#include #include "util.h" #include "input-devicemgr.h" -#include "src/libds/seat.h" #define TIZEN_INPUT_DEVICEMGR_VERSION 4 #define TIZEN_PRIV_INPUT_GENERATOR "http://tizen.org/privilege/inputgenerator" @@ -128,16 +126,12 @@ ds_tizen_input_devicemgr_create(struct ds_backend *backend, goto err_kbd; } - tz_devicemgr->grab = calloc(1, sizeof(struct ds_seat_keyboard_grab)); - if (!tz_devicemgr->grab) - { + tz_devicemgr->grab = ds_seat_create_keyboard_grab( + tz_devicemgr->seat, &devicemgr_keyboard_grab_iface, tz_devicemgr); + if (!tz_devicemgr->grab) { goto err_grab; } - tz_devicemgr->grab->iface = &devicemgr_keyboard_grab_iface; - tz_devicemgr->grab->seat = tz_devicemgr->seat; - tz_devicemgr->grab->data = tz_devicemgr; - wl_signal_init(&tz_devicemgr->events.destroy); wl_list_init(&tz_devicemgr->clients); wl_list_init(&tz_devicemgr->pressed_keys); @@ -150,6 +144,7 @@ ds_tizen_input_devicemgr_create(struct ds_backend *backend, ds_inf("Global created: ds_tizen_input_devicemgr(%p) ", tz_devicemgr); return tz_devicemgr; + err_grab: free(tz_devicemgr->devices.kbd); err_kbd: @@ -207,6 +202,7 @@ tz_devicemgr_destroy(struct ds_tizen_input_devicemgr *tz_devicemgr) 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); @@ -224,7 +220,6 @@ tz_devicemgr_destroy(struct ds_tizen_input_devicemgr *tz_devicemgr) } free(tz_devicemgr->devices.kbd); - free(tz_devicemgr->grab); free(tz_devicemgr); } @@ -846,12 +841,13 @@ static void devicemgr_keyboard_grab_iface_key(struct ds_seat_keyboard_grab *grab, uint32_t time_msec, uint32_t key, uint32_t state) { - struct ds_tizen_input_devicemgr *devicemgr = grab->data; + struct ds_tizen_input_devicemgr *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; @@ -1060,4 +1056,5 @@ device_manager_handle_unblock_events(struct wl_client *client, finish: tizen_input_device_manager_send_error(resource, ret); -} \ No newline at end of file +} + diff --git a/src/input-devicemgr/input-devicemgr.h b/src/input-devicemgr/input-devicemgr.h index 8418b16..52bd2ef 100644 --- a/src/input-devicemgr/input-devicemgr.h +++ b/src/input-devicemgr/input-devicemgr.h @@ -5,7 +5,7 @@ #include #include #include -#include "libds/interfaces/input_device.h" +#include #include struct ds_tizen_input_devicemgr_device { diff --git a/src/meson.build b/src/meson.build index 28ec46e..1ee9b99 100644 --- a/src/meson.build +++ b/src/meson.build @@ -59,5 +59,5 @@ pkgconfig.generate(lib_libds_tizen, ) subdir('keyrouter') -#subdir('input-devicemgr') +subdir('input-devicemgr') -- 2.7.4 From d4128c591749fba92d718853ef403f214fb6e421 Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Thu, 16 Jun 2022 11:52:13 +0900 Subject: [PATCH 05/16] backend/tdm: Add ds_tdm_output_hwc ds_tdm_output_hwc composites surface or buffer if hardware layer of output can use direct scan-out(bypass compositing at output buffer). ds_tdm_output_hwc has is consists of ds_tdm_output_hwc_window. for using hardware compositing, display-server should set compositing infomation of ds_tdm_output_hwc_window it would be nice to ds_tdm_output_hwc can display all ds_tdm_output_hwc_window by direct scan-out but it has restrictions. output has limited number of hardware layer and hardware layer has hw restrictions(buffer size, transform, format, etc). if ds_tdm_output_hwc_window can not be display by direct scan-out, display-server should composite it at output buffer. ds_tdm_output_hwc_window is updated at output when ds_output_hwc_validate and ds_output_commit is called because ds_tdm_output_hwc is component of ds_output. Change-Id: If78e862e4acbcc1ae465fe8315fc478f888657b3 --- include/libds-tizen/backend/tdm.h | 11 + include/libds-tizen/backend/tdm_output_hwc.h | 74 ++++ include/libds-tizen/tbm_server.h | 1 + src/backend/tdm/meson.build | 1 + src/backend/tdm/output.c | 68 ++- src/backend/tdm/tdm.h | 3 + src/backend/tdm/tdm_output_hwc.c | 636 +++++++++++++++++++++++++++ src/backend/tdm/tdm_output_hwc.h | 83 ++++ 8 files changed, 842 insertions(+), 35 deletions(-) create mode 100644 include/libds-tizen/backend/tdm_output_hwc.h create mode 100644 src/backend/tdm/tdm_output_hwc.c create mode 100644 src/backend/tdm/tdm_output_hwc.h diff --git a/include/libds-tizen/backend/tdm.h b/include/libds-tizen/backend/tdm.h index 8c5c605..33422ba 100644 --- a/include/libds-tizen/backend/tdm.h +++ b/include/libds-tizen/backend/tdm.h @@ -3,6 +3,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -10,8 +11,15 @@ extern "C" { struct ds_tdm_output; +struct ds_tdm_output_hwc; + struct ds_tdm_buffer_queue; +struct ds_tdm_box { + int x, y; + int width, height; +}; + struct ds_backend * ds_tdm_backend_create(struct wl_display *display); @@ -31,6 +39,9 @@ void ds_tdm_buffer_queue_add_acquirable_listener(struct ds_tdm_buffer_queue *queue, struct wl_listener *listener); +struct ds_tdm_output_hwc * +ds_tdm_output_get_hwc(struct ds_tdm_output *output); + #ifdef __cplusplus } #endif diff --git a/include/libds-tizen/backend/tdm_output_hwc.h b/include/libds-tizen/backend/tdm_output_hwc.h new file mode 100644 index 0000000..abde223 --- /dev/null +++ b/include/libds-tizen/backend/tdm_output_hwc.h @@ -0,0 +1,74 @@ +#ifndef LIBDS_TIZEN_BACKEND_TDM_OUTPUT_HWC_H +#define LIBDS_TIZEN_BACKEND_TDM_OUTPUT_HWC_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tdm_output_hwc; + +struct ds_tdm_output_hwc_window; + +enum ds_tdm_output_hwc_window_composition { + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE, + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT, + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE, + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR, + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO, +}; + +WL_EXPORT void +ds_tdm_output_hwc_set_enabled(struct ds_tdm_output_hwc *hwc, bool enabled); + +WL_EXPORT bool +ds_tdm_output_hwc_validate(struct ds_tdm_output_hwc *hwc, + struct ds_tdm_output_hwc_window **composited_windows, uint32_t num_windows, uint32_t *num_changed); + +WL_EXPORT bool +ds_tdm_output_hwc_get_changed_composition(struct ds_tdm_output_hwc *hwc, uint32_t *num_changed, + struct ds_tdm_output_hwc_window **changed_windows); + +WL_EXPORT bool +ds_tdm_output_hwc_accept_validation(struct ds_tdm_output_hwc *hwc); + +WL_EXPORT struct ds_tdm_output_hwc_window * +ds_tdm_output_hwc_window_create(struct ds_tdm_output_hwc *hwc); + +WL_EXPORT void +ds_tdm_output_hwc_window_destroy(struct ds_tdm_output_hwc_window *hwc_window); + +WL_EXPORT bool +ds_tdm_output_hwc_window_set_buffer(struct ds_tdm_output_hwc_window *hwc_window, + struct ds_buffer *buffer); + +WL_EXPORT void +ds_tdm_output_hwc_window_set_src_box(struct ds_tdm_output_hwc_window *hwc_window, + const struct ds_tdm_box *src_box); + +WL_EXPORT void +ds_tdm_output_hwc_window_set_transform(struct ds_tdm_output_hwc_window *hwc_window, + enum wl_output_transform transform); + +WL_EXPORT void +ds_tdm_output_hwc_window_set_position(struct ds_tdm_output_hwc_window *hwc_window, + int x, int y); + +WL_EXPORT void +ds_tdm_output_hwc_window_set_dest_size(struct ds_tdm_output_hwc_window *hwc_window, + int width, int height); + +WL_EXPORT void +ds_tdm_output_hwc_window_set_composition(struct ds_tdm_output_hwc_window *hwc_window, + enum ds_tdm_output_hwc_window_composition composition); + +WL_EXPORT enum ds_tdm_output_hwc_window_composition +ds_tdm_output_hwc_window_get_composition(struct ds_tdm_output_hwc_window *hwc_window); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/libds-tizen/tbm_server.h b/include/libds-tizen/tbm_server.h index f1cc97d..6e3b148 100644 --- a/include/libds-tizen/tbm_server.h +++ b/include/libds-tizen/tbm_server.h @@ -3,6 +3,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/src/backend/tdm/meson.build b/src/backend/tdm/meson.build index 932559f..7a7c25f 100644 --- a/src/backend/tdm/meson.build +++ b/src/backend/tdm/meson.build @@ -2,6 +2,7 @@ libds_tizen_files += files( 'backend.c', 'output.c', 'tdm_buffer_queue.c', + 'tdm_output_hwc.c', ) libtdm = dependency('libtdm', required: true) diff --git a/src/backend/tdm/output.c b/src/backend/tdm/output.c index 089c067..5e874df 100644 --- a/src/backend/tdm/output.c +++ b/src/backend/tdm/output.c @@ -7,6 +7,7 @@ #include "libds-tizen/allocator/tbm.h" #include "tdm.h" +#include "tdm_output_hwc.h" #include "tdm_buffer_queue.h" static const struct ds_output_interface tdm_output_iface; @@ -44,6 +45,12 @@ ds_tdm_output_get_buffer_queue(struct ds_tdm_output *output) return output->queue; } +WL_EXPORT struct ds_tdm_output_hwc * +ds_tdm_output_get_hwc(struct ds_tdm_output *output) +{ + return output->hwc; +} + struct ds_tdm_output * create_tdm_output(struct ds_tdm_backend *tdm, tdm_output *tdm_output) { @@ -265,6 +272,9 @@ output_destroy(struct ds_tdm_output *output) if (output->queue) buffer_queue_destroy(output->queue); + if (output->hwc) + ds_tdm_output_hwc_destroy(output->hwc); + free(output); } @@ -316,6 +326,18 @@ output_init_modes(struct ds_tdm_output *output) } static void +output_hwc_commit_handler(struct wl_listener *listener, void *data) +{ + struct ds_tdm_output *output; + + output = wl_container_of(listener, output, hwc_commit_handler_listener); + + output_update_front_buffer(output); + + wl_signal_emit(&output->base.events.frame, &output->base); +} + +static void output_init_hwc(struct ds_tdm_output *output) { tdm_error err; @@ -325,6 +347,15 @@ output_init_hwc(struct ds_tdm_output *output) ds_err("Could not get tdm_hwc: output(%p)", output); return; } + + output->hwc = ds_tdm_output_hwc_create(output->tdm.hwc); + if (!output->hwc) { + ds_err("Could not create ds_dm_hwc: output(%p)", output); + return; + } + + output->hwc_commit_handler_listener.notify = output_hwc_commit_handler; + ds_tdm_output_hwc_add_commit_handler_listener(output->hwc, &output->hwc_commit_handler_listener); } static bool @@ -352,8 +383,6 @@ output_set_pending_fb(struct ds_tdm_output *output, struct ds_tdm_queue_buffer *queue_buffer; struct ds_tdm_buffer *buffer; tbm_surface_h surface = NULL; - tdm_region fb_damage; - tdm_error err; if (output->queue) { queue_buffer = buffer_queue_find_buffer(output->queue, ds_buffer); @@ -371,10 +400,7 @@ output_set_pending_fb(struct ds_tdm_output *output, surface = buffer->surface; } - memset(&fb_damage, 0, sizeof(fb_damage)); - err = tdm_hwc_set_client_target_buffer(output->tdm.hwc, - surface, fb_damage); - if (err != TDM_ERROR_NONE) { + if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, surface)) { ds_err("Could not set hwc client target buffer"); ds_buffer_unlock(ds_buffer); return false; @@ -385,38 +411,10 @@ output_set_pending_fb(struct ds_tdm_output *output, return true; } -static void -output_hwc_commit_handler(tdm_hwc *hwc, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, void *user_data) -{ - struct ds_tdm_output *output = user_data; - - output_update_front_buffer(output); - - wl_signal_emit(&output->base.events.frame, &output->base); -} - static bool output_hwc_commit(struct ds_tdm_output *output) { - tdm_error err; - uint32_t num_changes; - - err = tdm_hwc_validate(output->tdm.hwc, NULL, 0, &num_changes); - if (err != TDM_ERROR_NONE) { - ds_err("Could not hwc validate"); - return false; - } - - err = tdm_hwc_accept_validation(output->tdm.hwc); - if (err != TDM_ERROR_NONE) { - ds_err("Could not hwc accept validation"); - return false; - } - - err = tdm_hwc_commit(output->tdm.hwc, 0, output_hwc_commit_handler, - output); - if (err != TDM_ERROR_NONE) { + if (!ds_tdm_output_hwc_commit(output->hwc)) { ds_err("Could not hwc commit"); return false; } diff --git a/src/backend/tdm/tdm.h b/src/backend/tdm/tdm.h index a151f01..7c00202 100644 --- a/src/backend/tdm/tdm.h +++ b/src/backend/tdm/tdm.h @@ -48,6 +48,9 @@ struct ds_tdm_output tdm_hwc *hwc; } tdm; + struct ds_tdm_output_hwc *hwc; + struct wl_listener hwc_commit_handler_listener; + struct wl_list link; enum ds_tdm_output_status status; diff --git a/src/backend/tdm/tdm_output_hwc.c b/src/backend/tdm/tdm_output_hwc.c new file mode 100644 index 0000000..8db2984 --- /dev/null +++ b/src/backend/tdm/tdm_output_hwc.c @@ -0,0 +1,636 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "tdm_output_hwc.h" + +static void +hwc_window_update_front_buffer(struct ds_tdm_output_hwc_window *hwc_window) +{ + if (hwc_window->front_buffer == hwc_window->back_buffer) { + if (hwc_window->back_buffer) { + ds_buffer_unlock(hwc_window->back_buffer); + hwc_window->back_buffer = NULL; + } + + return; + } + + ds_tdm_output_hwc_window_lock(hwc_window); + + if (hwc_window->front_buffer) { + ds_buffer_unlock(hwc_window->front_buffer); + hwc_window->front_buffer = NULL; + ds_tdm_output_hwc_window_unlock(hwc_window); + } + + hwc_window->front_buffer = hwc_window->back_buffer; + hwc_window->back_buffer = NULL; + + if (hwc_window->front_buffer) + ds_tdm_output_hwc_window_lock(hwc_window); + + ds_tdm_output_hwc_window_unlock(hwc_window); +} + +static void +hwc_window_attach_back_buffer(struct ds_tdm_output_hwc_window *hwc_window, + struct ds_buffer *buffer) +{ + if (hwc_window->back_buffer) { + ds_buffer_unlock(hwc_window->back_buffer); + hwc_window->back_buffer = NULL; + } + + if (buffer) + hwc_window->back_buffer = ds_buffer_lock(buffer); +} + +static unsigned int +get_horizontal_get(tbm_surface_h tsurface) +{ + unsigned int horizontal = 0; + tbm_surface_info_s surf_info; + + tbm_surface_get_info(tsurface, &surf_info); + + switch (surf_info.format) { + case TBM_FORMAT_YUV420: + case TBM_FORMAT_YVU420: + case TBM_FORMAT_YUV422: + case TBM_FORMAT_YVU422: + case TBM_FORMAT_NV12: + case TBM_FORMAT_NV21: + horizontal = surf_info.planes[0].stride; + break; + case TBM_FORMAT_YUYV: + case TBM_FORMAT_UYVY: + horizontal = surf_info.planes[0].stride >> 1; + break; + case TBM_FORMAT_XRGB8888: + case TBM_FORMAT_XBGR8888: + case TBM_FORMAT_RGBX8888: + case TBM_FORMAT_BGRX8888: + case TBM_FORMAT_ARGB8888: + case TBM_FORMAT_ABGR8888: + case TBM_FORMAT_RGBA8888: + case TBM_FORMAT_BGRA8888: + case TBM_FORMAT_XRGB2101010: + case TBM_FORMAT_XBGR2101010: + case TBM_FORMAT_RGBX1010102: + case TBM_FORMAT_BGRX1010102: + case TBM_FORMAT_ARGB2101010: + case TBM_FORMAT_ABGR2101010: + case TBM_FORMAT_RGBA1010102: + case TBM_FORMAT_BGRA1010102: + horizontal = surf_info.planes[0].stride >> 2; + break; + default: + ds_err("not supported format"); + } + + return horizontal; +} + +static tdm_transform +get_tdm_transform(enum wl_output_transform output_transform) +{ + switch (output_transform) { + case WL_OUTPUT_TRANSFORM_90: + return TDM_TRANSFORM_90; + case WL_OUTPUT_TRANSFORM_180: + return TDM_TRANSFORM_180; + case WL_OUTPUT_TRANSFORM_270: + return TDM_TRANSFORM_270; + case WL_OUTPUT_TRANSFORM_FLIPPED: + return TDM_TRANSFORM_FLIPPED; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + return TDM_TRANSFORM_FLIPPED_90; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + return TDM_TRANSFORM_FLIPPED_180; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + return TDM_TRANSFORM_FLIPPED_270; + case WL_OUTPUT_TRANSFORM_NORMAL: + default: + return TDM_TRANSFORM_NORMAL; + } +} + +static tdm_hwc_window_composition +get_tdm_composition(enum ds_tdm_output_hwc_window_composition composition) +{ + switch (composition) { + case DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT: + return TDM_HWC_WIN_COMPOSITION_CLIENT; + case DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR: + return TDM_HWC_WIN_COMPOSITION_CURSOR; + case DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE: + return TDM_HWC_WIN_COMPOSITION_DEVICE; + case DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO: + return TDM_HWC_WIN_COMPOSITION_VIDEO; + case DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE: + default: + return TDM_HWC_WIN_COMPOSITION_NONE; + } +} + +static enum ds_tdm_output_hwc_window_composition +get_composition(tdm_hwc_window_composition composition) +{ + switch (composition) { + case TDM_HWC_WIN_COMPOSITION_CLIENT: + return DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT; + case TDM_HWC_WIN_COMPOSITION_CURSOR: + return DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR; + case TDM_HWC_WIN_COMPOSITION_DEVICE: + return DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE; + case TDM_HWC_WIN_COMPOSITION_VIDEO: + return DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO; + case TDM_HWC_WIN_COMPOSITION_NONE: + default: + return DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE; + } +} + +struct ds_tdm_output_hwc * +ds_tdm_output_hwc_create(tdm_hwc *thwc) +{ + struct ds_tdm_output_hwc *hwc; + + hwc = calloc(1, sizeof *hwc); + if (!hwc) + return NULL; + + hwc->thwc = thwc; + + wl_list_init(&hwc->hwc_windows); + wl_signal_init(&hwc->events.commit_handler); + wl_signal_init(&hwc->events.destroy); + + return hwc; +} + +void +ds_tdm_output_hwc_destroy(struct ds_tdm_output_hwc *hwc) +{ + wl_signal_emit(&hwc->events.destroy, hwc); + + free(hwc); +} + +bool +ds_tdm_output_hwc_set_client_target_buffer(struct ds_tdm_output_hwc *hwc, tbm_surface_h tsurface) +{ + tdm_error terr; + tdm_region fb_damage; + + memset(&fb_damage, 0, sizeof(fb_damage)); + + hwc->target_buffer_info.src_config.pos.x = 0; + hwc->target_buffer_info.src_config.pos.y = 0; + hwc->target_buffer_info.src_config.pos.w = tbm_surface_get_width(tsurface); + hwc->target_buffer_info.src_config.pos.h = tbm_surface_get_height(tsurface); + hwc->target_buffer_info.src_config.size.h = get_horizontal_get(tsurface); + hwc->target_buffer_info.src_config.size.v = tbm_surface_get_height(tsurface); + hwc->target_buffer_info.src_config.format = tbm_surface_get_format(tsurface); + + hwc->target_buffer_info.dst_pos.x = 0; + hwc->target_buffer_info.dst_pos.y = 0; + hwc->target_buffer_info.dst_pos.w = tbm_surface_get_width(tsurface); + hwc->target_buffer_info.dst_pos.h = tbm_surface_get_height(tsurface); + + hwc->target_buffer_info.transform = TDM_TRANSFORM_NORMAL; + + tdm_hwc_set_client_target_buffer_info(hwc->thwc, &hwc->target_buffer_info); + + terr = tdm_hwc_set_client_target_buffer(hwc->thwc, tsurface, fb_damage); + if (terr != TDM_ERROR_NONE) { + ds_err("Could not set hwc client target buffer"); + return false; + } + + return true; +} + +void +ds_tdm_output_hwc_window_set_accepted_composition(struct ds_tdm_output_hwc_window *hwc_window, + enum ds_tdm_output_hwc_window_composition composition) +{ + if (hwc_window->accepted_composition == composition) + return; + + hwc_window->accepted_composition = composition; +} + +static void +hwc_window_free(struct ds_tdm_output_hwc_window *hwc_window) +{ + if (hwc_window->buffer) + ds_buffer_unlock(hwc_window->buffer); + + if (hwc_window->set_buffer) + ds_buffer_unlock(hwc_window->set_buffer); + + if (hwc_window->front_buffer) + ds_buffer_unlock(hwc_window->front_buffer); + + if (hwc_window->back_buffer) + ds_buffer_unlock(hwc_window->back_buffer); + + wl_list_remove(&hwc_window->link); + + tdm_hwc_window_destroy(hwc_window->twindow); + + free(hwc_window); +} + +static void +hwc_window_consider_destroy(struct ds_tdm_output_hwc_window *hwc_window) +{ + if (!hwc_window->dropped || hwc_window->n_locks > 0) + return; + + hwc_window_free(hwc_window); +} + +struct ds_tdm_output_hwc_window * +ds_tdm_output_hwc_window_lock(struct ds_tdm_output_hwc_window *hwc_window) +{ + hwc_window->n_locks++; + ds_dbg("hwc_window(%p) n_locks(%zu)", hwc_window, hwc_window->n_locks); + return hwc_window; +} + +void +ds_tdm_output_hwc_window_unlock(struct ds_tdm_output_hwc_window *hwc_window) +{ + hwc_window->n_locks--; + ds_dbg("hwc_window(%p) n_locks(%zu)", hwc_window, hwc_window->n_locks); + + hwc_window_consider_destroy(hwc_window); +} + +WL_EXPORT void +ds_tdm_output_hwc_set_enabled(struct ds_tdm_output_hwc *hwc, bool enabled) +{ + if (hwc->enabled == enabled) + return; + + hwc->enabled = enabled; +} + +WL_EXPORT struct ds_tdm_output_hwc_window * +ds_tdm_output_hwc_window_create(struct ds_tdm_output_hwc *hwc) +{ + tdm_error terr; + tdm_hwc_window *thwc_window; + struct ds_tdm_output_hwc_window *hwc_window; + + hwc_window = calloc(1, sizeof *hwc_window); + if (!hwc_window) + return NULL; + + thwc_window = tdm_hwc_create_window(hwc->thwc, &terr); + if (terr != TDM_ERROR_NONE) { + ds_err("Could not create tdm_hwc_window error:%d", terr); + free(hwc_window); + return NULL; + } + + hwc_window->twindow = thwc_window; + + wl_list_insert(hwc->hwc_windows.prev, &hwc_window->link); + + return hwc_window; +} + +WL_EXPORT void +ds_tdm_output_hwc_window_destroy(struct ds_tdm_output_hwc_window *hwc_window) +{ + hwc_window->dropped = true; + ds_dbg("hwc_window(%p) dropped: n_locks(%zu)", hwc_window, hwc_window->n_locks); + hwc_window_consider_destroy(hwc_window); +} + +WL_EXPORT bool +ds_tdm_output_hwc_window_set_buffer(struct ds_tdm_output_hwc_window *hwc_window, + struct ds_buffer *buffer) +{ + if (hwc_window->buffer == buffer) + return true; + + if (hwc_window->buffer) { + ds_buffer_unlock(hwc_window->set_buffer); + hwc_window->buffer = NULL; + } + + if (buffer) + hwc_window->buffer = ds_buffer_lock(buffer); + + return true; +} + +WL_EXPORT void +ds_tdm_output_hwc_window_set_src_box(struct ds_tdm_output_hwc_window *hwc_window, + const struct ds_tdm_box *src_box) +{ + if (src_box != NULL && !memcmp(&hwc_window->src_box, src_box, sizeof(*src_box))) + return; + + if (src_box != NULL) { + memcpy(&hwc_window->src_box, src_box, sizeof(*src_box)); + } else { + memset(&hwc_window->src_box, 0, sizeof(hwc_window->src_box)); + } +} + +WL_EXPORT void +ds_tdm_output_hwc_window_set_transform(struct ds_tdm_output_hwc_window *hwc_window, + enum wl_output_transform transform) +{ + if (hwc_window->transform == transform) + return; + + hwc_window->transform = transform; +} + +WL_EXPORT void +ds_tdm_output_hwc_window_set_position(struct ds_tdm_output_hwc_window *hwc_window, + int x, int y) +{ + if ((hwc_window->x == x) && (hwc_window->y == y)) + return; + + hwc_window->x = x; + hwc_window->y = y; +} + +WL_EXPORT void +ds_tdm_output_hwc_window_set_dest_size(struct ds_tdm_output_hwc_window *hwc_window, + int width, int height) +{ + if ((hwc_window->dest_width == width) && (hwc_window->dest_height == height)) + return; + + hwc_window->dest_width = width; + hwc_window->dest_height = height; +} + +WL_EXPORT void +ds_tdm_output_hwc_window_set_composition(struct ds_tdm_output_hwc_window *hwc_window, + enum ds_tdm_output_hwc_window_composition composition) +{ + if (hwc_window->composition == composition) + return; + + hwc_window->composition = composition; +} + +WL_EXPORT enum ds_tdm_output_hwc_window_composition +ds_tdm_output_hwc_window_get_composition(struct ds_tdm_output_hwc_window *hwc_window) +{ + return hwc_window->composition; +} + +static void +hwc_window_update(struct ds_tdm_output_hwc_window *hwc_window) +{ + tdm_error terr; + tbm_surface_h tsurface = NULL; + tdm_hwc_window_info tinfo = {0, }; + struct ds_tbm_client_buffer *client_buffer; + + if (hwc_window->buffer) { + client_buffer = ds_tbm_client_buffer_from_buffer(hwc_window->buffer); + if (client_buffer) + tsurface = ds_tbm_client_buffer_get_tbm_surface(client_buffer); + } + + if (hwc_window->set_buffer != hwc_window->buffer) { + if (hwc_window->set_buffer) { + ds_buffer_unlock(hwc_window->set_buffer); + hwc_window->set_buffer = NULL; + } + + if (hwc_window->buffer) + hwc_window->set_buffer = ds_buffer_lock(hwc_window->buffer); + + terr = tdm_hwc_window_set_buffer(hwc_window->twindow, tsurface); + if (terr != TDM_ERROR_NONE) + ds_err("Could not set buffer hwc_window:%p tdm_error:%d", hwc_window, terr); + } + + if (tsurface) { + tinfo.src_config.pos.x = 0; + tinfo.src_config.pos.y = 0; + tinfo.src_config.pos.w = tbm_surface_get_width(tsurface); + tinfo.src_config.pos.h = tbm_surface_get_height(tsurface); + tinfo.src_config.size.h = get_horizontal_get(tsurface); + tinfo.src_config.size.v = tbm_surface_get_height(tsurface); + tinfo.src_config.format = tbm_surface_get_format(tsurface); + tinfo.dst_pos.x = hwc_window->x; + tinfo.dst_pos.y = hwc_window->y; + tinfo.dst_pos.w = hwc_window->dest_width; + tinfo.dst_pos.h = hwc_window->dest_height; + tinfo.transform = get_tdm_transform(hwc_window->transform); + } + + if (memcmp(&hwc_window->tinfo, &tinfo, sizeof tinfo)) { + memcpy(&hwc_window->tinfo, &tinfo, sizeof tinfo); + + terr = tdm_hwc_window_set_info(hwc_window->twindow, &hwc_window->tinfo); + if (terr != TDM_ERROR_NONE) + ds_err("Could not set info hwc_window:%p tdm_error:%d", hwc_window, terr); + } + + terr = tdm_hwc_window_set_composition_type(hwc_window->twindow, + get_tdm_composition(hwc_window->composition)); + if (terr != TDM_ERROR_NONE) + ds_err("Could not set composition type hwc_window:%p tdm_error:%d", hwc_window, terr); +} + +WL_EXPORT bool +ds_tdm_output_hwc_validate(struct ds_tdm_output_hwc *hwc, + struct ds_tdm_output_hwc_window **composited_windows, uint32_t num_windows, uint32_t *num_changed) +{ + tdm_error terr; + tdm_hwc_window **compositied_hwc_windows = NULL; + struct ds_tdm_output_hwc_window *hwc_window; + int i; + + wl_list_for_each(hwc_window, &hwc->hwc_windows, link) + hwc_window_update(hwc_window); + + if (num_windows > 0) { + compositied_hwc_windows = calloc(num_windows, sizeof(tdm_hwc_window *)); + if (!compositied_hwc_windows) + return false; + + for (i = 0; i < num_windows; i++) + compositied_hwc_windows[i] = composited_windows[i]->twindow; + } + + terr = tdm_hwc_validate(hwc->thwc, compositied_hwc_windows, num_windows, num_changed); + if (terr != TDM_ERROR_NONE) { + if (compositied_hwc_windows) + free(compositied_hwc_windows); + ds_err("Could not hwc validate"); + return false; + } + + if (compositied_hwc_windows) + free(compositied_hwc_windows); + + hwc->validate_num_changed = *num_changed; + + return true; +} + +static struct ds_tdm_output_hwc_window * +hwc_get_hwc_window_from_tdm_hwc_window(struct ds_tdm_output_hwc *hwc, tdm_hwc_window *thwc_window) +{ + struct ds_tdm_output_hwc_window *hwc_window; + + wl_list_for_each(hwc_window, &hwc->hwc_windows, link) { + if (hwc_window->twindow == thwc_window) + return hwc_window; + } + + return NULL; +} + +WL_EXPORT bool +ds_tdm_output_hwc_get_changed_composition(struct ds_tdm_output_hwc *hwc, uint32_t *num_changed, + struct ds_tdm_output_hwc_window **changed_windows) +{ + tdm_hwc_window **changed_thwc_windows = NULL; + tdm_hwc_window_composition *compositions = NULL; + struct ds_tdm_output_hwc_window *hwc_window; + tdm_error terr; + int i; + + if (!hwc->validate_num_changed) { + *num_changed = 0; + return true; + } + + changed_thwc_windows = calloc(hwc->validate_num_changed, sizeof *changed_thwc_windows); + if (!changed_thwc_windows) + return false; + + compositions = calloc(hwc->validate_num_changed, sizeof *compositions); + if (!compositions) { + free(changed_thwc_windows); + return false; + } + + terr = tdm_hwc_get_changed_composition_types(hwc->thwc, &hwc->validate_num_changed, + changed_thwc_windows, compositions); + if (terr != TDM_ERROR_NONE) { + ds_err("Could not hwc get changed composition types"); + free(changed_thwc_windows); + free(compositions); + return false; + } + + for (i = 0; i < hwc->validate_num_changed; i++) { + if (i >= *num_changed) + break; + + hwc_window = hwc_get_hwc_window_from_tdm_hwc_window(hwc, changed_thwc_windows[i]); + if (!hwc_window) + continue; + + ds_tdm_output_hwc_window_set_composition(hwc_window, get_composition(compositions[i])); + changed_windows[i] = hwc_window; + } + + free(changed_thwc_windows); + free(compositions); + + *num_changed = i; + + return true; +} + +WL_EXPORT bool +ds_tdm_output_hwc_accept_validation(struct ds_tdm_output_hwc *hwc) +{ + tdm_error terr; + struct ds_tdm_output_hwc_window *hwc_window; + enum ds_tdm_output_hwc_window_composition composition; + + terr = tdm_hwc_accept_validation(hwc->thwc); + if (terr != TDM_ERROR_NONE) { + ds_err("Could not hwc accept validation"); + return false; + } + + wl_list_for_each(hwc_window, &hwc->hwc_windows, link) { + composition = ds_tdm_output_hwc_window_get_composition(hwc_window); + ds_tdm_output_hwc_window_set_accepted_composition(hwc_window, + composition); + if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO)) { + hwc_window_attach_back_buffer(hwc_window, hwc_window->set_buffer); + } else { + hwc_window_attach_back_buffer(hwc_window, NULL); + } + } + + return true; +} + +static void +ds_tdm_output_hwc_commit_handler(tdm_hwc *thwc, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + struct ds_tdm_output_hwc *hwc = user_data; + struct ds_tdm_output_hwc_window *hwc_window, *tmp; + + wl_list_for_each_safe(hwc_window, tmp, &hwc->hwc_windows, link) + hwc_window_update_front_buffer(hwc_window); + + wl_signal_emit(&hwc->events.commit_handler, hwc); +} + +bool +ds_tdm_output_hwc_commit(struct ds_tdm_output_hwc *hwc) +{ + tdm_error terr; + uint32_t num_changes; + + if (!hwc->enabled) { + terr = tdm_hwc_validate(hwc->thwc, NULL, 0, &num_changes); + if (terr != TDM_ERROR_NONE) { + ds_err("Could not hwc validate"); + return false; + } + + terr = tdm_hwc_accept_validation(hwc->thwc); + if (terr != TDM_ERROR_NONE) { + ds_err("Could not hwc accept validation"); + return false; + } + } + + terr = tdm_hwc_commit(hwc->thwc, 0, ds_tdm_output_hwc_commit_handler, hwc); + if (terr != TDM_ERROR_NONE) { + ds_err("Could not hwc commit"); + return false; + } + + return true; +} + +void +ds_tdm_output_hwc_add_commit_handler_listener(struct ds_tdm_output_hwc *hwc, + struct wl_listener *listener) +{ + wl_signal_add(&hwc->events.commit_handler, listener); +} diff --git a/src/backend/tdm/tdm_output_hwc.h b/src/backend/tdm/tdm_output_hwc.h new file mode 100644 index 0000000..07b3699 --- /dev/null +++ b/src/backend/tdm/tdm_output_hwc.h @@ -0,0 +1,83 @@ +#ifndef DS_TIZEN_BACKEND_TDM_OUTPUT_HWC_H +#define DS_TIZEN_BACKEND_TDM_OUTPUT_HWC_H + +#include +#include +#include + +#include +#include + +struct ds_tdm_output_hwc_window { + struct wl_list link; + + tdm_hwc *hwc; + + size_t n_locks; + bool dropped; + + tdm_hwc_window *twindow; + tdm_hwc_window_info tinfo; + + enum ds_tdm_output_hwc_window_composition composition; + enum ds_tdm_output_hwc_window_composition accepted_composition; + + struct ds_tdm_box src_box; + int x, y; + int dest_width, dest_height; + enum wl_output_transform transform; + struct ds_buffer *buffer; + + struct ds_buffer *set_buffer; + struct ds_buffer *back_buffer, *front_buffer; +}; + +struct ds_tdm_output_hwc { + struct ds_tdm_output *tdm_output; + + tdm_hwc *thwc; + tdm_hwc_window_info target_buffer_info; + bool enabled; + + struct { + struct wl_signal destroy; + struct wl_signal commit_handler; + } events; + + uint32_t validate_num_changed; + + struct wl_list hwc_windows; +}; + +struct ds_tdm_output_hwc * +ds_tdm_output_hwc_create(tdm_hwc *thwc); + +void +ds_tdm_output_hwc_destroy(struct ds_tdm_output_hwc *hwc); + +bool +ds_tdm_output_hwc_set_client_target_buffer(struct ds_tdm_output_hwc *hwc, + tbm_surface_h tsurface); + +bool +ds_tdm_output_hwc_commit(struct ds_tdm_output_hwc *hwc); + +void +ds_tdm_output_hwc_add_commit_handler_listener(struct ds_tdm_output_hwc *hwc, + struct wl_listener *listener); + +void +ds_tdm_output_hwc_window_set_accepted_composition(struct ds_tdm_output_hwc_window *hwc_window, + enum ds_tdm_output_hwc_window_composition composition); + +void +ds_tdm_output_hwc_window_set_changed_composition(struct ds_tdm_output_hwc_window *hwc_window, + enum ds_tdm_output_hwc_window_composition composition); + +struct ds_tdm_output_hwc_window * +ds_tdm_output_hwc_window_lock(struct ds_tdm_output_hwc_window *hwc_window); + +void +ds_tdm_output_hwc_window_unlock(struct ds_tdm_output_hwc_window *hwc_window); + +#endif -- 2.7.4 From 7b9fd87d6e8fd123f5fbd1351f1601de93229eeb Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Thu, 16 Jun 2022 11:53:26 +0900 Subject: [PATCH 06/16] example: Add tinyds-tdm-hwc example ds_tdm_output_hwc Change-Id: I5a6f9f0a6055eaf52f0d6456896d5e65c4a746ee --- examples/meson.build | 17 + examples/tinyds-tdm-hwc.c | 768 +++++++++++++++++++++++++++++++++++++++++++++ packaging/libds-tizen.spec | 1 + 3 files changed, 786 insertions(+) create mode 100644 examples/tinyds-tdm-hwc.c diff --git a/examples/meson.build b/examples/meson.build index d9233fb..b7500a1 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -60,3 +60,20 @@ executable('tinyds-tdm-dpms', install_dir: libds_tizen_bindir, install : true ) + +tinyds_tdm_hwc_files = [ + 'tinyds-tdm-hwc.c', + 'pixman-helper.c', + 'pixman-tbm-helper.c', + 'tinyds-tdm-renderer.c', +] +executable('tinyds-tdm-hwc', + tinyds_tdm_hwc_files, + dependencies: [ + common_deps, + dependency('pixman-1', required: true), + dependency('threads', required: true), + ], + install_dir: libds_tizen_bindir, + install : true +) diff --git a/examples/tinyds-tdm-hwc.c b/examples/tinyds-tdm-hwc.c new file mode 100644 index 0000000..46925f1 --- /dev/null +++ b/examples/tinyds-tdm-hwc.c @@ -0,0 +1,768 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USE_TDM_BUFFER_QUEUE + +#ifdef USE_TDM_BUFFER_QUEUE +#include "pixman-tbm-helper.h" +#include "tinyds-tdm-renderer.h" +#else +#include +#endif + +#include "pixman-helper.h" + +#define TINYDS_UNUSED __attribute__((unused)) + +struct tinyds_output +{ + struct tinyds_server *server; + struct ds_output *ds_output; + struct ds_allocator *allocator; +#ifdef USE_TDM_BUFFER_QUEUE + struct tinyds_renderer renderer; + struct ds_tdm_buffer_queue *buffer_queue; + struct wl_listener buffer_queue_acquirable; +#else + struct ds_swapchain *swapchain; +#endif + struct ds_buffer *front_buffer; + + struct wl_listener output_destroy; + struct wl_listener output_frame; + + int width, height; + + struct wl_event_source *idle_commit; + bool commitable; + bool damaged; + + struct ds_tdm_output_hwc *hwc; +}; + +struct tinyds_server +{ + struct ds_tbm_server *tbm_server; + + struct wl_display *display; + + struct ds_backend *backend; + struct ds_compositor *compositor; + struct ds_xdg_shell *xdg_shell; + + struct tinyds_output *output; + struct wl_event_source *stdin_source; + + struct wl_list views; + + struct wl_listener new_output; + struct wl_listener new_xdg_surface; +}; + +struct tinyds_view +{ + struct tinyds_server *server; + + struct tinyds_texture *texture; + struct ds_xdg_surface *xdg_surface; + + struct wl_listener xdg_surface_map; + struct wl_listener xdg_surface_unmap; + struct wl_listener xdg_surface_destroy; + struct wl_listener surface_commit; + struct wl_list link; // tinyds_server::views + + struct ds_tdm_output_hwc_window *hwc_window; + + int x, y; + bool mapped; +}; + +struct tinyds_server tinyds; + +static bool init_server(struct tinyds_server *server, struct wl_display *display); +static int server_dispatch_stdin(int fd, uint32_t mask, void *data); +static void output_handle_destroy(struct wl_listener *listener, void *data); +static void output_handle_frame(struct wl_listener *listener, void *data); +static void draw_server_with_damage(struct tinyds_server *server); +static void draw_output(struct tinyds_output *output); +static void output_swap_buffer(struct tinyds_output *output, + struct ds_buffer *buffer); +static void view_send_frame_done(struct tinyds_view *view); +static void output_hwc_init(struct tinyds_output *output); +static void output_schedule_commit(struct tinyds_output *output); +static void output_commit(struct tinyds_output *output); +#ifdef USE_TDM_BUFFER_QUEUE +static void output_buffer_queue_init(struct tinyds_output *output); +static void output_renderer_init(struct tinyds_output *output); +static void output_draw_with_renderer(struct tinyds_output *output); +#else +static void output_swapchain_init(struct tinyds_output *output, + int width, int height, uint32_t format); +static void output_draw_with_swapchain(struct tinyds_output *output); +static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image); +#endif + +int +main(void) +{ + struct tinyds_server *server = &tinyds; + struct wl_display *display; + struct wl_event_loop *loop; + const char *socket; + bool res; + + ds_log_init(DS_INF, NULL); + + display = wl_display_create(); + assert(display); + + res = init_server(server, display); + assert(res); + + socket = wl_display_add_socket_auto(display); + assert(socket); + + ds_backend_start(server->backend); + + setenv("WAYLAND_DISPLAY", socket, true); + + ds_inf("Running Wayland compositor on WAYLAND_DISPLAY=%s", socket); + + loop = wl_display_get_event_loop(display); + server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO, + WL_EVENT_READABLE, server_dispatch_stdin, server); + + wl_display_run(display); + + wl_display_destroy_clients(display); + wl_display_destroy(display); + + return 0; +} + +static void +view_handle_xdg_surface_map(struct wl_listener *listener, + void *data TINYDS_UNUSED) +{ + struct tinyds_view *view; + + view = wl_container_of(listener, view, xdg_surface_map); + view->mapped = true; +} + +static void +view_handle_xdg_surface_unmap(struct wl_listener *listener, + void *data TINYDS_UNUSED) +{ + struct tinyds_view *view; + + view = wl_container_of(listener, view, xdg_surface_unmap); + view->mapped = false; +} + +static void +view_handle_xdg_surface_destroy(struct wl_listener *listener, + void *data TINYDS_UNUSED) +{ + struct tinyds_view *view; + + view = wl_container_of(listener, view, xdg_surface_destroy); + + draw_server_with_damage(view->server); + + ds_tdm_output_hwc_window_destroy(view->hwc_window); + + wl_list_remove(&view->xdg_surface_destroy.link); + wl_list_remove(&view->xdg_surface_map.link); + wl_list_remove(&view->xdg_surface_unmap.link); + wl_list_remove(&view->surface_commit.link); + wl_list_remove(&view->link); + free(view); +} + +static void +view_handle_surface_commit(struct wl_listener *listener, + void *data TINYDS_UNUSED) +{ + struct tinyds_view *view; + + view = wl_container_of(listener, view, surface_commit); + + draw_server_with_damage(view->server); +} + +static void +server_new_xdg_surface(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct tinyds_view *view; + struct ds_xdg_surface *xdg_surface; + + server = wl_container_of(listener, server, new_xdg_surface); + xdg_surface = data; + + ds_inf("New xdg_surface(%p)", (void *)xdg_surface); + + view = calloc(1, sizeof *view); + assert(view); + + view->server = server; + view->xdg_surface = xdg_surface; + + view->xdg_surface_map.notify = view_handle_xdg_surface_map; + ds_xdg_surface_add_map_listener(xdg_surface, + &view->xdg_surface_map); + + view->xdg_surface_unmap.notify = view_handle_xdg_surface_unmap; + ds_xdg_surface_add_unmap_listener(xdg_surface, + &view->xdg_surface_unmap); + + view->xdg_surface_destroy.notify = view_handle_xdg_surface_destroy; + ds_xdg_surface_add_destroy_listener(xdg_surface, + &view->xdg_surface_destroy); + + view->surface_commit.notify = view_handle_surface_commit; + ds_surface_add_commit_listener( + ds_xdg_surface_get_surface(xdg_surface), + &view->surface_commit); + + view->hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc); + + wl_list_insert(server->views.prev, &view->link); +} + +static void +backend_handle_new_output(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct tinyds_output *output; + struct ds_output *ds_output; + const struct ds_output_mode *mode; + + server = wl_container_of(listener, server, new_output); + ds_output = data; + + ds_inf("New output(%p)", ds_output); + + if (server->output) + return; + + mode = ds_output_get_preferred_mode(ds_output); + ds_output_set_mode(ds_output, mode); + + output = calloc(1, sizeof *output); + if (!output) + return; + + output->server = server; + output->ds_output = ds_output; + output->width = mode->width; + output->height = mode->height; + output->damaged = true; + output->commitable = true; + +#ifdef USE_TDM_BUFFER_QUEUE + output_buffer_queue_init(output); + output_renderer_init(output); +#else + output_swapchain_init(output, mode->width, mode->height, + DRM_FORMAT_XRGB8888); +#endif + + output_hwc_init(output); + + output->output_destroy.notify = output_handle_destroy; + ds_output_add_destroy_listener(ds_output, &output->output_destroy); + + output->output_frame.notify = output_handle_frame; + ds_output_add_frame_listener(ds_output, &output->output_frame); + + server->output = output; + + output_schedule_commit(output); +} + +static bool +init_server(struct tinyds_server *server, struct wl_display *display) +{ + server->display = display; + + wl_list_init(&server->views); + + if (wl_display_init_shm(display) != 0) + return false; + + server->backend = ds_tdm_backend_create(display); + if (!server->backend) + return false; + + server->new_output.notify = backend_handle_new_output; + ds_backend_add_new_output_listener(server->backend, + &server->new_output); + + server->compositor = ds_compositor_create(display); + if (!server->compositor) { + ds_backend_destroy(server->backend); + return false; + } + + server->tbm_server = ds_tbm_server_create(display); + if (!server->tbm_server) { + ds_backend_destroy(server->backend); + return false; + } + + server->xdg_shell = ds_xdg_shell_create(display); + if (!server->xdg_shell) { + ds_backend_destroy(server->backend); + return false; + } + + server->new_xdg_surface.notify = server_new_xdg_surface; + ds_xdg_shell_add_new_surface_listener(server->xdg_shell, + &server->new_xdg_surface); + + return true; +} + +static void +output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) +{ + struct tinyds_output *output = + wl_container_of(listener, output, output_destroy); + + wl_list_remove(&output->output_destroy.link); + wl_list_remove(&output->output_frame.link); + + if (output->front_buffer) + ds_buffer_unlock(output->front_buffer); + +#ifdef USE_TDM_BUFFER_QUEUE + fini_renderer(&output->renderer); +#else + if (output->swapchain) + ds_swapchain_destroy(output->swapchain); + + if (output->allocator) + ds_allocator_destroy(output->allocator); +#endif + + wl_display_terminate(output->server->display); + + output->server->output = NULL; + + free(output); +} +static void +output_commit(struct tinyds_output *output) +{ + uint32_t num_changed = 0; + uint32_t num_windows = 0, current_num_windows = 0; + struct ds_tdm_output_hwc_window **composited_hwc_windows = NULL; + struct ds_tdm_output_hwc_window **changed_hwc_windows = NULL; + enum ds_tdm_output_hwc_window_composition composition; + struct tinyds_view *view; + int i; + bool need_target = false; + + if (!output->commitable || !output->damaged) + return; + + wl_list_for_each_reverse(view, &output->server->views, link) { + if (!view->hwc_window) + continue; + + if (view->mapped) + num_windows++; + } + + if (num_windows) { + composited_hwc_windows = calloc(num_windows, sizeof *composited_hwc_windows); + if (!composited_hwc_windows) + return; + } + + wl_list_for_each_reverse(view, &output->server->views, link) { + struct ds_buffer *ds_buffer; + struct ds_tdm_box src_box; + int w = 0, h = 0; + + if (!view->hwc_window) + continue; + + ds_buffer = ds_surface_get_buffer( + ds_xdg_surface_get_surface(view->xdg_surface)); + if (!ds_buffer) + continue; + + ds_tdm_output_hwc_window_set_buffer(view->hwc_window, ds_buffer); + + if (ds_buffer) + ds_buffer_get_size(ds_buffer, &w, &h); + + src_box.x = 0; + src_box.y = 0; + src_box.width = w; + src_box.height = h; + + ds_tdm_output_hwc_window_set_src_box(view->hwc_window, &src_box); + ds_tdm_output_hwc_window_set_position(view->hwc_window, view->x, view->y); + ds_tdm_output_hwc_window_set_dest_size(view->hwc_window, w, h); + ds_tdm_output_hwc_window_set_transform(view->hwc_window, WL_OUTPUT_TRANSFORM_NORMAL); + + if (view->mapped) { + ds_tdm_output_hwc_window_set_composition(view->hwc_window, + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE); + + composited_hwc_windows[current_num_windows] = view->hwc_window; + current_num_windows++; + } else { + ds_tdm_output_hwc_window_set_composition(view->hwc_window, + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE); + } + } + + if (!ds_tdm_output_hwc_validate(output->hwc, composited_hwc_windows, + num_windows, &num_changed)) { + free(composited_hwc_windows); + ds_err("Could not hwc validate"); + return; + } + + if (composited_hwc_windows) + free(composited_hwc_windows); + + if (num_changed > 0) { + changed_hwc_windows = calloc(num_windows, sizeof *changed_hwc_windows); + if (!changed_hwc_windows) + return; + + if (!ds_tdm_output_hwc_get_changed_composition(output->hwc, &num_changed, + changed_hwc_windows)) { + ds_err("Could not get chaged composition"); + return; + } + + for (i = 0; i < num_changed; i++) { + composition = ds_tdm_output_hwc_window_get_composition(changed_hwc_windows[i]); + if (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT) { + need_target = true; + break; + } + } + } + + if (changed_hwc_windows) + free(changed_hwc_windows); + + if (!ds_tdm_output_hwc_accept_validation(output->hwc)) { + ds_err("Could not hwc accept validateion"); + return; + } + + if (need_target) + draw_output(output); + +#ifdef USE_TDM_BUFFER_QUEUE + struct ds_buffer *buffer; + + buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue); + if (buffer) + output_swap_buffer(output, buffer); +#endif + + ds_output_commit(output->ds_output); + + output->commitable = false; + output->damaged = false; + + wl_list_for_each(view, &output->server->views, link) { + enum ds_tdm_output_hwc_window_composition composition; + + if (!view->mapped) + continue; + + composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window); + if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR)) + view_send_frame_done(view); + } + + ds_inf("output:%p commit", output); +} + +static void +output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED) +{ + struct tinyds_output *output = + wl_container_of(listener, output, output_frame); + + ds_inf("output:%p handle frame", output); + + output->commitable = true; + + output_commit(output); +} + +static void +draw_server_with_damage(struct tinyds_server *server) +{ + server->output->damaged = true; + output_schedule_commit(server->output); +} + +static void +output_hwc_init(struct tinyds_output *output) +{ + struct ds_tdm_output *tdm_output; + + tdm_output = ds_tdm_output_from_output(output->ds_output); + assert(tdm_output); + + output->hwc = ds_tdm_output_get_hwc(tdm_output); + assert(output->hwc); + + ds_tdm_output_hwc_set_enabled(output->hwc, true); +} + +#ifdef USE_TDM_BUFFER_QUEUE +static void +output_handle_buffer_queue_acquirable(struct wl_listener *listener, + void *data TINYDS_UNUSED) +{ + struct tinyds_output *output; + + output = wl_container_of(listener, output, buffer_queue_acquirable); + + draw_server_with_damage(output->server); +} + +static void +output_buffer_queue_init(struct tinyds_output *output) +{ + struct ds_tdm_output *tdm_output; + + tdm_output = ds_tdm_output_from_output(output->ds_output); + assert(tdm_output); + + output->buffer_queue = ds_tdm_output_get_buffer_queue(tdm_output); + assert(output->buffer_queue); + + output->buffer_queue_acquirable.notify = + output_handle_buffer_queue_acquirable; + ds_tdm_buffer_queue_add_acquirable_listener(output->buffer_queue, + &output->buffer_queue_acquirable); +} + +static void +output_renderer_init(struct tinyds_output *output) +{ + init_renderer(&output->renderer); + + renderer_set_surface_queue(&output->renderer, + ds_tdm_buffer_queue_get_native_queue(output->buffer_queue)); + + renderer_set_bg_color(&output->renderer, 0, 0, 0); +} + +static void +output_draw_with_renderer(struct tinyds_output *output) +{ + struct tinyds_view *view; + + ds_dbg(">> BEGIN UPDATE TEXTURES"); + + wl_list_for_each(view, &output->server->views, link) { + struct ds_buffer *ds_buffer; + struct ds_tbm_client_buffer *tbm_buffer; + tbm_surface_h surface; + enum ds_tdm_output_hwc_window_composition composition; + + if (!view->mapped) + continue; + + composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window); + if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR)) + continue; + + ds_buffer = ds_surface_get_buffer( + ds_xdg_surface_get_surface(view->xdg_surface)); + assert(ds_buffer); + + tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer); + assert(tbm_buffer); + + surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer); + + renderer_add_texture(&output->renderer, surface, view->x, view->y); + + view_send_frame_done(view); + } + + ds_dbg("<< END UPDATE TEXTURES"); + + renderer_draw(&output->renderer); +} + +#else +static void +output_swapchain_init(struct tinyds_output *output, + int width, int height, uint32_t format) + +{ + output->allocator = ds_tbm_allocator_create(); + assert(output->allocator); + + output->swapchain = ds_swapchain_create(output->allocator, + width, height, format); + assert(output->swapchain); +} + +static void +output_draw_with_swapchain(struct tinyds_output *output) +{ + struct tinyds_view *view; + struct ds_buffer *output_buffer; + pixman_image_t *output_image; + enum ds_tdm_output_hwc_window_composition composition; + + output_buffer = ds_swapchain_acquire(output->swapchain, NULL); + if (!output_buffer) + return; + + output_image = pixman_image_from_buffer(output_buffer, + DS_BUFFER_DATA_PTR_ACCESS_WRITE); + if (!output_image) { + ds_buffer_unlock(output_buffer); + return; + } + + pixman_image_fill_color(output_image, 0, 0, 0); + + wl_list_for_each(view, &output->server->views, link) { + if (!view->mapped) + continue; + + composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window); + if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR)) + continue; + + draw_view(view, output_image); + } + pixman_image_unref(output_image); + + output_swap_buffer(output, output_buffer); +} + +static void +draw_view(struct tinyds_view *view, pixman_image_t *dst_image) +{ + struct ds_buffer *buffer; + pixman_image_t *src_image; + + buffer = ds_surface_get_buffer( + ds_xdg_surface_get_surface(view->xdg_surface)); + if (!buffer) + return; + + src_image = pixman_image_from_buffer(buffer, + DS_BUFFER_DATA_PTR_ACCESS_READ); + pixman_image_composite32(PIXMAN_OP_OVER, + src_image, + NULL, + dst_image, + 0, 0, 0, 0, + view->x, view->y, + pixman_image_get_width(src_image), + pixman_image_get_height(src_image)); + pixman_image_unref(src_image); + + view_send_frame_done(view); +} +#endif + +static void +draw_output(struct tinyds_output *output) +{ +#ifdef USE_TDM_BUFFER_QUEUE + output_draw_with_renderer(output); +#else + output_draw_with_swapchain(output); +#endif + + ds_inf("output:%p draw", output); +} + +static void +output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer) +{ + ds_output_attach_buffer(output->ds_output, buffer); + + if (output->front_buffer) + ds_buffer_unlock(output->front_buffer); + output->front_buffer = buffer; +} + +static void +view_send_frame_done(struct tinyds_view *view) +{ + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface), + &now); +} + +static void +output_schedule_commit_handle_idle_timer(void *data) +{ + struct tinyds_output *output = data; + output->idle_commit = NULL; + + output_commit(output); +} + +static void +output_schedule_commit(struct tinyds_output *output) +{ + if (output->idle_commit) + return; + + output->damaged = true; + + struct wl_event_loop *ev = wl_display_get_event_loop(output->server->display); + output->idle_commit = + wl_event_loop_add_idle(ev, output_schedule_commit_handle_idle_timer, output); +} + +static int +server_dispatch_stdin(int fd, uint32_t mask, void *data) +{ + struct tinyds_server *server = data; + + wl_display_terminate(server->display); + + return 1; +} diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index c2e0180..000f5a9 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -99,6 +99,7 @@ ninja -C builddir install %{_libdir}/libds-tizen.so %{_bindir}/tdm-backend %{_bindir}/tinyds-tdm +%{_bindir}/tinyds-tdm-hwc %{_bindir}/ds-simple-tbm %{_bindir}/tinyds-tdm-dpms %{_bindir}/ds-simple-dpms -- 2.7.4 From 5f18020e1cc613b66afcc24ce241f0db6e675755 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 10 Jun 2022 10:14:06 +0900 Subject: [PATCH 07/16] keyrouter: Use macro for keyrouter version Change-Id: Ifb199c1e5cf7e64d5e9f7cc7c4687093639c0cfc --- src/keyrouter/keyrouter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index 2e95e48..0a67641 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -12,6 +12,8 @@ #include "util.h" #include "keyrouter.h" +#define TIZEN_KEYROUTER_VERSION 2 + static void keyrouter_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id); @@ -64,7 +66,7 @@ ds_tizen_keyrouter_create(struct wl_display *display) } keyrouter->global = wl_global_create(display, &tizen_keyrouter_interface, - 2, keyrouter, keyrouter_bind); + TIZEN_KEYROUTER_VERSION, keyrouter, keyrouter_bind); if (!keyrouter->global) { keyrouter_grab_destroy(keyrouter->keyrouter_grab); free(keyrouter); @@ -346,7 +348,8 @@ keyrouter_bind(struct wl_client *client, void *data, uint32_t version, keyrouter_client->keyrouter = keyrouter; keyrouter_client->resource = - wl_resource_create(client, &tizen_keyrouter_interface, MIN(version, 2), id); + wl_resource_create(client, &tizen_keyrouter_interface, + MIN(version, TIZEN_KEYROUTER_VERSION), id); if (keyrouter_client->resource == NULL) { ds_err("wl_resource_create() failed.(version :%d, id:%d)", version, id); free(keyrouter_client); -- 2.7.4 From 0376b430941e98661e322bd191fbe3911fffb883 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 10 Jun 2022 10:15:19 +0900 Subject: [PATCH 08/16] keyrouter: Remove unused included headers Change-Id: I3ef89c2a8ce9266e093445538ef9c4b23ec4d1f1 --- src/keyrouter/keyrouter.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index 0a67641..62753dd 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -1,10 +1,8 @@ -#include #include #include -#include -#include #include #include +#include #include #include "libds-tizen/keyrouter.h" -- 2.7.4 From e2a5301768f61ff6a889e31eb255c6d743832ebc Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 10 Jun 2022 10:42:34 +0900 Subject: [PATCH 09/16] keyrouter: Rename grabbed for more suitable name The variable 'grabbed' was only used to check to see if the associated client has been privileged. So, it's better to rename 'grabbed' to 'privileged'. Plus, it should be determined when checking privilege. Change-Id: Ibc3956b6ab6e21bf8fd3d58d9a1c4fbcce1aec67 --- src/keyrouter/keyrouter.c | 13 ++++++------- src/keyrouter/keyrouter.h | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index 62753dd..9d70fce 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -120,8 +120,6 @@ keyrouter_handle_keygrab_set(struct wl_client *client, res = keyrouter_grab_grab_key(keyrouter->keyrouter_grab, mode, key, (void *)client); - if (res == TIZEN_KEYROUTER_ERROR_NONE && keyrouter_client->grabbed != true) - keyrouter_client->grabbed = true; tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res); } @@ -210,8 +208,6 @@ keyrouter_handle_keygrab_set_list(struct wl_client *client, } else { res = keyrouter_grab_grab_key(keyrouter->keyrouter_grab, grab_data->mode, grab_data->key, (void *)client); - if (res == TIZEN_KEYROUTER_ERROR_NONE && keyrouter_client->grabbed != true) - keyrouter_client->grabbed = true; grab_data->err = res; } @@ -381,13 +377,16 @@ keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client, return true; } - // grabbed client is already checked the privilege before. - if (keyrouter_client->grabbed) + // already checked the privilege before. + if (keyrouter_client->privileged) return true; wl_client_get_credentials(client, &pid, &uid, &gid); - return tizen_security_check_privilege(pid, uid, "http://tizen.org/privilege/keygrab"); + keyrouter_client->privileged = tizen_security_check_privilege(pid, uid, + "http://tizen.org/privilege/keygrab"); + + return keyrouter_client->privileged; } static void diff --git a/src/keyrouter/keyrouter.h b/src/keyrouter/keyrouter.h index 3d88346..ab10f9b 100644 --- a/src/keyrouter/keyrouter.h +++ b/src/keyrouter/keyrouter.h @@ -66,7 +66,7 @@ struct ds_tizen_keyrouter_client struct wl_resource *resource; - bool grabbed; + bool privileged; struct wl_list link; // ds_tizen_keyrouter::clients }; -- 2.7.4 From 60e2fd5fdd251847d609293033d267651a815439 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 10 Jun 2022 10:46:04 +0900 Subject: [PATCH 10/16] keyrouter: Use macro for a string of privilege Change-Id: I586bada8424050ee660c59fc17b56b474e3ab637 --- src/keyrouter/keyrouter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index 9d70fce..4ab3734 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -11,6 +11,7 @@ #include "keyrouter.h" #define TIZEN_KEYROUTER_VERSION 2 +#define TIZEN_KEYROUTER_PRIVILEGE "http://tizen.org/privilege/keygrab" static void keyrouter_bind(struct wl_client *client, void *data, uint32_t version, @@ -384,7 +385,7 @@ keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client, wl_client_get_credentials(client, &pid, &uid, &gid); keyrouter_client->privileged = tizen_security_check_privilege(pid, uid, - "http://tizen.org/privilege/keygrab"); + TIZEN_KEYROUTER_PRIVILEGE); return keyrouter_client->privileged; } -- 2.7.4 From 54c632c3954c9c96758bd868e2a41233b91430f3 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 10 Jun 2022 10:52:34 +0900 Subject: [PATCH 11/16] keyrouter: Rename keyrouter_client to client for shorter name Change-Id: Ic4e1397f3fee212d4dff9e3d433384b964e0a47a --- src/keyrouter/keyrouter.c | 132 +++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index 4ab3734..199af6b 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -14,11 +14,11 @@ #define TIZEN_KEYROUTER_PRIVILEGE "http://tizen.org/privilege/keygrab" static void -keyrouter_bind(struct wl_client *client, void *data, uint32_t version, +keyrouter_bind(struct wl_client *wl_client, void *data, uint32_t version, uint32_t id); static bool -keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client, - struct wl_client *client, uint32_t mode, uint32_t keycode); +keyrouter_check_privilege(struct ds_tizen_keyrouter_client *client, + struct wl_client *wl_client, uint32_t mode, uint32_t keycode); static void keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter); @@ -100,19 +100,19 @@ ds_tizen_keyrouter_add_destroy_listener(struct ds_tizen_keyrouter *keyrouter, } static void -keyrouter_handle_keygrab_set(struct wl_client *client, +keyrouter_handle_keygrab_set(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode) { - struct ds_tizen_keyrouter_client *keyrouter_client; + struct ds_tizen_keyrouter_client *client; struct ds_tizen_keyrouter *keyrouter; int res = TIZEN_KEYROUTER_ERROR_NONE; bool ret; - keyrouter_client = wl_resource_get_user_data(resource); - keyrouter = keyrouter_client->keyrouter; + client = wl_resource_get_user_data(resource); + keyrouter = client->keyrouter; - ret = keyrouter_check_privilege(keyrouter_client, client, mode, key); + ret = keyrouter_check_privilege(client, wl_client, mode, key); if (ret == false) { tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, TIZEN_KEYROUTER_ERROR_NO_PERMISSION); @@ -120,29 +120,29 @@ keyrouter_handle_keygrab_set(struct wl_client *client, } res = keyrouter_grab_grab_key(keyrouter->keyrouter_grab, - mode, key, (void *)client); + mode, key, (void *)wl_client); tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res); } static void -keyrouter_handle_keygrab_unset(struct wl_client *client, +keyrouter_handle_keygrab_unset(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key) { - struct ds_tizen_keyrouter_client *keyrouter_client; + struct ds_tizen_keyrouter_client *client; struct ds_tizen_keyrouter *keyrouter; int res = TIZEN_KEYROUTER_ERROR_NONE; bool ret; - keyrouter_client = wl_resource_get_user_data(resource); - keyrouter = keyrouter_client->keyrouter; + client = wl_resource_get_user_data(resource); + keyrouter = client->keyrouter; /* ungrab TOP POSITION grab first, this grab mode is not check privilege */ keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, - TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)client); + TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)wl_client); - ret = keyrouter_check_privilege(keyrouter_client, - client, TIZEN_KEYROUTER_MODE_NONE, key); + ret = keyrouter_check_privilege(client, + wl_client, TIZEN_KEYROUTER_MODE_NONE, key); if (ret == false) { tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, TIZEN_KEYROUTER_ERROR_NO_PERMISSION); @@ -150,19 +150,19 @@ keyrouter_handle_keygrab_unset(struct wl_client *client, } keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, - TIZEN_KEYROUTER_MODE_EXCLUSIVE, key, (void *)client); + TIZEN_KEYROUTER_MODE_EXCLUSIVE, key, (void *)wl_client); keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, - TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, key, (void *)client); + TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, key, (void *)wl_client); keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, - TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)client); + TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)wl_client); keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, - TIZEN_KEYROUTER_MODE_SHARED, key, (void *)client); + TIZEN_KEYROUTER_MODE_SHARED, key, (void *)wl_client); tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res); } static void -keyrouter_handle_get_keygrab_status(struct wl_client *client, +keyrouter_handle_get_keygrab_status(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key) { tizen_keyrouter_send_keygrab_notify(resource, surface, key, @@ -183,18 +183,18 @@ keyrouter_get_array_length(const struct wl_array *array) } static void -keyrouter_handle_keygrab_set_list(struct wl_client *client, +keyrouter_handle_keygrab_set_list(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list) { - struct ds_tizen_keyrouter_client *keyrouter_client; + struct ds_tizen_keyrouter_client *client; struct ds_tizen_keyrouter *keyrouter; struct wl_array *return_list; struct ds_tizen_grab_data *grab_data = NULL; int res = TIZEN_KEYROUTER_ERROR_NONE; bool ret; - keyrouter_client = wl_resource_get_user_data(resource); - keyrouter = keyrouter_client->keyrouter; + client = wl_resource_get_user_data(resource); + keyrouter = client->keyrouter; if ((keyrouter_get_array_length(grab_list) % 3) != 0) { ds_err("Invalid keycode and grab mode pair. Check arguments in a list."); @@ -203,12 +203,12 @@ keyrouter_handle_keygrab_set_list(struct wl_client *client, } wl_array_for_each(grab_data, grab_list) { - ret = keyrouter_check_privilege(keyrouter_client, client, grab_data->mode, grab_data->key); + ret = keyrouter_check_privilege(client, wl_client, grab_data->mode, grab_data->key); if (ret == false) { grab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; } else { res = keyrouter_grab_grab_key(keyrouter->keyrouter_grab, - grab_data->mode, grab_data->key, (void *)client); + grab_data->mode, grab_data->key, (void *)wl_client); grab_data->err = res; } @@ -220,18 +220,18 @@ keyrouter_handle_keygrab_set_list(struct wl_client *client, } static void -keyrouter_handle_keygrab_unset_list(struct wl_client *client, +keyrouter_handle_keygrab_unset_list(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *ungrab_list) { - struct ds_tizen_keyrouter_client *keyrouter_client; + struct ds_tizen_keyrouter_client *client; struct ds_tizen_keyrouter *keyrouter; struct wl_array *return_list = NULL; struct ds_tizen_ungrab_data *ungrab_data = NULL; bool ret; - keyrouter_client = wl_resource_get_user_data(resource); - keyrouter = keyrouter_client->keyrouter; + client = wl_resource_get_user_data(resource); + keyrouter = client->keyrouter; if ((keyrouter_get_array_length(ungrab_list) % 3) != 0) { ds_err("Invalid keycode and grab mode pair. Check arguments in a list."); @@ -241,24 +241,24 @@ keyrouter_handle_keygrab_unset_list(struct wl_client *client, wl_array_for_each(ungrab_data, ungrab_list) { keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, - TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)client); + TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)wl_client); - ret = keyrouter_check_privilege(keyrouter_client, client, + ret = keyrouter_check_privilege(client, wl_client, TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key); if (!ret) { ungrab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; } else { keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, - TIZEN_KEYROUTER_MODE_EXCLUSIVE, ungrab_data->key, (void *)client); + TIZEN_KEYROUTER_MODE_EXCLUSIVE, ungrab_data->key, (void *)wl_client); keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, - TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, ungrab_data->key, (void *)client); + TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, ungrab_data->key, (void *)wl_client); keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, - TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)client); + TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)wl_client); keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, - TIZEN_KEYROUTER_MODE_SHARED, ungrab_data->key, (void *)client); + TIZEN_KEYROUTER_MODE_SHARED, ungrab_data->key, (void *)wl_client); ungrab_data->err = TIZEN_KEYROUTER_ERROR_NONE; } @@ -270,14 +270,14 @@ keyrouter_handle_keygrab_unset_list(struct wl_client *client, } static void -keyrouter_handle_get_keygrab_list(struct wl_client *client, +keyrouter_handle_get_keygrab_list(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface) { tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL); } static void -keyrouter_handle_set_register_none_key(struct wl_client *client, +keyrouter_handle_set_register_none_key(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, uint32_t data) { @@ -285,14 +285,14 @@ keyrouter_handle_set_register_none_key(struct wl_client *client, } static void -keyrouter_handle_get_keyregister_status(struct wl_client *client, +keyrouter_handle_get_keyregister_status(struct wl_client *wl_client, struct wl_resource *resource, uint32_t key) { tizen_keyrouter_send_keyregister_notify(resource, (int)false); } static void -keyrouter_handle_set_input_config(struct wl_client *client, +keyrouter_handle_set_input_config(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, uint32_t config_mode, uint32_t value) { @@ -300,7 +300,7 @@ keyrouter_handle_set_input_config(struct wl_client *client, } static void -keyrouter_handle_destory(struct wl_client *client, +keyrouter_handle_destory(struct wl_client *wl_client, struct wl_resource *resource) { wl_resource_destroy(resource); @@ -322,47 +322,47 @@ static const struct tizen_keyrouter_interface tizen_keyrouter_impl = { static void keyrouter_handle_resource_destory(struct wl_resource *resource) { - struct ds_tizen_keyrouter_client *keyrouter_client = wl_resource_get_user_data(resource); + struct ds_tizen_keyrouter_client *client = wl_resource_get_user_data(resource); - wl_list_remove(&keyrouter_client->link); - free(keyrouter_client); + wl_list_remove(&client->link); + free(client); } static void -keyrouter_bind(struct wl_client *client, void *data, uint32_t version, +keyrouter_bind(struct wl_client *wl_client, void *data, uint32_t version, uint32_t id) { struct ds_tizen_keyrouter *keyrouter = data; - struct ds_tizen_keyrouter_client *keyrouter_client; + struct ds_tizen_keyrouter_client *client; - keyrouter_client = calloc(1, sizeof *keyrouter_client); - if (keyrouter_client == NULL) { - wl_client_post_no_memory(client); + client = calloc(1, sizeof *client); + if (client == NULL) { + wl_client_post_no_memory(wl_client); return; } - keyrouter_client->keyrouter = keyrouter; - keyrouter_client->resource = - wl_resource_create(client, &tizen_keyrouter_interface, + client->keyrouter = keyrouter; + client->resource = + wl_resource_create(wl_client, &tizen_keyrouter_interface, MIN(version, TIZEN_KEYROUTER_VERSION), id); - if (keyrouter_client->resource == NULL) { + if (client->resource == NULL) { ds_err("wl_resource_create() failed.(version :%d, id:%d)", version, id); - free(keyrouter_client); - wl_client_post_no_memory(client); + free(client); + wl_client_post_no_memory(wl_client); return; } - wl_resource_set_implementation(keyrouter_client->resource, &tizen_keyrouter_impl, - keyrouter_client, keyrouter_handle_resource_destory); + wl_resource_set_implementation(client->resource, &tizen_keyrouter_impl, + client, keyrouter_handle_resource_destory); - wl_list_insert(&keyrouter->clients, &keyrouter_client->link); + wl_list_insert(&keyrouter->clients, &client->link); } static bool -keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client, - struct wl_client *client, uint32_t mode, uint32_t keycode) +keyrouter_check_privilege(struct ds_tizen_keyrouter_client *client, + struct wl_client *wl_client, uint32_t mode, uint32_t keycode) { - struct ds_tizen_keyrouter *keyrouter = keyrouter_client->keyrouter; + struct ds_tizen_keyrouter *keyrouter = client->keyrouter; pid_t pid = 0; uid_t uid = 0; @@ -379,15 +379,15 @@ keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client, } // already checked the privilege before. - if (keyrouter_client->privileged) + if (client->privileged) return true; - wl_client_get_credentials(client, &pid, &uid, &gid); + wl_client_get_credentials(wl_client, &pid, &uid, &gid); - keyrouter_client->privileged = tizen_security_check_privilege(pid, uid, + client->privileged = tizen_security_check_privilege(pid, uid, TIZEN_KEYROUTER_PRIVILEGE); - return keyrouter_client->privileged; + return client->privileged; } static void -- 2.7.4 From 9b2ff241cf17b7f708c0a7d00b590c9cb63f4e81 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 10 Jun 2022 11:07:32 +0900 Subject: [PATCH 12/16] keyrouter: Rename keyrouter_grab for shorter name Change-Id: I30b62158ede60976ac760d39bafb894f274acf21 --- src/keyrouter/keyrouter.c | 32 ++++++------ src/keyrouter/keyrouter.h | 16 +++--- src/keyrouter/keyrouter_grab.c | 116 ++++++++++++++++++++--------------------- 3 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index 199af6b..730b8a8 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -42,7 +42,7 @@ keyrouter_handle_display_destroy(struct wl_listener *listener, void *data) wl_global_destroy(keyrouter->global); - keyrouter_grab_destroy(keyrouter->keyrouter_grab); + keyrouter_grab_destroy(keyrouter->keygrab); free(keyrouter); } @@ -57,8 +57,8 @@ ds_tizen_keyrouter_create(struct wl_display *display) return NULL; } - keyrouter->keyrouter_grab = keyrouter_grab_create(); - if (keyrouter->keyrouter_grab == NULL) { + keyrouter->keygrab = keyrouter_grab_create(); + if (keyrouter->keygrab == NULL) { ds_err("Failed to create keyrouter."); free(keyrouter); return NULL; @@ -67,7 +67,7 @@ ds_tizen_keyrouter_create(struct wl_display *display) keyrouter->global = wl_global_create(display, &tizen_keyrouter_interface, TIZEN_KEYROUTER_VERSION, keyrouter, keyrouter_bind); if (!keyrouter->global) { - keyrouter_grab_destroy(keyrouter->keyrouter_grab); + keyrouter_grab_destroy(keyrouter->keygrab); free(keyrouter); return NULL; } @@ -119,7 +119,7 @@ keyrouter_handle_keygrab_set(struct wl_client *wl_client, return; } - res = keyrouter_grab_grab_key(keyrouter->keyrouter_grab, + res = keyrouter_grab_grab_key(keyrouter->keygrab, mode, key, (void *)wl_client); tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res); @@ -138,7 +138,7 @@ keyrouter_handle_keygrab_unset(struct wl_client *wl_client, keyrouter = client->keyrouter; /* ungrab TOP POSITION grab first, this grab mode is not check privilege */ - keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keygrab, TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)wl_client); ret = keyrouter_check_privilege(client, @@ -149,13 +149,13 @@ keyrouter_handle_keygrab_unset(struct wl_client *wl_client, return; } - keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keygrab, TIZEN_KEYROUTER_MODE_EXCLUSIVE, key, (void *)wl_client); - keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keygrab, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, key, (void *)wl_client); - keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keygrab, TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)wl_client); - keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keygrab, TIZEN_KEYROUTER_MODE_SHARED, key, (void *)wl_client); tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res); @@ -207,7 +207,7 @@ keyrouter_handle_keygrab_set_list(struct wl_client *wl_client, if (ret == false) { grab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; } else { - res = keyrouter_grab_grab_key(keyrouter->keyrouter_grab, + res = keyrouter_grab_grab_key(keyrouter->keygrab, grab_data->mode, grab_data->key, (void *)wl_client); grab_data->err = res; @@ -240,7 +240,7 @@ keyrouter_handle_keygrab_unset_list(struct wl_client *wl_client, } wl_array_for_each(ungrab_data, ungrab_list) { - keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keygrab, TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)wl_client); ret = keyrouter_check_privilege(client, wl_client, @@ -248,16 +248,16 @@ keyrouter_handle_keygrab_unset_list(struct wl_client *wl_client, if (!ret) { ungrab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; } else { - keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keygrab, TIZEN_KEYROUTER_MODE_EXCLUSIVE, ungrab_data->key, (void *)wl_client); - keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keygrab, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, ungrab_data->key, (void *)wl_client); - keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keygrab, TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)wl_client); - keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keygrab, TIZEN_KEYROUTER_MODE_SHARED, ungrab_data->key, (void *)wl_client); ungrab_data->err = TIZEN_KEYROUTER_ERROR_NONE; diff --git a/src/keyrouter/keyrouter.h b/src/keyrouter/keyrouter.h index ab10f9b..11fbadc 100644 --- a/src/keyrouter/keyrouter.h +++ b/src/keyrouter/keyrouter.h @@ -55,7 +55,7 @@ struct ds_tizen_keyrouter struct ds_tizen_keyrouter_key_options *opts; - struct ds_tizen_keyrouter_grab *keyrouter_grab; + struct ds_tizen_keyrouter_grab *keygrab; bool security_initialized; }; @@ -87,24 +87,24 @@ struct ds_tizen_ungrab_data struct ds_tizen_keyrouter_grab * keyrouter_grab_create(void); void -keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keyrouter_grab); +keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keygrab); int -keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keygrab, int type, int keycode, void *data); void -keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keygrab, int type, int keycode, void *data); int -keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keygrab, int keycode, int pressed, struct wl_list *delivery_list); void -keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keygrab, void *focus_client); void -keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keygrab, void *top_client); bool -keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keygrab, int keycode); #endif diff --git a/src/keyrouter/keyrouter_grab.c b/src/keyrouter/keyrouter_grab.c index 6af0c85..755f6d4 100644 --- a/src/keyrouter/keyrouter_grab.c +++ b/src/keyrouter/keyrouter_grab.c @@ -6,41 +6,41 @@ #include "keyrouter.h" static struct wl_list * -keyrouter_grab_get_grabbed_list(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_get_grabbed_list(struct ds_tizen_keyrouter_grab *keygrab, int type, int keycode) { switch(type) { case TIZEN_KEYROUTER_MODE_EXCLUSIVE: - return &keyrouter_grab->hard_keys[keycode].grab.excl; + return &keygrab->hard_keys[keycode].grab.excl; case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE: - return &keyrouter_grab->hard_keys[keycode].grab.or_excl; + return &keygrab->hard_keys[keycode].grab.or_excl; case TIZEN_KEYROUTER_MODE_TOPMOST: - return &keyrouter_grab->hard_keys[keycode].grab.top; + return &keygrab->hard_keys[keycode].grab.top; case TIZEN_KEYROUTER_MODE_SHARED: - return &keyrouter_grab->hard_keys[keycode].grab.shared; + return &keygrab->hard_keys[keycode].grab.shared; default: return NULL; } } bool -keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, int keycode) +keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keygrab, int keycode) { struct wl_list *list; - list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_EXCLUSIVE, keycode); + list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_EXCLUSIVE, keycode); if (list && !wl_list_empty(list)) return true; - list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, keycode); + list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, keycode); if (list && !wl_list_empty(list)) return true; - list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_TOPMOST, keycode); + list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_TOPMOST, keycode); if (list && !wl_list_empty(list)) return true; - list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_SHARED, keycode); + list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_SHARED, keycode); if (list && !wl_list_empty(list)) return true; @@ -64,13 +64,13 @@ keyrouter_grab_check_duplicated_data(struct wl_list *list, void *data) } static bool -keyrouter_grab_check_grabbed(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_check_grabbed(struct ds_tizen_keyrouter_grab *keygrab, int type, int keycode, void *data) { struct wl_list *list; bool ret; - list = keyrouter_grab_get_grabbed_list(keyrouter_grab, type, keycode); + list = keyrouter_grab_get_grabbed_list(keygrab, type, keycode); if (list == NULL) { ds_err("keycode(%d) had no list for type(%d).", keycode, type); return false; @@ -101,10 +101,10 @@ keyrouter_grab_check_grabbed(struct ds_tizen_keyrouter_grab *keyrouter_grab, } void -keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keygrab, void *focus_client) { - keyrouter_grab->focus_client = focus_client; + keygrab->focus_client = focus_client; if (focus_client) ds_dbg("[%s] focus client has been set. (focus_client=0x%p)", __FUNCTION__, focus_client); @@ -113,9 +113,9 @@ keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, } void -keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, void *top_client) +keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keygrab, void *top_client) { - keyrouter_grab->top_client = top_client; + keygrab->top_client = top_client; if (top_client) ds_dbg("[%s] top client has been set. (top_client=0x%p)", __FUNCTION__, top_client); @@ -124,7 +124,7 @@ keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, vo } int -keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keygrab, int keycode, int pressed, struct wl_list *delivery_list) { struct ds_tizen_keyrouter_key_info *info, *delivery; @@ -135,8 +135,8 @@ keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, return 0; } - if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.excl)) { - info = wl_container_of(keyrouter_grab->hard_keys[keycode].grab.excl.next, info, link); + if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.excl)) { + info = wl_container_of(keygrab->hard_keys[keycode].grab.excl.next, info, link); if (info) { delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); if (delivery == NULL) { @@ -148,8 +148,8 @@ keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, ds_dbg("Exclusive Mode: keycode: %d to data: %p", keycode, info->data); return 1; } - } else if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.or_excl)) { - info = wl_container_of(keyrouter_grab->hard_keys[keycode].grab.or_excl.next, info, link); + } else if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.or_excl)) { + info = wl_container_of(keygrab->hard_keys[keycode].grab.or_excl.next, info, link); if (info) { delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); if (delivery == NULL) { @@ -161,9 +161,9 @@ keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, ds_dbg("OR-Excl Mode: keycode: %d to data: %p", keycode, info->data); return 1; } - } else if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.top)) { - wl_list_for_each(info, &keyrouter_grab->hard_keys[keycode].grab.top, link) { - if (keyrouter_grab->top_client && keyrouter_grab->top_client == info->data) { + } else if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.top)) { + wl_list_for_each(info, &keygrab->hard_keys[keycode].grab.top, link) { + if (keygrab->top_client && keygrab->top_client == info->data) { delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); if (delivery == NULL) { ds_err("Failed to allocate memory."); @@ -177,21 +177,21 @@ keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, } } - if (keyrouter_grab->focus_client) { + if (keygrab->focus_client) { delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); if (delivery == NULL) { ds_err("Failed to allocate memory."); return 0; } - delivery->data = keyrouter_grab->focus_client; + delivery->data = keygrab->focus_client; wl_list_insert(delivery_list, &delivery->link); count++; ds_dbg("Focus: keycode: %d to data: %p, count: %d", keycode, delivery->data, count); } - if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.shared)) { - wl_list_for_each(info, &keyrouter_grab->hard_keys[keycode].grab.shared, link) { - if (keyrouter_grab->focus_client && keyrouter_grab->focus_client == info->data) + if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.shared)) { + wl_list_for_each(info, &keygrab->hard_keys[keycode].grab.shared, link) { + if (keygrab->focus_client && keygrab->focus_client == info->data) continue; delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); if (delivery == NULL) { @@ -209,7 +209,7 @@ keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, } int -keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keygrab, int type, int keycode, void *data) { struct ds_tizen_keyrouter_key_info *info = NULL; @@ -220,7 +220,7 @@ keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, return TIZEN_KEYROUTER_ERROR_INVALID_KEY; } - if (keyrouter_grab_check_grabbed(keyrouter_grab, type, keycode, data)) + if (keyrouter_grab_check_grabbed(keygrab, type, keycode, data)) return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY; info = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); @@ -232,15 +232,15 @@ keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, wl_list_init(&info->link); - list = keyrouter_grab_get_grabbed_list(keyrouter_grab, type, keycode); + list = keyrouter_grab_get_grabbed_list(keygrab, type, keycode); if (!list) { ds_err("keycode(%d) had no list for type(%d)", keycode, type); free(info); return TIZEN_KEYROUTER_ERROR_INVALID_MODE; } - if (!keyrouter_grab->hard_keys[keycode].keycode) - keyrouter_grab->hard_keys[keycode].keycode = keycode; + if (!keygrab->hard_keys[keycode].keycode) + keygrab->hard_keys[keycode].keycode = keycode; wl_list_insert(list, &info->link); @@ -264,7 +264,7 @@ keyrouter_list_remove_data(struct wl_list *list, void *data) } void -keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keygrab, int type, int keycode, void *data) { struct wl_list *list; @@ -274,10 +274,10 @@ keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, return; } - if (keyrouter_grab->hard_keys[keycode].keycode == 0) + if (keygrab->hard_keys[keycode].keycode == 0) return; - list = keyrouter_grab_get_grabbed_list(keyrouter_grab, type, keycode); + list = keyrouter_grab_get_grabbed_list(keygrab, type, keycode); if (list == NULL) { ds_err("keycode(%d) had no list for type(%d)", keycode, type); return; @@ -289,34 +289,34 @@ keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, struct ds_tizen_keyrouter_grab * keyrouter_grab_create(void) { - struct ds_tizen_keyrouter_grab *keyrouter_grab = NULL; + struct ds_tizen_keyrouter_grab *keygrab = NULL; int i; - keyrouter_grab = calloc(1, sizeof(struct ds_tizen_keyrouter_grab)); - if (keyrouter_grab == NULL) { + keygrab = calloc(1, sizeof(struct ds_tizen_keyrouter_grab)); + if (keygrab == NULL) { ds_err("Failed to allocate memory."); return NULL; } /* FIXME: Who defined max keycode? */ - keyrouter_grab->hard_keys = calloc(KEYROUTER_MAX_KEYS, sizeof(struct ds_tizen_keyrouter_grabbed)); - if (keyrouter_grab->hard_keys == NULL) { + keygrab->hard_keys = calloc(KEYROUTER_MAX_KEYS, sizeof(struct ds_tizen_keyrouter_grabbed)); + if (keygrab->hard_keys == NULL) { ds_err("Failed to allocate memory."); - free(keyrouter_grab); + free(keygrab); return NULL; } for (i = 0; i < KEYROUTER_MAX_KEYS; i++) { /* Enable all of keys to grab */ - //keyrouter_grab->hard_keys[i].keycode = i; - wl_list_init(&keyrouter_grab->hard_keys[i].grab.excl); - wl_list_init(&keyrouter_grab->hard_keys[i].grab.or_excl); - wl_list_init(&keyrouter_grab->hard_keys[i].grab.top); - wl_list_init(&keyrouter_grab->hard_keys[i].grab.shared); - wl_list_init(&keyrouter_grab->hard_keys[i].pressed); + //keygrab->hard_keys[i].keycode = i; + wl_list_init(&keygrab->hard_keys[i].grab.excl); + wl_list_init(&keygrab->hard_keys[i].grab.or_excl); + wl_list_init(&keygrab->hard_keys[i].grab.top); + wl_list_init(&keygrab->hard_keys[i].grab.shared); + wl_list_init(&keygrab->hard_keys[i].pressed); } - return keyrouter_grab; + return keygrab; } static void @@ -334,18 +334,18 @@ keyrouter_grab_delete_list(struct wl_list *list) } void -keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keyrouter_grab) +keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keygrab) { int i; for (i = 0; i < KEYROUTER_MAX_KEYS; i++) { - keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.excl); - keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.or_excl); - keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.top); - keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.shared); - keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].pressed); + keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.excl); + keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.or_excl); + keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.top); + keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.shared); + keyrouter_grab_delete_list(&keygrab->hard_keys[i].pressed); } - free(keyrouter_grab->hard_keys); - free(keyrouter_grab); + free(keygrab->hard_keys); + free(keygrab); } -- 2.7.4 From fcec353fd01820db2973ab1b1e6ef577e54ce9f6 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 10 Jun 2022 14:55:24 +0900 Subject: [PATCH 13/16] keyrouter: Drop unnecessary NULL check for wl_container_of() If wl_container_of() returned null, it's not something that we treat as an exception case, but is something that we'd better fail immediately. The result of wl_container_of() is never null. Change-Id: I1812a2f148888cbd64441a2a39916c13f2f68a27 --- src/keyrouter/keyrouter_grab.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/keyrouter/keyrouter_grab.c b/src/keyrouter/keyrouter_grab.c index 755f6d4..ae29e8e 100644 --- a/src/keyrouter/keyrouter_grab.c +++ b/src/keyrouter/keyrouter_grab.c @@ -136,31 +136,27 @@ keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keygrab, } if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.excl)) { - info = wl_container_of(keygrab->hard_keys[keycode].grab.excl.next, info, link); - if (info) { - delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); - if (delivery == NULL) { - ds_err("Failed to allocate memory."); - return 0; - } - delivery->data = info->data; - wl_list_insert(delivery_list, &delivery->link); - ds_dbg("Exclusive Mode: keycode: %d to data: %p", keycode, info->data); - return 1; + delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); + if (delivery == NULL) { + ds_err("Failed to allocate memory."); + return 0; } + info = wl_container_of(keygrab->hard_keys[keycode].grab.excl.next, info, link); + delivery->data = info->data; + wl_list_insert(delivery_list, &delivery->link); + ds_dbg("Exclusive Mode: keycode: %d to data: %p", keycode, info->data); + return 1; } else if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.or_excl)) { - info = wl_container_of(keygrab->hard_keys[keycode].grab.or_excl.next, info, link); - if (info) { - delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); - if (delivery == NULL) { - ds_err("Failed to allocate memory."); - return 0; - } - delivery->data = info->data; - wl_list_insert(delivery_list, &delivery->link); - ds_dbg("OR-Excl Mode: keycode: %d to data: %p", keycode, info->data); - return 1; + delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); + if (delivery == NULL) { + ds_err("Failed to allocate memory."); + return 0; } + info = wl_container_of(keygrab->hard_keys[keycode].grab.or_excl.next, info, link); + delivery->data = info->data; + wl_list_insert(delivery_list, &delivery->link); + ds_dbg("OR-Excl Mode: keycode: %d to data: %p", keycode, info->data); + return 1; } else if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.top)) { wl_list_for_each(info, &keygrab->hard_keys[keycode].grab.top, link) { if (keygrab->top_client && keygrab->top_client == info->data) { -- 2.7.4 From d67d917ad16c8e89ee5cfd94371b04fc426ebd29 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 10 Jun 2022 14:42:22 +0900 Subject: [PATCH 14/16] keyrouter: Refactor out ds_tizen_keyrouter Change-Id: I35add1ab1c81c8589789708b8ef38f4693cc1ee2 --- include/libds-tizen/keyrouter.h | 55 +++++ src/keyrouter/keyrouter.c | 398 ++++++++++++++++----------------- src/keyrouter/keyrouter.h | 71 +++--- src/keyrouter/keyrouter_grab.c | 478 +++++++++++++++++++--------------------- 4 files changed, 509 insertions(+), 493 deletions(-) diff --git a/include/libds-tizen/keyrouter.h b/include/libds-tizen/keyrouter.h index a870003..bd47b54 100644 --- a/include/libds-tizen/keyrouter.h +++ b/include/libds-tizen/keyrouter.h @@ -7,15 +7,70 @@ extern "C" { #endif +/** + * A handle for accessing ds_tizen_keyrouter. + */ struct ds_tizen_keyrouter; +/** + * The information of keyroute + */ +struct ds_tizen_keyroute_info +{ + struct wl_client *wl_client; +}; + +/** + * Keyroute mode of keyroutes returned by ds_tizen_keyrouter_get_keyroutes() + * for a given keycode. + */ +enum ds_tizen_keyroute_mode { + /** + * The keycode is not under any keyroute mode. + * The compositor may send a keycode to a focused wayland cliet as usual. + */ + DS_TIZEN_KEYROUTE_MODE_NONE, + /** + * Exclusive mode means that a given keycode is required to be sent + * exclusively to wayland clients of returned keyroutes. So the compositor + * must not send this keycode to any other wayland clients except for + * returned wayland clients. + */ + DS_TIZEN_KEYROUTE_MODE_EXCLUSIVE, + /** + * The keycode is required to be shared with returned wayland clients. + * The compositor must send the keycode not only to returned wayland + * clients, but also to a focused wayland client. + */ + DS_TIZEN_KEYROUTE_MODE_SHARED, +}; + +/** + * Creates a ds_tizen_keyrouter. + */ struct ds_tizen_keyrouter * ds_tizen_keyrouter_create(struct wl_display *display); +/** + * Adds destroy listener of ds_tizen_keyrouter + */ void ds_tizen_keyrouter_add_destroy_listener(struct ds_tizen_keyrouter *keyrouter, struct wl_listener *listener); +/** + * Gets keyroutes and mode for a given keycode. + * The compositor must send a keycode to returned wayland clients according to + * the mode. The parameter, topmost_client, should be given to determine whether + * the given topmost_client require a keycode exclusively when one of its + * surfaces is on very top of stack. See tizen_keyrouter protocol in + * tizen-extension.xml for more detail. + */ +enum ds_tizen_keyroute_mode +ds_tizen_keyrouter_get_keyroutes(struct ds_tizen_keyrouter *keyrouter, + int keycode, struct wl_client *topmost_client, + struct wl_array *keyroutes); + #ifdef __cplusplus } #endif diff --git a/src/keyrouter/keyrouter.c b/src/keyrouter/keyrouter.c index 730b8a8..4bcee93 100644 --- a/src/keyrouter/keyrouter.c +++ b/src/keyrouter/keyrouter.c @@ -13,39 +13,21 @@ #define TIZEN_KEYROUTER_VERSION 2 #define TIZEN_KEYROUTER_PRIVILEGE "http://tizen.org/privilege/keygrab" -static void -keyrouter_bind(struct wl_client *wl_client, void *data, uint32_t version, - uint32_t id); +static void keyrouter_bind(struct wl_client *wl_client, void *data, + uint32_t version, uint32_t id); +static void keyrouter_handle_display_destroy(struct wl_listener *listener, + void *data); +static void keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter); +static void create_keyrouter_client(struct ds_tizen_keyrouter *keyrouter, + struct wl_client *wl_client, uint32_t version, uint32_t id); +static void destroy_keyrouter_client(struct keyrouter_client *client); static bool -keyrouter_check_privilege(struct ds_tizen_keyrouter_client *client, - struct wl_client *wl_client, uint32_t mode, uint32_t keycode); -static void -keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter); - -static void -keyrouter_handle_display_destroy(struct wl_listener *listener, void *data) -{ - struct ds_tizen_keyrouter *keyrouter; - - keyrouter = wl_container_of(listener, keyrouter, display_destroy); - - ds_inf("Global destroy: ds_tizen_keyrouter(%p)", keyrouter); - - wl_signal_emit(&keyrouter->events.destroy, keyrouter); - - if (keyrouter->security_initialized) - tizen_security_finish(); - - free(keyrouter->opts); - - wl_list_remove(&keyrouter->display_destroy.link); - - wl_global_destroy(keyrouter->global); - - keyrouter_grab_destroy(keyrouter->keygrab); - - free(keyrouter); -} +keyrouter_client_check_privilege(struct keyrouter_client *client, uint32_t mode, + uint32_t keycode); +static int keyrouter_client_grab_key(struct keyrouter_client *client, int mode, + int keycode); +static int keyrouter_client_ungrab_key(struct keyrouter_client *client, + int keycode); WL_EXPORT struct ds_tizen_keyrouter * ds_tizen_keyrouter_create(struct wl_display *display) @@ -57,21 +39,15 @@ ds_tizen_keyrouter_create(struct wl_display *display) return NULL; } - keyrouter->keygrab = keyrouter_grab_create(); - if (keyrouter->keygrab == NULL) { - ds_err("Failed to create keyrouter."); - free(keyrouter); - return NULL; - } - keyrouter->global = wl_global_create(display, &tizen_keyrouter_interface, TIZEN_KEYROUTER_VERSION, keyrouter, keyrouter_bind); if (!keyrouter->global) { - keyrouter_grab_destroy(keyrouter->keygrab); free(keyrouter); return NULL; } + keyrouter_grab_init(&keyrouter->keygrab); + wl_list_init(&keyrouter->clients); wl_signal_init(&keyrouter->events.destroy); @@ -99,70 +75,43 @@ 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) +{ + return keyrouter_grab_get_keyroutes(&keyrouter->keygrab, + keycode, topmost_client, keyroutes); +} + static void -keyrouter_handle_keygrab_set(struct wl_client *wl_client, +keyrouter_client_handle_set_keygrab(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode) { - struct ds_tizen_keyrouter_client *client; - struct ds_tizen_keyrouter *keyrouter; - int res = TIZEN_KEYROUTER_ERROR_NONE; - bool ret; + struct keyrouter_client *client; + int err; client = wl_resource_get_user_data(resource); - keyrouter = client->keyrouter; - - ret = keyrouter_check_privilege(client, wl_client, mode, key); - if (ret == false) { - tizen_keyrouter_send_keygrab_notify(resource, surface, - key, mode, TIZEN_KEYROUTER_ERROR_NO_PERMISSION); - return; - } - - res = keyrouter_grab_grab_key(keyrouter->keygrab, - mode, key, (void *)wl_client); - - tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res); + err = keyrouter_client_grab_key(client, mode, key); + tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, err); } static void -keyrouter_handle_keygrab_unset(struct wl_client *wl_client, +keyrouter_client_handle_unset_keygrab(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key) { - struct ds_tizen_keyrouter_client *client; - struct ds_tizen_keyrouter *keyrouter; - int res = TIZEN_KEYROUTER_ERROR_NONE; - bool ret; + struct keyrouter_client *client; + int err; client = wl_resource_get_user_data(resource); - keyrouter = client->keyrouter; - - /* ungrab TOP POSITION grab first, this grab mode is not check privilege */ - keyrouter_grab_ungrab_key(keyrouter->keygrab, - TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)wl_client); - - ret = keyrouter_check_privilege(client, - wl_client, TIZEN_KEYROUTER_MODE_NONE, key); - if (ret == false) { - tizen_keyrouter_send_keygrab_notify(resource, surface, key, - TIZEN_KEYROUTER_MODE_NONE, TIZEN_KEYROUTER_ERROR_NO_PERMISSION); - return; - } - - keyrouter_grab_ungrab_key(keyrouter->keygrab, - TIZEN_KEYROUTER_MODE_EXCLUSIVE, key, (void *)wl_client); - keyrouter_grab_ungrab_key(keyrouter->keygrab, - TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, key, (void *)wl_client); - keyrouter_grab_ungrab_key(keyrouter->keygrab, - TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)wl_client); - keyrouter_grab_ungrab_key(keyrouter->keygrab, - TIZEN_KEYROUTER_MODE_SHARED, key, (void *)wl_client); - - tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res); + err = keyrouter_client_ungrab_key(client, key); + tizen_keyrouter_send_keygrab_notify(resource, surface, key, + TIZEN_KEYROUTER_MODE_NONE, err); } static void -keyrouter_handle_get_keygrab_status(struct wl_client *wl_client, +keyrouter_client_handle_get_keygrab_status(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key) { tizen_keyrouter_send_keygrab_notify(resource, surface, key, @@ -172,29 +121,22 @@ keyrouter_handle_get_keygrab_status(struct wl_client *wl_client, static int keyrouter_get_array_length(const struct wl_array *array) { - int *data = NULL; + int *data; int count = 0; - wl_array_for_each(data, array) { + wl_array_for_each(data, array) count++; - } return count; } static void -keyrouter_handle_keygrab_set_list(struct wl_client *wl_client, +keyrouter_client_handle_set_keygrab_list(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list) { - struct ds_tizen_keyrouter_client *client; - struct ds_tizen_keyrouter *keyrouter; + struct keyrouter_client *client; + struct ds_tizen_grab_data *grab_data; struct wl_array *return_list; - struct ds_tizen_grab_data *grab_data = NULL; - int res = TIZEN_KEYROUTER_ERROR_NONE; - bool ret; - - client = wl_resource_get_user_data(resource); - keyrouter = client->keyrouter; if ((keyrouter_get_array_length(grab_list) % 3) != 0) { ds_err("Invalid keycode and grab mode pair. Check arguments in a list."); @@ -202,16 +144,11 @@ keyrouter_handle_keygrab_set_list(struct wl_client *wl_client, return; } + client = wl_resource_get_user_data(resource); + wl_array_for_each(grab_data, grab_list) { - ret = keyrouter_check_privilege(client, wl_client, grab_data->mode, grab_data->key); - if (ret == false) { - grab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; - } else { - res = keyrouter_grab_grab_key(keyrouter->keygrab, - grab_data->mode, grab_data->key, (void *)wl_client); - - grab_data->err = res; - } + grab_data->err = keyrouter_client_grab_key(client, grab_data->mode, + grab_data->key); } return_list = grab_list; @@ -220,18 +157,13 @@ keyrouter_handle_keygrab_set_list(struct wl_client *wl_client, } static void -keyrouter_handle_keygrab_unset_list(struct wl_client *wl_client, +keyrouter_client_handle_unset_keygrab_list(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *ungrab_list) { - struct ds_tizen_keyrouter_client *client; - struct ds_tizen_keyrouter *keyrouter; - struct wl_array *return_list = NULL; - struct ds_tizen_ungrab_data *ungrab_data = NULL; - bool ret; - - client = wl_resource_get_user_data(resource); - keyrouter = client->keyrouter; + struct keyrouter_client *client; + struct wl_array *return_list; + struct ds_tizen_ungrab_data *ungrab_data; if ((keyrouter_get_array_length(ungrab_list) % 3) != 0) { ds_err("Invalid keycode and grab mode pair. Check arguments in a list."); @@ -239,29 +171,11 @@ keyrouter_handle_keygrab_unset_list(struct wl_client *wl_client, return; } - wl_array_for_each(ungrab_data, ungrab_list) { - keyrouter_grab_ungrab_key(keyrouter->keygrab, - TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)wl_client); - - ret = keyrouter_check_privilege(client, wl_client, - TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key); - if (!ret) { - ungrab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; - } else { - keyrouter_grab_ungrab_key(keyrouter->keygrab, - TIZEN_KEYROUTER_MODE_EXCLUSIVE, ungrab_data->key, (void *)wl_client); - - keyrouter_grab_ungrab_key(keyrouter->keygrab, - TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, ungrab_data->key, (void *)wl_client); - - keyrouter_grab_ungrab_key(keyrouter->keygrab, - TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)wl_client); - - keyrouter_grab_ungrab_key(keyrouter->keygrab, - TIZEN_KEYROUTER_MODE_SHARED, ungrab_data->key, (void *)wl_client); + client = wl_resource_get_user_data(resource); - ungrab_data->err = TIZEN_KEYROUTER_ERROR_NONE; - } + wl_array_for_each(ungrab_data, ungrab_list) { + ungrab_data->err = keyrouter_client_ungrab_key(client, + ungrab_data->key); } return_list = ungrab_list; @@ -270,14 +184,14 @@ keyrouter_handle_keygrab_unset_list(struct wl_client *wl_client, } static void -keyrouter_handle_get_keygrab_list(struct wl_client *wl_client, +keyrouter_client_handle_get_keygrab_list(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface) { tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL); } static void -keyrouter_handle_set_register_none_key(struct wl_client *wl_client, +keyrouter_client_handle_set_register_none_key(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, uint32_t data) { @@ -285,14 +199,14 @@ keyrouter_handle_set_register_none_key(struct wl_client *wl_client, } static void -keyrouter_handle_get_keyregister_status(struct wl_client *wl_client, +keyrouter_client_handle_get_keyregister_status(struct wl_client *wl_client, struct wl_resource *resource, uint32_t key) { tizen_keyrouter_send_keyregister_notify(resource, (int)false); } static void -keyrouter_handle_set_input_config(struct wl_client *wl_client, +keyrouter_client_handle_set_input_config(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *surface, uint32_t config_mode, uint32_t value) { @@ -300,32 +214,32 @@ keyrouter_handle_set_input_config(struct wl_client *wl_client, } static void -keyrouter_handle_destory(struct wl_client *wl_client, +keyrouter_client_handle_destroy(struct wl_client *wl_client, struct wl_resource *resource) { wl_resource_destroy(resource); } static const struct tizen_keyrouter_interface tizen_keyrouter_impl = { - keyrouter_handle_keygrab_set, - keyrouter_handle_keygrab_unset, - keyrouter_handle_get_keygrab_status, - keyrouter_handle_keygrab_set_list, - keyrouter_handle_keygrab_unset_list, - keyrouter_handle_get_keygrab_list, - keyrouter_handle_set_register_none_key, - keyrouter_handle_get_keyregister_status, - keyrouter_handle_set_input_config, - keyrouter_handle_destory + .set_keygrab = keyrouter_client_handle_set_keygrab, + .unset_keygrab = keyrouter_client_handle_unset_keygrab, + .get_keygrab_status = keyrouter_client_handle_get_keygrab_status, + .set_keygrab_list = keyrouter_client_handle_set_keygrab_list, + .unset_keygrab_list = keyrouter_client_handle_unset_keygrab_list, + .get_keygrab_list = keyrouter_client_handle_get_keygrab_list, + .set_register_none_key = keyrouter_client_handle_set_register_none_key, + .get_keyregister_status = keyrouter_client_handle_get_keyregister_status, + .set_input_config = keyrouter_client_handle_set_input_config, + .destroy = keyrouter_client_handle_destroy }; static void -keyrouter_handle_resource_destory(struct wl_resource *resource) +keyrouter_client_handle_resource_destroy(struct wl_resource *resource) { - struct ds_tizen_keyrouter_client *client = wl_resource_get_user_data(resource); + struct keyrouter_client *client; - wl_list_remove(&client->link); - free(client); + client = wl_resource_get_user_data(resource); + destroy_keyrouter_client(client); } static void @@ -333,61 +247,33 @@ keyrouter_bind(struct wl_client *wl_client, void *data, uint32_t version, uint32_t id) { struct ds_tizen_keyrouter *keyrouter = data; - struct ds_tizen_keyrouter_client *client; - - client = calloc(1, sizeof *client); - if (client == NULL) { - wl_client_post_no_memory(wl_client); - return; - } - - client->keyrouter = keyrouter; - client->resource = - wl_resource_create(wl_client, &tizen_keyrouter_interface, - MIN(version, TIZEN_KEYROUTER_VERSION), id); - if (client->resource == NULL) { - ds_err("wl_resource_create() failed.(version :%d, id:%d)", version, id); - free(client); - wl_client_post_no_memory(wl_client); - return; - } - wl_resource_set_implementation(client->resource, &tizen_keyrouter_impl, - client, keyrouter_handle_resource_destory); - - wl_list_insert(&keyrouter->clients, &client->link); + create_keyrouter_client(keyrouter, wl_client, version, id); } -static bool -keyrouter_check_privilege(struct ds_tizen_keyrouter_client *client, - struct wl_client *wl_client, uint32_t mode, uint32_t keycode) +static void +keyrouter_handle_display_destroy(struct wl_listener *listener, void *data) { - struct ds_tizen_keyrouter *keyrouter = client->keyrouter; + struct ds_tizen_keyrouter *keyrouter; - pid_t pid = 0; - uid_t uid = 0; - gid_t gid = 0; + keyrouter = wl_container_of(listener, keyrouter, display_destroy); - /* Top position grab is always allowed. This mode do not need privilege.*/ - if (mode == TIZEN_KEYROUTER_MODE_TOPMOST) - return true; + ds_inf("Global destroy: ds_tizen_keyrouter(%p)", keyrouter); - // check no privilege option on the keycode - if (keyrouter->opts) { - if (keyrouter->opts[keycode].no_privilege) - return true; - } + wl_signal_emit(&keyrouter->events.destroy, keyrouter); - // already checked the privilege before. - if (client->privileged) - return true; + if (keyrouter->security_initialized) + tizen_security_finish(); - wl_client_get_credentials(wl_client, &pid, &uid, &gid); + free(keyrouter->opts); - client->privileged = tizen_security_check_privilege(pid, uid, - TIZEN_KEYROUTER_PRIVILEGE); + wl_list_remove(&keyrouter->display_destroy.link); - return client->privileged; + wl_global_destroy(keyrouter->global); + + keyrouter_grab_finish(&keyrouter->keygrab); + + free(keyrouter); } static void @@ -398,7 +284,7 @@ keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter) char *ret, *tmp, *buf_ptr, buf[1024] = {0,}; keyrouter->opts = calloc(KEYROUTER_MAX_KEYS, - sizeof(struct ds_tizen_keyrouter_key_options)); + sizeof(struct keyrouter_key_options)); if (!keyrouter->opts) { return; } @@ -433,3 +319,107 @@ keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter) fclose(file); } + +static void +create_keyrouter_client(struct ds_tizen_keyrouter *keyrouter, + struct wl_client *wl_client, uint32_t version, uint32_t id) +{ + struct keyrouter_client *client; + + client = calloc(1, sizeof *client); + if (!client) { + wl_client_post_no_memory(wl_client); + return; + } + + client->keyrouter = keyrouter; + client->wl_client = wl_client; + client->resource = wl_resource_create(wl_client, &tizen_keyrouter_interface, + MIN(version, TIZEN_KEYROUTER_VERSION), id); + if (!client->resource) { + ds_err("wl_resource_create() failed. (version :%d, id:%d)", + version, id); + free(client); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(client->resource, &tizen_keyrouter_impl, + client, keyrouter_client_handle_resource_destroy); + + wl_list_insert(&keyrouter->clients, &client->link); +} + +static void +destroy_keyrouter_client(struct keyrouter_client *client) +{ + wl_list_remove(&client->link); + free(client); +} + +static bool +keyrouter_client_check_privilege(struct keyrouter_client *client, uint32_t mode, + uint32_t keycode) +{ + struct ds_tizen_keyrouter *keyrouter = client->keyrouter; + pid_t pid = 0; + uid_t uid = 0; + + /* Top position grab is always allowed. This mode do not need privilege.*/ + if (mode == TIZEN_KEYROUTER_MODE_TOPMOST) + return true; + + // check no privilege option on the keycode + if (keyrouter->opts && keyrouter->opts[keycode].no_privilege) + return true; + + // already checked the privilege before. + if (client->privileged) + return true; + + wl_client_get_credentials(client->wl_client, &pid, &uid, NULL); + + client->privileged = tizen_security_check_privilege(pid, uid, + TIZEN_KEYROUTER_PRIVILEGE); + + return client->privileged; +} + +static int +keyrouter_client_grab_key(struct keyrouter_client *client, int mode, + int keycode) +{ + struct ds_tizen_keyrouter *keyrouter = client->keyrouter; + + if (!keyrouter_client_check_privilege(client, mode, keycode)) + return TIZEN_KEYROUTER_ERROR_NO_PERMISSION; + + return keyrouter_grab_grab_key(&keyrouter->keygrab, mode, keycode, + client->wl_client); +} + +static int +keyrouter_client_ungrab_key(struct keyrouter_client *client, int keycode) +{ + struct ds_tizen_keyrouter *keyrouter = client->keyrouter; + + /* ungrab TOP POSITION grab first, this grab mode is not check privilege */ + keyrouter_grab_ungrab_key(&keyrouter->keygrab, + TIZEN_KEYROUTER_MODE_TOPMOST, keycode, client->wl_client); + + if (!keyrouter_client_check_privilege(client, TIZEN_KEYROUTER_MODE_NONE, + keycode)) + return TIZEN_KEYROUTER_ERROR_NO_PERMISSION; + + keyrouter_grab_ungrab_key(&keyrouter->keygrab, + TIZEN_KEYROUTER_MODE_EXCLUSIVE, keycode, client->wl_client); + keyrouter_grab_ungrab_key(&keyrouter->keygrab, + TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, keycode, + client->wl_client); + keyrouter_grab_ungrab_key(&keyrouter->keygrab, + TIZEN_KEYROUTER_MODE_TOPMOST, keycode, client->wl_client); + keyrouter_grab_ungrab_key(&keyrouter->keygrab, + TIZEN_KEYROUTER_MODE_SHARED, keycode, client->wl_client); + + return TIZEN_KEYROUTER_ERROR_NONE; +} diff --git a/src/keyrouter/keyrouter.h b/src/keyrouter/keyrouter.h index 11fbadc..bea9ab1 100644 --- a/src/keyrouter/keyrouter.h +++ b/src/keyrouter/keyrouter.h @@ -5,37 +5,34 @@ #include #include +#include "libds-tizen/keyrouter.h" + #define KEYROUTER_MAX_KEYS 512 -struct ds_tizen_keyrouter_key_info +struct keyroute_info { - void *data; - struct wl_list link; + struct wl_client *wl_client; + struct wl_list link; }; -struct ds_tizen_keyrouter_grabbed +struct keyrouter_grabbed { - int keycode; - struct { - struct wl_list excl; - struct wl_list or_excl; - struct wl_list top; - struct wl_list shared; + struct wl_list excl; // keyroute_info::link + struct wl_list or_excl; // keyroute_info::link + struct wl_list top; // keyroute_info::link + struct wl_list shared; // keyroute_info::link } grab; struct wl_list pressed; }; -struct ds_tizen_keyrouter_grab +struct keyrouter_grab { - struct ds_tizen_keyrouter_grabbed *hard_keys; - - void *focus_client; - void *top_client; + struct keyrouter_grabbed hard_keys[KEYROUTER_MAX_KEYS]; }; -struct ds_tizen_keyrouter_key_options +struct keyrouter_key_options { bool enabled; bool no_privilege; @@ -53,18 +50,19 @@ struct ds_tizen_keyrouter struct wl_signal destroy; } events; - struct ds_tizen_keyrouter_key_options *opts; + struct keyrouter_key_options *opts; - struct ds_tizen_keyrouter_grab *keygrab; + struct keyrouter_grab keygrab; bool security_initialized; }; -struct ds_tizen_keyrouter_client +struct keyrouter_client { struct ds_tizen_keyrouter *keyrouter; struct wl_resource *resource; + struct wl_client *wl_client; bool privileged; @@ -84,27 +82,18 @@ struct ds_tizen_ungrab_data int err; }; -struct ds_tizen_keyrouter_grab * -keyrouter_grab_create(void); -void -keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keygrab); -int -keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keygrab, - int type, int keycode, void *data); -void -keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keygrab, - int type, int keycode, void *data); -int -keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keygrab, - int keycode, int pressed, struct wl_list *delivery_list); -void -keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keygrab, - void *focus_client); -void -keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keygrab, - void *top_client); -bool -keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keygrab, - int keycode); +void keyrouter_grab_init(struct keyrouter_grab *keygrab); + +void keyrouter_grab_finish(struct keyrouter_grab *keygrab); + +int keyrouter_grab_grab_key(struct keyrouter_grab *keygrab, int mode, + int keycode, struct wl_client *wl_client); + +void keyrouter_grab_ungrab_key(struct keyrouter_grab *keygrab, int mode, + int keycode, struct wl_client *wl_client); + +enum ds_tizen_keyroute_mode +keyrouter_grab_get_keyroutes(struct keyrouter_grab *keygrab, int keycode, + struct wl_client *topmost_client, struct wl_array *keyroutes); #endif diff --git a/src/keyrouter/keyrouter_grab.c b/src/keyrouter/keyrouter_grab.c index ae29e8e..fed301b 100644 --- a/src/keyrouter/keyrouter_grab.c +++ b/src/keyrouter/keyrouter_grab.c @@ -1,3 +1,4 @@ +#include #include #include @@ -5,343 +6,324 @@ #include "keyrouter.h" +#define KEYGRAB_IS_VALID_KEYCODE(code) \ + ((code > 0) && (code < KEYROUTER_MAX_KEYS)) +#define KEYGRAB_LIST_FIRST(head, sample, member) \ + wl_container_of((head)->next, sample, member) + static struct wl_list * -keyrouter_grab_get_grabbed_list(struct ds_tizen_keyrouter_grab *keygrab, - int type, int keycode) +keyrouter_grab_get_mode_list(struct keyrouter_grab *keygrab, int mode, + int keycode); +static void mode_list_clean(struct wl_list *list); +static void mode_list_remove_wl_client(struct wl_list *list, + struct wl_client *wl_client); +static bool mode_list_check_duplicated(struct wl_list *list, + struct wl_client *wl_client); +static struct keyroute_info *create_keyroute_info(struct wl_client *wl_client); +static void destroy_key_info(struct keyroute_info *info); +static struct keyroute_info * +keyrouter_grab_get_exclusive_first(struct keyrouter_grab *keygrab, int keycode); +static struct keyroute_info * +keyrouter_grab_get_overridable_exclusive_first(struct keyrouter_grab *keygrab, + int keycode); +static struct keyroute_info * +keyrouter_grab_topmost_find(struct keyrouter_grab *keygrab, int keycode, + struct wl_client *topmost_client); +static bool keyrouter_grab_get_shared_keyroutes(struct keyrouter_grab *keygrab, + int keycode, struct wl_array *keyroutes); +static bool keyroutes_add_info(struct wl_array *keyroutes, + struct wl_client *wl_client); + +void +keyrouter_grab_init(struct keyrouter_grab *keygrab) { - switch(type) { - case TIZEN_KEYROUTER_MODE_EXCLUSIVE: - return &keygrab->hard_keys[keycode].grab.excl; - case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE: - return &keygrab->hard_keys[keycode].grab.or_excl; - case TIZEN_KEYROUTER_MODE_TOPMOST: - return &keygrab->hard_keys[keycode].grab.top; - case TIZEN_KEYROUTER_MODE_SHARED: - return &keygrab->hard_keys[keycode].grab.shared; - default: - return NULL; + for (size_t i = 0; i < KEYROUTER_MAX_KEYS; i++) { + wl_list_init(&keygrab->hard_keys[i].grab.excl); + wl_list_init(&keygrab->hard_keys[i].grab.or_excl); + wl_list_init(&keygrab->hard_keys[i].grab.top); + wl_list_init(&keygrab->hard_keys[i].grab.shared); + wl_list_init(&keygrab->hard_keys[i].pressed); } } -bool -keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keygrab, int keycode) +void +keyrouter_grab_finish(struct keyrouter_grab *keygrab) { - struct wl_list *list; + for (size_t i = 0; i < KEYROUTER_MAX_KEYS; i++) { + mode_list_clean(&keygrab->hard_keys[i].grab.excl); + mode_list_clean(&keygrab->hard_keys[i].grab.or_excl); + mode_list_clean(&keygrab->hard_keys[i].grab.top); + mode_list_clean(&keygrab->hard_keys[i].grab.shared); + mode_list_clean(&keygrab->hard_keys[i].pressed); + } +} - list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_EXCLUSIVE, keycode); - if (list && !wl_list_empty(list)) - return true; +enum ds_tizen_keyroute_mode +keyrouter_grab_get_keyroutes(struct keyrouter_grab *keygrab, int keycode, + struct wl_client *topmost_client, struct wl_array *keyroutes) +{ + struct keyroute_info *info; - list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, keycode); - if (list && !wl_list_empty(list)) - return true; + if (!KEYGRAB_IS_VALID_KEYCODE(keycode)) { + ds_err("Invalid keycode(%d)", keycode); + goto none_out; + } - list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_TOPMOST, keycode); - if (list && !wl_list_empty(list)) - return true; + info = keyrouter_grab_get_exclusive_first(keygrab, keycode); + if (info) + goto exclusive_out; - list = keyrouter_grab_get_grabbed_list(keygrab, TIZEN_KEYROUTER_MODE_SHARED, keycode); - if (list && !wl_list_empty(list)) - return true; + info = keyrouter_grab_get_overridable_exclusive_first(keygrab, keycode); + if (info) + goto exclusive_out; - return false; -} + info = keyrouter_grab_topmost_find(keygrab, keycode, topmost_client); + if (info) + goto exclusive_out; -static bool -keyrouter_grab_check_duplicated_data(struct wl_list *list, void *data) -{ - struct ds_tizen_keyrouter_key_info *info; + if (keyrouter_grab_get_shared_keyroutes(keygrab, keycode, keyroutes)) + return DS_TIZEN_KEYROUTE_MODE_SHARED; - if (wl_list_empty(list)) - return false; +none_out: + return DS_TIZEN_KEYROUTE_MODE_NONE; - wl_list_for_each(info, list, link) { - if (info->data == data) - return true; - } +exclusive_out: + if (!keyroutes_add_info(keyroutes, info->wl_client)) + ds_err("Could not add wl_client to keyroutes"); - return false; + return DS_TIZEN_KEYROUTE_MODE_EXCLUSIVE; } -static bool -keyrouter_grab_check_grabbed(struct ds_tizen_keyrouter_grab *keygrab, - int type, int keycode, void *data) +int +keyrouter_grab_grab_key(struct keyrouter_grab *keygrab, int mode, int keycode, + struct wl_client *wl_client) { + struct keyroute_info *info; struct wl_list *list; - bool ret; - list = keyrouter_grab_get_grabbed_list(keygrab, type, keycode); - if (list == NULL) { - ds_err("keycode(%d) had no list for type(%d).", keycode, type); - return false; + if (!KEYGRAB_IS_VALID_KEYCODE(keycode)) { + ds_err("Invalid keycode(%d)", keycode); + return TIZEN_KEYROUTER_ERROR_INVALID_KEY; } - switch(type) { + switch (mode) { case TIZEN_KEYROUTER_MODE_EXCLUSIVE: - if (wl_list_empty(list) == false) - ret = true; - else - ret = false; + list = &keygrab->hard_keys[keycode].grab.excl; + if (!wl_list_empty(list)) + return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY; break; case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE: - ret = keyrouter_grab_check_duplicated_data(list, data); - break; case TIZEN_KEYROUTER_MODE_TOPMOST: - ret = keyrouter_grab_check_duplicated_data(list, data); - break; case TIZEN_KEYROUTER_MODE_SHARED: - ret = keyrouter_grab_check_duplicated_data(list, data); + if (mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE) + list = &keygrab->hard_keys[keycode].grab.or_excl; + else if (mode == TIZEN_KEYROUTER_MODE_TOPMOST) + list = &keygrab->hard_keys[keycode].grab.top; + else + list = &keygrab->hard_keys[keycode].grab.shared; + + if (mode_list_check_duplicated(list, wl_client)) + return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY; break; default: - ret = true; - break; + return TIZEN_KEYROUTER_ERROR_INVALID_MODE; } - return ret; -} + info = create_keyroute_info(wl_client); + if (!info) { + ds_err("Could not create key info"); + return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES; + } -void -keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keygrab, - void *focus_client) -{ - keygrab->focus_client = focus_client; + wl_list_insert(list, &info->link); - if (focus_client) - ds_dbg("[%s] focus client has been set. (focus_client=0x%p)", __FUNCTION__, focus_client); - else - ds_dbg("[%s] focus client has been set to NULL.", __FUNCTION__); + return TIZEN_KEYROUTER_ERROR_NONE; } void -keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keygrab, void *top_client) -{ - keygrab->top_client = top_client; - - if (top_client) - ds_dbg("[%s] top client has been set. (top_client=0x%p)", __FUNCTION__, top_client); - else - ds_dbg("[%s] top client has been set to NULL.", __FUNCTION__); -} - -int -keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keygrab, - int keycode, int pressed, struct wl_list *delivery_list) +keyrouter_grab_ungrab_key(struct keyrouter_grab *keygrab, + int mode, int keycode, struct wl_client *wl_client) { - struct ds_tizen_keyrouter_key_info *info, *delivery; - int count = 0; + struct wl_list *list; - if (keycode <= 0 || keycode >= KEYROUTER_MAX_KEYS) { + if (!KEYGRAB_IS_VALID_KEYCODE(keycode)) { ds_err("Invalid keycode(%d)", keycode); - return 0; + return; } - if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.excl)) { - delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); - if (delivery == NULL) { - ds_err("Failed to allocate memory."); - return 0; - } - info = wl_container_of(keygrab->hard_keys[keycode].grab.excl.next, info, link); - delivery->data = info->data; - wl_list_insert(delivery_list, &delivery->link); - ds_dbg("Exclusive Mode: keycode: %d to data: %p", keycode, info->data); - return 1; - } else if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.or_excl)) { - delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); - if (delivery == NULL) { - ds_err("Failed to allocate memory."); - return 0; - } - info = wl_container_of(keygrab->hard_keys[keycode].grab.or_excl.next, info, link); - delivery->data = info->data; - wl_list_insert(delivery_list, &delivery->link); - ds_dbg("OR-Excl Mode: keycode: %d to data: %p", keycode, info->data); - return 1; - } else if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.top)) { - wl_list_for_each(info, &keygrab->hard_keys[keycode].grab.top, link) { - if (keygrab->top_client && keygrab->top_client == info->data) { - delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); - if (delivery == NULL) { - ds_err("Failed to allocate memory."); - return 0; - } - delivery->data = info->data; - wl_list_insert(delivery_list, &delivery->link); - ds_dbg("Topmost Mode: keycode: %d to data: %p", keycode, info->data); - return 1; - } - } + list = keyrouter_grab_get_mode_list(keygrab, mode, keycode); + if (!list) { + ds_err("keycode(%d) had no list for mode(%d)", keycode, mode); + return; } - if (keygrab->focus_client) { - delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); - if (delivery == NULL) { - ds_err("Failed to allocate memory."); - return 0; - } - delivery->data = keygrab->focus_client; - wl_list_insert(delivery_list, &delivery->link); - count++; - ds_dbg("Focus: keycode: %d to data: %p, count: %d", keycode, delivery->data, count); - } + mode_list_remove_wl_client(list, wl_client); +} - if (!wl_list_empty(&keygrab->hard_keys[keycode].grab.shared)) { - wl_list_for_each(info, &keygrab->hard_keys[keycode].grab.shared, link) { - if (keygrab->focus_client && keygrab->focus_client == info->data) - continue; - delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); - if (delivery == NULL) { - ds_err("Failed to allocate memory."); - return 0; - } - delivery->data = info->data; - wl_list_insert(delivery_list, &delivery->link); - count++; - ds_dbg("Shared: keycode: %d to data: %p, count: %d", keycode, info->data, count); - } - } +static void +mode_list_clean(struct wl_list *list) +{ + struct keyroute_info *info, *tmp; - return count; + wl_list_for_each_safe(info, tmp, list, link) + destroy_key_info(info); } -int -keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keygrab, - int type, int keycode, void *data) +static void +mode_list_remove_wl_client(struct wl_list *list, struct wl_client *wl_client) { - struct ds_tizen_keyrouter_key_info *info = NULL; - struct wl_list *list = NULL; + struct keyroute_info *info, *tmp; - if (keycode <= 0 || keycode >= KEYROUTER_MAX_KEYS) { - ds_err("Invalid keycode(%d)", keycode); - return TIZEN_KEYROUTER_ERROR_INVALID_KEY; + wl_list_for_each_safe(info ,tmp, list, link) { + if (info->wl_client == wl_client) + destroy_key_info(info); } +} - if (keyrouter_grab_check_grabbed(keygrab, type, keycode, data)) - return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY; - - info = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info)); - if (info == NULL) { - ds_err("Failed to allocate memory."); - return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES; +static struct wl_list * +keyrouter_grab_get_mode_list(struct keyrouter_grab *keygrab, + int mode, int keycode) +{ + switch(mode) { + case TIZEN_KEYROUTER_MODE_EXCLUSIVE: + return &keygrab->hard_keys[keycode].grab.excl; + case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE: + return &keygrab->hard_keys[keycode].grab.or_excl; + case TIZEN_KEYROUTER_MODE_TOPMOST: + return &keygrab->hard_keys[keycode].grab.top; + case TIZEN_KEYROUTER_MODE_SHARED: + return &keygrab->hard_keys[keycode].grab.shared; + default: + return NULL; } - info->data = data; +} - wl_list_init(&info->link); +static bool +mode_list_check_duplicated(struct wl_list *list, struct wl_client *wl_client) +{ + struct keyroute_info *info; - list = keyrouter_grab_get_grabbed_list(keygrab, type, keycode); - if (!list) { - ds_err("keycode(%d) had no list for type(%d)", keycode, type); - free(info); - return TIZEN_KEYROUTER_ERROR_INVALID_MODE; + wl_list_for_each(info, list, link) { + if (info->wl_client == wl_client) + return true; } - if (!keygrab->hard_keys[keycode].keycode) - keygrab->hard_keys[keycode].keycode = keycode; + return false; +} + +static struct keyroute_info * +create_keyroute_info(struct wl_client *wl_client) +{ + struct keyroute_info *info; - wl_list_insert(list, &info->link); + info = calloc(1, sizeof *info); + if (!info) + return NULL; - return TIZEN_KEYROUTER_ERROR_NONE; + info->wl_client = wl_client; + + return info; } static void -keyrouter_list_remove_data(struct wl_list *list, void *data) +destroy_key_info(struct keyroute_info *info) { - struct ds_tizen_keyrouter_key_info *info, *tmp; + wl_list_remove(&info->link); + free(info); +} + +static struct keyroute_info * +keyrouter_grab_get_exclusive_first(struct keyrouter_grab *keygrab, int keycode) +{ + struct wl_list *list = &keygrab->hard_keys[keycode].grab.excl; + struct keyroute_info *info; if (wl_list_empty(list)) - return; + return NULL; - wl_list_for_each_safe(info ,tmp, list, link) { - if (info->data == data) { - wl_list_remove(&info->link); - free(info); - } - } + info = KEYGRAB_LIST_FIRST(list, info, link); + + ds_dbg("Exclusive Mode: keycode: %d to wl_client: %p", + keycode, info->wl_client); + + return info; } -void -keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keygrab, - int type, int keycode, void *data) +static struct keyroute_info * +keyrouter_grab_get_overridable_exclusive_first(struct keyrouter_grab *keygrab, + int keycode) { - struct wl_list *list; + struct wl_list *list = &keygrab->hard_keys[keycode].grab.or_excl; + struct keyroute_info *info; - if (keycode <= 0 || keycode >= KEYROUTER_MAX_KEYS) { - ds_err("Invalid keycode(%d)", keycode); - return; - } + if (wl_list_empty(list)) + return NULL; - if (keygrab->hard_keys[keycode].keycode == 0) - return; + info = KEYGRAB_LIST_FIRST(list, info, link); - list = keyrouter_grab_get_grabbed_list(keygrab, type, keycode); - if (list == NULL) { - ds_err("keycode(%d) had no list for type(%d)", keycode, type); - return; - } + ds_dbg("OR-Excl Mode: keycode: %d to wl_client: %p", + keycode, info->wl_client); - keyrouter_list_remove_data(list, data); + return info; } -struct ds_tizen_keyrouter_grab * -keyrouter_grab_create(void) +static struct keyroute_info * +keyrouter_grab_topmost_find(struct keyrouter_grab *keygrab, + int keycode, struct wl_client *topmost_client) { - struct ds_tizen_keyrouter_grab *keygrab = NULL; - int i; + struct wl_list *list = &keygrab->hard_keys[keycode].grab.top; + struct keyroute_info *info; - keygrab = calloc(1, sizeof(struct ds_tizen_keyrouter_grab)); - if (keygrab == NULL) { - ds_err("Failed to allocate memory."); + if (!topmost_client) return NULL; - } - /* FIXME: Who defined max keycode? */ - keygrab->hard_keys = calloc(KEYROUTER_MAX_KEYS, sizeof(struct ds_tizen_keyrouter_grabbed)); - if (keygrab->hard_keys == NULL) { - ds_err("Failed to allocate memory."); - free(keygrab); - return NULL; - } + wl_list_for_each(info, list, link) { + if (info->wl_client != topmost_client) + continue; - for (i = 0; i < KEYROUTER_MAX_KEYS; i++) { - /* Enable all of keys to grab */ - //keygrab->hard_keys[i].keycode = i; - wl_list_init(&keygrab->hard_keys[i].grab.excl); - wl_list_init(&keygrab->hard_keys[i].grab.or_excl); - wl_list_init(&keygrab->hard_keys[i].grab.top); - wl_list_init(&keygrab->hard_keys[i].grab.shared); - wl_list_init(&keygrab->hard_keys[i].pressed); + ds_dbg("Topmost Mode: keycode: %d to wl_client: %p", + keycode, info->wl_client); + + return info; } - return keygrab; + return NULL; } -static void -keyrouter_grab_delete_list(struct wl_list *list) +static bool +keyrouter_grab_get_shared_keyroutes(struct keyrouter_grab *keygrab, + int keycode, struct wl_array *keyroutes) { - struct ds_tizen_keyrouter_key_info *info, *tmp; + struct wl_list *list = &keygrab->hard_keys[keycode].grab.shared; + struct keyroute_info *info; + int count = 0; - if (wl_list_empty(list)) - return; + wl_list_for_each(info, list, link) { + if (!keyroutes_add_info(keyroutes, info->wl_client)) { + ds_err("Could not prepend wl_client to delivery_list"); + continue; + } - wl_list_for_each_safe(info, tmp, list, link) { - wl_list_remove(&info->link); - free(info); + count++; + + ds_dbg("Shared: keycode: %d to wl_client: %p, count: %d", + keycode, info->wl_client, count); } + + return !!count; } -void -keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keygrab) +static bool +keyroutes_add_info(struct wl_array *keyroutes, + struct wl_client *wl_client) { - int i; - - for (i = 0; i < KEYROUTER_MAX_KEYS; i++) { - keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.excl); - keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.or_excl); - keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.top); - keyrouter_grab_delete_list(&keygrab->hard_keys[i].grab.shared); - keyrouter_grab_delete_list(&keygrab->hard_keys[i].pressed); - } + struct ds_tizen_keyroute_info *info; + + info = wl_array_add(keyroutes, sizeof *info); + if (!info) + return false; + + info->wl_client = wl_client; - free(keygrab->hard_keys); - free(keygrab); + return true; } -- 2.7.4 From 2761e0c3dfae0d221b53c77b63149e0af8315c86 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Tue, 28 Jun 2022 13:59:10 +0900 Subject: [PATCH 15/16] devicemgr: implement input generator (pointer & touch) Change-Id: Ia27ed1fd2baa29db0df19ee2b3e18cb7d020cad7 --- clients/input-generator.c | 152 ++++++-- examples/tinyds-tdm-libinput.c | 2 + include/libds-tizen/input-devicemgr.h | 4 + src/input-devicemgr/input-devicemgr.c | 674 +++++++++++++++++++++++++++++----- src/input-devicemgr/input-devicemgr.h | 25 +- 5 files changed, 727 insertions(+), 130 deletions(-) diff --git a/clients/input-generator.c b/clients/input-generator.c index f61e84b..73b7ab4 100644 --- a/clients/input-generator.c +++ b/clients/input-generator.c @@ -19,10 +19,10 @@ enum enum_key_type enum enum_touch_type { - TOUCH_BEGIN = 0, - TOUCH_UPDATE, - TOUCH_END, - TOUCH_ALL + POINTER_BEGIN = 0, + POINTER_UPDATE, + POINTER_END, + POINTER_ALL }; struct display @@ -60,8 +60,7 @@ usage(void) printf("init {device type}\n"); printf(" : device type:\n"); printf(" - default: all\n"); - printf(" - key/keyboard: keyboard\n"); - printf(" - touch: touch screen\n"); + printf(" - keyboard / touch / mouse\n"); printf(" - all: all of devices\n"); printf(" : ex> init keyboard / init\n"); printf("\n"); @@ -78,15 +77,33 @@ usage(void) printf("touch {index} {type} {x} {y}\n"); printf(" : index:\n"); printf(" - default: first finger(0)\n"); - printf(" - first finger is 0\n"); printf(" : type:\n"); printf(" - default: generate sample touch events\n"); - printf(" - touch begin: 1\n"); - printf(" - touch update: 2\n"); - printf(" - touch end: 3\n"); + printf(" - touch down: 0\n"); + printf(" - touch move: 1\n"); + printf(" - touch up: 2\n"); printf(" : x/y:\n"); printf(" - default: 0\n"); - printf(" : ex> touch / touch 0 1 100 100\n"); + printf(" : ex> touch\n"); + printf(" : ex> touch 0 0 400 400\n"); + printf(" : touch 0 1 410 410\n"); + printf(" : touch 0 2 0 0\n"); + printf("mouse {button} {type} {x} {y}\n"); + printf(" : button:\n"); + printf(" - default: left button(1)\n"); + printf(" : type:\n"); + printf(" - default: generate sample mouse events\n"); + printf(" - button down: 0\n"); + printf(" - mouse move: 1\n"); + printf(" - button up: 2\n"); + printf(" : x/y:\n"); + printf(" - default: 0\n"); + printf(" - relative motion\n"); + printf(" : ex> mouse\n"); + printf(" : ex> mouse 1 0 0 0\n"); + printf(" : mouse 1 1 10 10\n"); + printf(" : mouse 1 1 -10 -10\n"); + printf(" : mouse 1 2 0 0\n"); printf("\n"); } @@ -162,7 +179,7 @@ key_generate(char *name, int type) printf("name: %s, type: %d\n", name, type); if (!data_wl.init) { - printf("Input genrator is not initialized\n"); + printf("Input generator is not initialized\n"); return; } @@ -180,7 +197,7 @@ key_generate(char *name, int type) } static char * -touch_type_string_get(int type) +type_string_get(int type) { switch (type) { case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN: @@ -204,10 +221,10 @@ input_generator_touch(int idx, int type, int x, int y) if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { if (data_wl.enable_log) { - printf("Success to generate touch: %d finger %s on (%d, %d)\n", idx, touch_type_string_get(type), x, y); + printf("Success to generate touch: %d finger %s on (%d, %d)\n", idx, type_string_get(type), x, y); } } else { - printf("Failed to generate touch(%d finger %s on (%d, %d)): %d\n", idx, touch_type_string_get(type), x, y, data_wl.request_notified); + printf("Failed to generate touch(%d finger %s on (%d, %d)): %d\n", idx, type_string_get(type), x, y, data_wl.request_notified); } data_wl.request_notified = -1; @@ -217,38 +234,77 @@ static void touch_generate(int idx, int type, int x, int y) { if (!data_wl.init) { - printf("Input genrator is not initialized\n"); + printf("Input generator is not initialized\n"); return; } - if (type == TOUCH_ALL) { - input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 100, 100); - input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 200, 200); - input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 300, 300); + if (type == POINTER_ALL) { + input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 300, 300); + input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 400, 400); + input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 500, 500); - input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 110, 110); - input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 210, 210); - input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 310, 310); + input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 310, 310); + input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 410, 410); + input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 510, 510); - input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 120, 120); - input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 220, 220); - input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 320, 320); + input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 320, 320); + input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 420, 420); + input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 520, 520); - input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 120, 120); - input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 220, 220); - input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 320, 320); + input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 320, 320); + input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 420, 420); + input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 520, 520); } else { input_generator_touch(idx, type, x, y); } } static void +input_generator_mouse(int type, int x, int y, int button) +{ + tizen_input_device_manager_generate_pointer(data_wl.devicemgr, type, x, y, button); + + while (data_wl.request_notified == -1) + wl_display_dispatch_queue(data_wl.display, data_wl.queue); + + if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + if (data_wl.enable_log) { + printf("Success to generate mouse: %s on (%d, %d)\n", type_string_get(type), x, y); + } + } else { + printf("Failed to generate mouse(%s on (%d, %d)): %d\n", type_string_get(type), x, y, data_wl.request_notified); + } + + data_wl.request_notified = -1; +} + +static void +mouse_generate(int btn, int type, int x, int y) +{ + if (!data_wl.init) { + printf("Input generator is not initialized\n"); + return; + } + + if (type == POINTER_ALL) { + input_generator_mouse(TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, -1, -1, 1); + input_generator_mouse(TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1); + input_generator_mouse(TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1); + input_generator_mouse(TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1); + input_generator_mouse(TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, -1, -1, 1); + + } else { + input_generator_mouse(type, x, y, btn); + } +} + +static void stdin_read(void) { int c; char buf[MAX_STR] = {0, }, *tmp, *buf_ptr, key_name[MAX_STR] = {0, }; int count = 0; - int key_type = KEY_ALL, touch_idx = 0, touch_type = TOUCH_ALL, touch_x = 0, touch_y = 0; + int key_type = KEY_ALL, idx = 0, type = POINTER_ALL, x = 0, y = 0; while ((c = getchar()) != EOF) { if (c == '\n') break; @@ -272,6 +328,8 @@ stdin_read(void) init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD); else if (!strncmp("touch", tmp, MAX_STR-1)) init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN); + else if (!strncmp("mouse", tmp, MAX_STR-1)) + init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE); break; default: break; @@ -305,16 +363,40 @@ stdin_read(void) if (tmp) { switch (count) { case 0: - touch_idx = atoi(tmp); + idx = atoi(tmp); + break; + case 1: + type = atoi(tmp); + break; + case 2: + x = atoi(tmp); + break; + case 3: + y = atoi(tmp); + break; + default: + break; + } + } + count++; + } + touch_generate(idx, type, x, y); + } else if (!strncmp(tmp, "mouse", sizeof("mouse"))) { + while (tmp) { + tmp = strtok_r(NULL, " ", &buf_ptr); + if (tmp) { + switch (count) { + case 0: + idx = atoi(tmp); break; case 1: - touch_type = atoi(tmp); + type = atoi(tmp); break; case 2: - touch_x = atoi(tmp); + x = atoi(tmp); break; case 3: - touch_y = atoi(tmp); + y = atoi(tmp); break; default: break; @@ -322,7 +404,7 @@ stdin_read(void) } count++; } - touch_generate(touch_idx, touch_type, touch_x, touch_y); + mouse_generate(idx, type, x, y); } else if (!strncmp(buf, "q", MAX_STR) || !strncmp(buf, "quit", MAX_STR)) { data_wl.run = 0; } else if (!strncmp(buf, "help", MAX_STR)) { diff --git a/examples/tinyds-tdm-libinput.c b/examples/tinyds-tdm-libinput.c index 5634707..3feb932 100644 --- a/examples/tinyds-tdm-libinput.c +++ b/examples/tinyds-tdm-libinput.c @@ -352,6 +352,8 @@ backend_handle_new_output(struct wl_listener *listener, void *data) output->output_frame.notify = output_handle_frame; ds_output_add_frame_listener(ds_output, &output->output_frame); + ds_tizen_input_devicemgr_set_output_width_height(server->devicemgr, (uint32_t)output->width, (uint32_t)output->height); + server->output = output; draw_output(output); diff --git a/include/libds-tizen/input-devicemgr.h b/include/libds-tizen/input-devicemgr.h index a9ed808..fc1060e 100644 --- a/include/libds-tizen/input-devicemgr.h +++ b/include/libds-tizen/input-devicemgr.h @@ -33,6 +33,10 @@ 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 diff --git a/src/input-devicemgr/input-devicemgr.c b/src/input-devicemgr/input-devicemgr.c index 3e69d0e..c825b4c 100644 --- a/src/input-devicemgr/input-devicemgr.c +++ b/src/input-devicemgr/input-devicemgr.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "util.h" #include "input-devicemgr.h" @@ -12,6 +14,7 @@ #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; @@ -52,6 +55,14 @@ 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); @@ -59,7 +70,7 @@ device_manager_handle_destroy(struct wl_client *client, static void tz_devicemgr_destroy(struct ds_tizen_input_devicemgr *tz_devicemgr); static int tz_devicemgr_init_generator(struct ds_tizen_input_devicemgr *tz_devicemgr, - struct wl_resource *resource, const char *name); + 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); @@ -77,6 +88,19 @@ 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); @@ -125,6 +149,17 @@ ds_tizen_input_devicemgr_create(struct ds_backend *backend, 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); @@ -134,7 +169,7 @@ ds_tizen_input_devicemgr_create(struct ds_backend *backend, wl_signal_init(&tz_devicemgr->events.destroy); wl_list_init(&tz_devicemgr->clients); - wl_list_init(&tz_devicemgr->pressed_keys); + wl_list_init(&tz_devicemgr->devices.kbd->key.pressed); wl_list_init(&tz_devicemgr->keymap_list); wl_list_init(&tz_devicemgr->blocked_keys); @@ -146,6 +181,10 @@ ds_tizen_input_devicemgr_create(struct ds_backend *backend, 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); @@ -192,6 +231,21 @@ ds_tizen_input_devicemgr_set_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) { @@ -219,6 +273,8 @@ tz_devicemgr_destroy(struct ds_tizen_input_devicemgr *tz_devicemgr) free(client_data); } + free(tz_devicemgr->devices.touch); + free(tz_devicemgr->devices.ptr); free(tz_devicemgr->devices.kbd); free(tz_devicemgr); } @@ -248,6 +304,14 @@ seat_handle_destroy(struct wl_listener *listener, void *data) } 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; @@ -259,14 +323,18 @@ backend_handle_input_device_add(struct wl_listener *listener, void *data) 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"); + 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) { - //TODO: assign input_device 'dev' to devices.ptr + 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) { - //TODO: assign input_device 'dev' to devices.ptr + 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; } } @@ -276,8 +344,8 @@ static const struct tizen_input_device_manager_interface _devicemgr_impl = { .init_generator = device_manager_handle_init_generator, .deinit_generator = device_manager_handle_deinit_generator, .generate_key = device_manager_handle_generate_key, - .generate_pointer = NULL, - .generate_touch = NULL, + .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 @@ -359,13 +427,7 @@ device_manager_handle_init_generator(struct wl_client *client, goto finish; } - if (clas != TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) { - ds_err("only support keyboard device. (requested: 0x%x)\n", clas); - ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER; - goto finish; - } - - ret = tz_devicemgr_init_generator(tz_devicemgr, resource, + 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"); @@ -398,13 +460,7 @@ device_manager_handle_init_generator_with_name(struct wl_client *client, goto finish; } - if (clas != TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) { - ds_err("only support keyboard device. (requested: 0x%x)\n", clas); - ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER; - goto finish; - } - - ret = tz_devicemgr_init_generator(tz_devicemgr, resource, + 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"); @@ -417,7 +473,7 @@ finish: static void device_manager_handle_deinit_generator(struct wl_client *client, - struct wl_resource *resource, uint32_t clas) + 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; @@ -431,12 +487,6 @@ device_manager_handle_deinit_generator(struct wl_client *client, goto finish; } - if (clas != TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) { - ds_err("only support keyboard device. (requested: 0x%x)\n", clas); - ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER; - goto finish; - } - ret = tz_devicemgr_deinit_generator(tz_devicemgr, resource); if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { ds_err("Failed to deinit input generator\n"); @@ -498,6 +548,19 @@ tz_devicemgr_xkb_keyname_to_keycode(struct xkb_keymap *keymap, 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) @@ -507,9 +570,17 @@ device_manager_handle_generate_key(struct wl_client *client, 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"); @@ -557,6 +628,144 @@ finish: } 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) { @@ -597,58 +806,242 @@ create_ds_keyboard() 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_init_generator(struct ds_tizen_input_devicemgr *tz_devicemgr, - struct wl_resource *resource, const char *name) +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; - struct ds_tizen_input_devicemgr_client *client_data; - struct ds_tizen_input_devicemgr_device *kbd; - - ds_inf("Init generator. name:%s", name); + const char *dev_name; - kbd = tz_devicemgr->devices.kbd; - if (strlen(kbd->name) > 0) { - ds_inf("devices.kbd already has name. name:%s", kbd->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 (kbd->input_device) { - ds_inf("devices.kbd is already set. name:%s", - ds_input_device_get_name(kbd->input_device)); + 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 - kbd->input_device = calloc(1, sizeof(struct ds_input_device)); - if(!kbd->input_device) { + dev->input_device = calloc(1, sizeof(struct ds_input_device)); + if(!dev->input_device) { ds_err("Failed to create input device !\n"); return ret; } - ds_input_device_init(kbd->input_device, DS_INPUT_DEVICE_KEYBOARD, - &input_device_iface, name, -1, -1); - kbd->input_device->keyboard = create_ds_keyboard(); + 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(); + } - wl_signal_emit(&tz_devicemgr->backend->events.new_input, - kbd->input_device); + dev->created = true; + dev->name = strdup(name); - kbd->created = true; - strncpy(kbd->name, name, UINPUT_MAX_NAME_SIZE); + 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 == false) { - client_data->init = true; - tz_devicemgr->ref++; + if (client_data->init == true) { + client_data->init = false; + clas = client_data->clas; + break; + } else { + return ret; } - break; } } + 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; + } - ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE; + 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; + } - return ret; + 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 @@ -715,10 +1108,10 @@ tz_devicemgr_pressed_keys_update(struct ds_tizen_input_devicemgr *tz_devicemgr, } key->keycode = keycode; wl_list_init(&key->link); - wl_list_insert(&tz_devicemgr->pressed_keys, &key->link); + wl_list_insert(&tz_devicemgr->devices.kbd->key.pressed, &key->link); } else { - wl_list_for_each_safe(key, tmp, &tz_devicemgr->pressed_keys, link) { + 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); @@ -728,7 +1121,7 @@ tz_devicemgr_pressed_keys_update(struct ds_tizen_input_devicemgr *tz_devicemgr, } ds_inf("Update pressed keys. length: %d, keycode:%d, pressed:%d", - wl_list_length(&tz_devicemgr->pressed_keys), keycode, pressed); + wl_list_length(&tz_devicemgr->devices.kbd->key.pressed), keycode, pressed); return true; } @@ -738,10 +1131,10 @@ tz_devicemgr_pressed_keys_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr) { struct ds_tizen_input_devicemgr_key_info *keydata, *tmp; - ds_inf("Clean up the pressed_keys. length: %d", - wl_list_length(&tz_devicemgr->pressed_keys)); + 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->pressed_keys, link) { + 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); @@ -765,48 +1158,145 @@ tz_devicemgr_keymap_list_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr) } } -static void -tz_devicemgr_keyboard_close(struct ds_tizen_input_devicemgr *tz_devicemgr) +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) { - if (!tz_devicemgr->devices.kbd->input_device) return; - ds_input_device_destroy(tz_devicemgr->devices.kbd->input_device); - tz_devicemgr->devices.kbd->input_device = NULL; - tz_devicemgr->devices.kbd->created = false; + 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 int -tz_devicemgr_deinit_generator(struct ds_tizen_input_devicemgr *tz_devicemgr, - struct wl_resource *resource) +static bool +tz_devicemgr_generate_touch_up(struct ds_input_device *device, uint32_t finger) { - int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE; - struct ds_tizen_input_devicemgr_client *client_data; + struct ds_event_touch_up ds_event; + struct timeval time; + unsigned int timestamp; + struct ds_touch *touch; - ds_inf("Deinit generator."); - wl_list_for_each(client_data, &tz_devicemgr->clients, link) { - if (client_data->resource == resource) { - if (client_data->init == true) { - client_data->init = false; - tz_devicemgr->ref--; - if (tz_devicemgr->ref < 0) tz_devicemgr->ref = 0; - break; - } else { - return ret; - } - } + 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; } - if (tz_devicemgr->ref <= 0) { - tz_devicemgr_pressed_keys_cleanup(tz_devicemgr); + 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); - if (!tz_devicemgr->devices.kbd) - return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE; + wl_signal_emit(&pointer->events.motion, &ds_event); - if (tz_devicemgr->devices.kbd->created) - tz_devicemgr_keyboard_close(tz_devicemgr); - memset(tz_devicemgr->devices.kbd->name, 0, UINPUT_MAX_NAME_SIZE); + 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; } - return ret; + 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 diff --git a/src/input-devicemgr/input-devicemgr.h b/src/input-devicemgr/input-devicemgr.h index 52bd2ef..a4428ee 100644 --- a/src/input-devicemgr/input-devicemgr.h +++ b/src/input-devicemgr/input-devicemgr.h @@ -9,9 +9,23 @@ #include struct ds_tizen_input_devicemgr_device { - char name[UINPUT_MAX_NAME_SIZE + 1]; + 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 { @@ -34,20 +48,25 @@ struct ds_tizen_input_devicemgr { } devices; struct wl_list clients; - int ref; - struct wl_list pressed_keys; struct wl_list keymap_list; struct wl_list blocked_keys; struct wl_resource *block_resource; struct wl_event_source *timer; struct ds_seat_keyboard_grab *grab; + 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 }; -- 2.7.4 From 08b81f339305fddb4bcabaf20c9cb29c31bb2abc Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Wed, 29 Jun 2022 10:46:54 +0900 Subject: [PATCH 16/16] devicemgr: use seat_destroy listener in seat_handle_destoy() func. Change-Id: If5556f8ec94836470981691efa5d9d40742f23fa --- src/input-devicemgr/input-devicemgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input-devicemgr/input-devicemgr.c b/src/input-devicemgr/input-devicemgr.c index c825b4c..91b7d57 100644 --- a/src/input-devicemgr/input-devicemgr.c +++ b/src/input-devicemgr/input-devicemgr.c @@ -296,7 +296,7 @@ seat_handle_destroy(struct wl_listener *listener, void *data) { struct ds_tizen_input_devicemgr *tz_devicemgr; - tz_devicemgr = wl_container_of(listener, tz_devicemgr, backend_destroy); + 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); -- 2.7.4