From 6b623314a75861b6695c577dc2462ad98e711b43 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Tue, 23 Aug 2022 18:19:37 +0900 Subject: [PATCH 01/16] input_method: add object pointer member in event struct Change-Id: I5002a7b4e42c5c6a7bb5b47dcf92500a0b22dcdf --- include/libds-tizen/input_method.h | 15 +++++++++++++++ src/input_method/input_method.c | 13 ++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/libds-tizen/input_method.h b/include/libds-tizen/input_method.h index 731b889..2209026 100644 --- a/include/libds-tizen/input_method.h +++ b/include/libds-tizen/input_method.h @@ -8,62 +8,77 @@ extern "C" { #endif +struct ds_tizen_input_method_manager; +struct ds_tizen_input_method_context; +struct ds_tizen_input_method; + struct ds_tizen_input_method_manager_event_set_transient_for { + struct ds_tizen_input_method_manager *im_mgr; uint32_t pid_parent, pid_child; }; struct ds_tizen_input_method_context_event_commit_string { + struct ds_tizen_input_method_context *im_context; uint32_t serial; const char *text; }; struct ds_tizen_input_method_context_event_preedit_string { + struct ds_tizen_input_method_context *im_context; uint32_t serial; const char *text, *commit; }; struct ds_tizen_input_method_context_event_preedit_styling { + struct ds_tizen_input_method_context *im_context; uint32_t index, length, style; }; struct ds_tizen_input_method_context_event_preedit_cursor { + struct ds_tizen_input_method_context *im_context; int32_t index; }; struct ds_tizen_input_method_context_event_delete_surrounding_text { + struct ds_tizen_input_method_context *im_context; int32_t index; uint32_t length; }; struct ds_tizen_input_method_context_event_cursor_position { + struct ds_tizen_input_method_context *im_context; int32_t index, anchor; }; struct ds_tizen_input_method_context_event_modifiers_map { + struct ds_tizen_input_method_context *im_context; struct wl_array *map; }; struct ds_tizen_input_method_context_event_keysym { + struct ds_tizen_input_method_context *im_context; uint32_t serial, time, sym, state, modifiers; }; struct ds_tizen_input_method_context_event_language { + struct ds_tizen_input_method_context *im_context; uint32_t serial; const char *language; }; struct ds_tizen_input_method_context_event_text_direction { + struct ds_tizen_input_method_context *im_context; uint32_t serial, direction; }; diff --git a/src/input_method/input_method.c b/src/input_method/input_method.c index 2293272..eb6232b 100644 --- a/src/input_method/input_method.c +++ b/src/input_method/input_method.c @@ -103,6 +103,7 @@ input_method_mgr_handle_set_transient_for(struct wl_client *wl_client, ds_inf("input_method_mgr_handle_set_transient_for() parent:%u, child:%u", parent_pid, child_pid); + ds_event.im_mgr = input_method_mgr; ds_event.pid_parent = parent_pid; ds_event.pid_child = child_pid; wl_signal_emit(&input_method_mgr->events.set_transient_for, &ds_event); @@ -218,7 +219,7 @@ input_method_context_client_handle_destroy(struct wl_resource *resource) { struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource); struct ds_tizen_input_method *input_method; - + ds_inf("input_method_context_client_handle_destroy"); input_method = context->input_method; @@ -443,6 +444,7 @@ context_handle_commit_string(struct wl_client *client, struct ds_tizen_input_method_context_event_commit_string ds_event; ds_inf("context_handle_commit_string"); + ds_event.im_context = context; ds_event.serial = serial; ds_event.text = text; @@ -460,6 +462,7 @@ context_handle_preedit_string(struct wl_client *client, ds_inf("context_handle_preedit_string() serial:%u, text:%s, commit:%s", serial, text, commit); + ds_event.im_context = context; ds_event.serial = serial; ds_event.text = text; ds_event.commit = commit; @@ -478,6 +481,7 @@ context_handle_preedit_styling(struct wl_client *client, ds_inf("context_handle_preedit_styling() index:%u, length:%u, style:%u", index, length, style); + ds_event.im_context = context; ds_event.index = index; ds_event.length = length; ds_event.style = style; @@ -494,6 +498,7 @@ context_handle_preedit_cursor(struct wl_client *client, ds_inf("context_handle_preedit_cursor() cursor:%d", index); + ds_event.im_context = context; ds_event.index = index; wl_signal_emit(&context->events.preedit_styling, &ds_event); } @@ -507,6 +512,7 @@ context_handle_delete_surrounding_text(struct wl_client *client, ds_inf("context_handle_delete_surrounding_text() index:%d, length:%u", index, length); + ds_event.im_context = context; ds_event.index = index; ds_event.length = length; wl_signal_emit(&context->events.delete_surrounding_text, &ds_event); @@ -521,6 +527,7 @@ context_handle_cursor_position(struct wl_client *client, ds_inf("context_handle_cursor_position() index:%d anchor:%d", index, anchor); + ds_event.im_context = context; ds_event.index = index; ds_event.anchor = anchor; wl_signal_emit(&context->events.cursor_position, &ds_event); @@ -535,6 +542,7 @@ context_handle_modifiers_map(struct wl_client *client, ds_inf("context_handle_modifiers_map() map(%p)", map); + ds_event.im_context = context; ds_event.map = map; wl_signal_emit(&context->events.modifiers_map, &ds_event); } @@ -550,6 +558,7 @@ context_handle_keysym(struct wl_client *client, struct wl_resource *resource, ds_inf("context_handle_keysym() serial(%u), time(%u), sym(%u), state(%u), modifiers(%u)", serial, time, sym, state, modifiers); + ds_event.im_context = context; ds_event.serial = serial; ds_event.time = time; ds_event.sym = sym; @@ -592,6 +601,7 @@ context_handle_language(struct wl_client *client, ds_inf("context_handle_language() serial(%u) language(%s)", serial, language); + ds_event.im_context = context; ds_event.serial = serial; ds_event.language = language; wl_signal_emit(&context->events.language, &ds_event); @@ -606,6 +616,7 @@ context_handle_text_direction(struct wl_client *client, ds_inf("context_handle_text_direction() serial(%u) direction(%u)", serial, direction); + ds_event.im_context = context; ds_event.serial = serial; ds_event.direction = direction; wl_signal_emit(&context->events.text_direction, &ds_event); -- 2.7.4 From c6b878a8afb44527c778f518c2da7349dfa33078 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Wed, 24 Aug 2022 10:12:38 +0900 Subject: [PATCH 02/16] clients: 'text-entry' fix formatting Change-Id: I5f175968d063363be2cb6343d92ea3e27ce6b60f --- clients/text-entry.c | 300 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 242 insertions(+), 58 deletions(-) diff --git a/clients/text-entry.c b/clients/text-entry.c index a806f0e..ce21d02 100644 --- a/clients/text-entry.c +++ b/clients/text-entry.c @@ -51,7 +51,7 @@ struct display { struct xdg_wm_base *wm_base; struct wl_shm *shm; struct wl_seat *seat; - struct wayland_tbm_client *wl_tbm; + struct wayland_tbm_client *wl_tbm; bool has_xrgb; struct wl_text_input_manager *text_input_mgr; @@ -69,13 +69,13 @@ struct window { struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; struct wl_callback *callback; - tbm_surface_queue_h surface_queue; + tbm_surface_queue_h surface_queue; bool wait_for_configure; }; struct buffer_info { - struct window *window; - struct wl_buffer *wl_buffer; + struct window *window; + struct wl_buffer *wl_buffer; }; struct text_entry { @@ -580,19 +580,19 @@ text_entry_update(struct text_entry *entry) fprintf(stderr, "text_entry_update()\n"); wl_text_input_set_content_type(entry->text_input, - WL_TEXT_INPUT_CONTENT_HINT_NONE, - entry->content_purpose); + WL_TEXT_INPUT_CONTENT_HINT_NONE, + entry->content_purpose); if (entry->preferred_language) wl_text_input_set_preferred_language(entry->text_input, - entry->preferred_language); + entry->preferred_language); text_entry_get_cursor_rectangle(entry, &cursor_rectangle); wl_text_input_set_cursor_rectangle(entry->text_input, - cursor_rectangle.x, - cursor_rectangle.y, - cursor_rectangle.width, - cursor_rectangle.height); + cursor_rectangle.x, + cursor_rectangle.y, + cursor_rectangle.width, + cursor_rectangle.height); wl_text_input_commit_state(entry->text_input, ++entry->serial); } @@ -600,7 +600,7 @@ text_entry_update(struct text_entry *entry) static void text_entry_reset_preedit(struct text_entry *entry) { - fprintf(stderr, "text_entry_reset_preedit()\n"); + fprintf(stderr, "text_entry_reset_preedit()\n"); entry->preedit.cursor = 0; free(entry->preedit.text); @@ -664,9 +664,9 @@ text_entry_commit_and_reset(struct text_entry *entry) static void text_input_enter(void *data, struct wl_text_input *text_input, - struct wl_surface *surface) + struct wl_surface *surface) { - fprintf(stderr, "text_input_enter()\n"); + fprintf(stderr, "text_input_enter()\n"); struct display *d = data; struct text_entry *entry = d->entry; @@ -676,15 +676,16 @@ text_input_enter(void *data, struct wl_text_input *text_input, text_entry_update(entry); entry->reset_serial = entry->serial; } + static void text_input_leave(void *data, struct wl_text_input *text_input) { - fprintf(stderr, "text_input_leave()\n"); + fprintf(stderr, "text_input_leave()\n"); struct display *d = data; struct text_entry *entry = d->entry; - text_entry_commit_and_reset(entry); + text_entry_commit_and_reset(entry); d->entry->active--; if (!entry->active) { @@ -695,81 +696,264 @@ text_input_leave(void *data, struct wl_text_input *text_input) static void text_input_modifiers_map(void *data, struct wl_text_input *text_input, - struct wl_array *map) + struct wl_array *map) { - fprintf(stderr, "text_input_modifiers_map()\n"); + fprintf(stderr, "text_input_modifiers_map()\n"); } static void text_input_input_panel_state(void *data, struct wl_text_input *text_input, - uint32_t state) + uint32_t state) +{ + fprintf(stderr, "text_input_input_panel_state() state:%u\n", state); +} + +static void +clear_pending_preedit(struct text_entry *entry) +{ + fprintf(stderr, "clear_pending_preedit()\n"); + + memset(&entry->pending_commit, 0, sizeof entry->pending_commit); + + entry->preedit_info.cursor = 0; + + memset(&entry->preedit_info, 0, sizeof entry->preedit_info); +} + +static void +text_entry_delete_text(struct text_entry *entry, + uint32_t index, uint32_t length) +{ + uint32_t l; + + fprintf(stderr, "text_entry_delete_text()\n"); + + assert(index <= strlen(entry->text)); + assert(index + length <= strlen(entry->text)); + assert(index + length >= length); + + l = strlen(entry->text + index + length); + memmove(entry->text + index, + entry->text + index + length, + l + 1); + + if (entry->cursor > (index + length)) + entry->cursor -= length; + else if (entry->cursor > index) + entry->cursor = index; + + entry->anchor = entry->cursor; + + text_entry_update(entry); +} + +static void +text_entry_delete_selected_text(struct text_entry *entry) +{ + uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor; + uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor; + + fprintf(stderr, "text_entry_delete_selected_text()\n"); + + if (entry->anchor == entry->cursor) + return; + + text_entry_delete_text(entry, start_index, end_index - start_index); + + entry->anchor = entry->cursor; +} + +static void +text_entry_set_preedit(struct text_entry *entry, + const char *preedit_text, + int preedit_cursor) { - fprintf(stderr, "text_input_input_panel_state() state:%u\n", state); + fprintf(stderr, "text_entry_set_preedit()\n"); + + text_entry_reset_preedit(entry); + + if (!preedit_text) + return; + + entry->preedit.text = strdup(preedit_text); + entry->preedit.cursor = preedit_cursor; } static void text_input_preedit_string(void *data, struct wl_text_input *text_input, - uint32_t serial, const char *text, const char *commit) + uint32_t serial, const char *text, const char *commit) { - fprintf(stderr, "text_input_preedit_string() serial(%u), text(%s), commit(%s)\n", serial, text, commit); + struct display *d = data; + struct text_entry *entry = d->entry; + + fprintf(stderr, "text_input_preedit_string() serial(%u), text(%s), commit(%s)\n", serial, text, commit); + + if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) { + fprintf(stderr, "Ignore preedit_string. Serial: %u, Current: %u, Reset: %u\n", + serial, entry->serial, entry->reset_serial); + clear_pending_preedit(entry); + return; + } + + if (entry->pending_commit.invalid_delete) { + fprintf(stderr, "Ignore preedit_string. Invalid previous delete_surrounding event.\n"); + clear_pending_preedit(entry); + return; + } + + if (entry->pending_commit.delete_length) { + text_entry_delete_text(entry, + entry->pending_commit.delete_index, + entry->pending_commit.delete_length); + } else { + text_entry_delete_selected_text(entry); + } + + text_entry_set_preedit(entry, text, entry->preedit_info.cursor); + entry->preedit.commit = strdup(commit); + + clear_pending_preedit(entry); + + text_entry_update(entry); } static void text_input_preedit_styling(void *data, struct wl_text_input *text_input, - uint32_t index, uint32_t length, uint32_t style) + uint32_t index, uint32_t length, uint32_t style) { - fprintf(stderr, "text_input_preedit_styling() index(%u), length(%u), style(%u)\n", index, length, style); + fprintf(stderr, "text_input_preedit_styling() index(%u), length(%u), style(%u)\n", index, length, style); + + switch (style) { + case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT: + fprintf(stderr, "text_input_preedit_styling() style:DEFAULT"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE: + fprintf(stderr, "text_input_preedit_styling() style:UNDERLINE"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT: + fprintf(stderr, "text_input_preedit_styling() style:INCORRECT"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION: + fprintf(stderr, "text_input_preedit_styling() style:SELECTION"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT: + fprintf(stderr, "text_input_preedit_styling() style:HIGHLIGHT"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE: + fprintf(stderr, "text_input_preedit_styling() style:ACTIVE"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE: + fprintf(stderr, "text_input_preedit_styling() style:INACTIVE"); + break; + default: + fprintf(stderr, "text_input_preedit_styling() no style enum found"); + break; + } } static void text_input_preedit_cursor(void *data, struct wl_text_input *text_input, - int32_t index) + int32_t index) { - fprintf(stderr, "text_input_preedit_cursor() index(%u)\n", index); + struct display *d = data; + struct text_entry *entry = d->entry; + + fprintf(stderr, "text_input_preedit_cursor() index(%u)\n", index); + + entry->preedit_info.cursor = index; } static void text_input_commit_string(void *data, struct wl_text_input *text_input, - uint32_t serial, const char *text) + uint32_t serial, const char *text) { - fprintf(stderr, "text_input_commit_string() serial(%u), text(%s)\n", serial, text); + struct display *d = data; + struct text_entry *entry = d->entry; + + fprintf(stderr, "text_input_commit_string() serial(%u), text(%s)\n", serial, text); + + if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) { + fprintf(stderr, "Ignore commit. Serial: %u, Current: %u, Reset: %u\n", + serial, entry->serial, entry->reset_serial); + return; + } + + if (entry->pending_commit.invalid_delete) { + fprintf(stderr, "Ignore commit. Invalid previous delete_surrounding event.\n"); + memset(&entry->pending_commit, 0, sizeof entry->pending_commit); + return; + } + + text_entry_reset_preedit(entry); + + if (entry->pending_commit.delete_length) { + text_entry_delete_text(entry, + entry->pending_commit.delete_index, + entry->pending_commit.delete_length); + } else { + text_entry_delete_selected_text(entry); + } + + text_entry_insert_at_cursor(entry, text, + entry->pending_commit.cursor, + entry->pending_commit.anchor); + + memset(&entry->pending_commit, 0, sizeof entry->pending_commit); } static void text_input_cursor_position(void *data, struct wl_text_input *text_input, - int32_t index, int32_t anchor) + int32_t index, int32_t anchor) { - fprintf(stderr, "text_input_cursor_position() index(%d), anchor(%d)\n", index, anchor); + fprintf(stderr, "text_input_cursor_position() index(%d), anchor(%d)\n", index, anchor); } static void text_input_delete_surrounding_text(void *data, - struct wl_text_input *text_input, int32_t index, uint32_t length) + struct wl_text_input *text_input, int32_t index, uint32_t length) { - fprintf(stderr, "text_input_delete_surrounding_text() index(%d), length(%u)\n", index, length); + struct text_entry *entry = data; + uint32_t text_length; + + fprintf(stderr, "text_input_delete_surrounding_text() index(%d), length(%u)\n", index, length); + + entry->pending_commit.delete_index = entry->cursor + index; + entry->pending_commit.delete_length = length; + entry->pending_commit.invalid_delete = false; + + text_length = strlen(entry->text); + + if (entry->pending_commit.delete_index > text_length || + length > text_length || + entry->pending_commit.delete_index + length > text_length) { + fprintf(stderr, "delete_surrounding_text: Invalid index: %d," \ + "length %u'; cursor: %u text length: %u\n", index, length, entry->cursor, text_length); + entry->pending_commit.invalid_delete = true; + return; + } } static void text_input_keysym(void *data, struct wl_text_input *text_input, - uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, - uint32_t modifiers) + uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, + uint32_t modifiers) { - fprintf(stderr, "text_input_keysym() serial(%u), time(%u), sym(%u), state(%u), modifiers(%u)\n", - serial, time, sym, state, modifiers); + fprintf(stderr, "text_input_keysym() serial(%u), time(%u), sym(%u), state(%u), modifiers(%u)\n", + serial, time, sym, state, modifiers); } static void text_input_language(void *data, struct wl_text_input *text_input, - uint32_t serial, const char *language) + uint32_t serial, const char *language) { - fprintf(stderr, "text_input_language() serial(%u), language(%s)\n", serial, language); + fprintf(stderr, "text_input_language() serial(%u), language(%s)\n", serial, language); } static void text_input_text_direction(void *data, struct wl_text_input *text_input, - uint32_t serial, uint32_t direction) + uint32_t serial, uint32_t direction) { - fprintf(stderr, "text_input_text_direction() serial(%d), direction(%d)\n", serial, direction); + fprintf(stderr, "text_input_text_direction() serial(%d), direction(%d)\n", serial, direction); } static const struct wl_text_input_listener text_input_listener = { @@ -786,7 +970,7 @@ static const struct wl_text_input_listener text_input_listener = { .keysym = text_input_keysym, .language = text_input_language, .text_direction = text_input_text_direction, - // TIZEN_ONLY(20150918): Support to set the selection region + // TIZEN_ONLY .selection_region = NULL, .private_command = NULL, .input_panel_geometry = NULL, @@ -807,7 +991,7 @@ text_entry_activate(struct display *d) struct wl_surface *surface = d->entered_surface; struct text_entry *entry = d->entry; - fprintf(stderr, "text_entry_activate\n"); + fprintf(stderr, "text_entry_activate\n"); if (entry->click_to_show && entry->active) { entry->panel_visible = !entry->panel_visible; @@ -823,8 +1007,8 @@ text_entry_activate(struct display *d) wl_text_input_show_input_panel(entry->text_input); wl_text_input_activate(entry->text_input, - d->seat, - surface); + d->seat, + surface); } static void @@ -832,9 +1016,9 @@ text_entry_deactivate(struct display *d) { struct text_entry *entry = d->entry; - fprintf(stderr, "text_entry_deactivate\n"); + fprintf(stderr, "text_entry_deactivate\n"); wl_text_input_deactivate(entry->text_input, - d->seat); + d->seat); } static void @@ -858,7 +1042,7 @@ text_entry_create(struct display *d, const char *text) entry = calloc(1, sizeof *entry); if (!entry) - return NULL; + return NULL; entry->text = strdup(text); entry->active = 0; @@ -869,10 +1053,10 @@ text_entry_create(struct display *d, const char *text) entry->text_input = wl_text_input_manager_create_text_input(d->text_input_mgr); wl_text_input_add_listener(entry->text_input, - &text_input_listener, d); + &text_input_listener, d); - d->entry = entry; - fprintf(stderr, "text_entry_create() entry(%p) created.\n", entry); + d->entry = entry; + fprintf(stderr, "text_entry_create() entry(%p) created.\n", entry); return entry; } @@ -990,11 +1174,11 @@ create_display(void) exit(1); } - display->wl_tbm = wayland_tbm_client_init(display->display); - if (!display->wl_tbm) { - fprintf(stderr, "failed wayland_tbm_client_init()\n"); - exit(1); - } + display->wl_tbm = wayland_tbm_client_init(display->display); + if (!display->wl_tbm) { + fprintf(stderr, "failed wayland_tbm_client_init()\n"); + exit(1); + } display->notified = -1; @@ -1007,10 +1191,10 @@ destroy_display(struct display *display) text_entry_destroy(display); if (display->text_input_mgr) - wl_text_input_manager_destroy(display->text_input_mgr); + wl_text_input_manager_destroy(display->text_input_mgr); if (display->seat) - wl_seat_destroy(display->seat); + wl_seat_destroy(display->seat); if (display->shm) wl_shm_destroy(display->shm); @@ -1021,7 +1205,7 @@ destroy_display(struct display *display) if (display->compositor) wl_compositor_destroy(display->compositor); - wayland_tbm_client_deinit(display->wl_tbm); + wayland_tbm_client_deinit(display->wl_tbm); wl_registry_destroy(display->registry); wl_display_flush(display->display); wl_display_disconnect(display->display); -- 2.7.4 From 928ee8905b7248112a372b3de94d0d6058b2d8c9 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Wed, 24 Aug 2022 11:32:57 +0900 Subject: [PATCH 03/16] ime: refactoring. delete new_input_method_context event/listener Change-Id: Iaf93b435f8178b8b8bf2a13d477d9a2364d20503 --- examples/tinyds-tdm.c | 277 ++++++++++++++++++------------------- include/libds-tizen/input_method.h | 3 - src/input_method/input_method.c | 38 ++--- src/text_input/text_input.c | 8 +- tests/tc_input_method.cpp | 31 +---- 5 files changed, 148 insertions(+), 209 deletions(-) diff --git a/examples/tinyds-tdm.c b/examples/tinyds-tdm.c index 56d9412..8ffaec5 100644 --- a/examples/tinyds-tdm.c +++ b/examples/tinyds-tdm.c @@ -217,8 +217,6 @@ struct tinyds_input_method { struct wl_listener destroy; struct wl_listener mgr_destroy; - - struct wl_listener new_im_context; }; struct tinyds_input_method_context { @@ -285,6 +283,9 @@ server_view_at(struct tinyds_server *server, double lx, double ly, static bool add_new_text_input(struct tinyds_server *server); static bool add_new_input_method(struct tinyds_server *server); +static bool add_new_input_method_context( + struct tinyds_input_method *input_method, + struct tinyds_text_input *text_input); static void text_input_mgr_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED); @@ -296,8 +297,6 @@ static void input_method_mgr_handle_destroy(struct wl_listener *listener, static void input_method_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED); -static void input_method_handle_new_im_context(struct wl_listener *listener, - void *data TINYDS_UNUSED); int main(void) @@ -1827,82 +1826,6 @@ output_schedule_commit(struct tinyds_output *output) wl_event_loop_add_idle(ev, output_schedule_commit_handle_idle_timer, output); } -static bool -add_new_text_input(struct tinyds_server *server) -{ - struct tinyds_text_input *text_input; - - text_input = calloc(1, sizeof *text_input); - if (!text_input) - return false; - - text_input->text_input_mgr = ds_tizen_text_input_manager_create(server->display); - if (!text_input->text_input_mgr) { - free(text_input); - ds_err("Could not create ds_tizen_text_input_manager"); - return false; - } - - wl_list_init(&text_input->input_methods); - - text_input->destroy.notify = text_input_mgr_handle_destroy; - ds_tizen_text_input_manager_add_destroy_listener(text_input->text_input_mgr, - &text_input->destroy); - - text_input->new_text_input.notify = text_input_mgr_handle_new_text_input; - ds_tizen_text_input_manager_add_new_text_input_listener(text_input->text_input_mgr, - &text_input->new_text_input); - - text_input->server = server; - server->text_input = text_input; - - ds_inf("Text_Input (%p) added", text_input); - - return true; -} - -static bool -add_new_input_method(struct tinyds_server *server) -{ - struct tinyds_input_method *input_method; - - input_method = calloc(1, sizeof *input_method); - if (!input_method) - return false; - - input_method->input_method = ds_tizen_input_method_create(server->display); - if (!input_method->input_method) { - free(input_method); - ds_err("Could not create ds_tizen_input_method"); - return false; - } - input_method->destroy.notify = input_method_handle_destroy; - ds_tizen_input_method_add_destroy_listener(input_method->input_method, - &input_method->destroy); - - input_method->input_method_mgr = ds_tizen_input_method_manager_create(server->display); - if (!input_method->input_method_mgr) { - free(input_method); - ds_err("Could not create ds_tizen_input_method_manager"); - return false; - } - - input_method->mgr_destroy.notify = input_method_mgr_handle_destroy; - ds_tizen_input_method_manager_add_destroy_listener(input_method->input_method_mgr, - &input_method->mgr_destroy); - - input_method->new_im_context.notify = input_method_handle_new_im_context; - ds_tizen_input_method_add_new_input_method_context_listener(input_method->input_method, - &input_method->new_im_context); - - input_method->server = server; - server->input_method = input_method; - - ds_inf("Input_Method (%p) added", input_method); - - return true; -} - static void text_input_mgr_handle_destroy(struct wl_listener *listener, void *data) { @@ -1935,7 +1858,7 @@ static void text_input_handle_destroy(struct wl_listener *listener, void *data) { struct tinyds_text_input *text_input; - + ds_inf("text_input_handle_destroy"); text_input = wl_container_of(listener, text_input, destroy); @@ -1948,7 +1871,6 @@ text_input_handle_activate(struct wl_listener *listener, void *data) { struct tinyds_text_input *text_input; struct tinyds_input_method *input_method; - struct tinyds_input_method_context *context; struct ds_tizen_text_input_event_activate *event = data; text_input = wl_container_of(listener, text_input, text_input_activate); @@ -1967,17 +1889,8 @@ text_input_handle_activate(struct wl_listener *listener, void *data) text_input->surface = event->surface; - context = calloc(1, sizeof *context); - if (context == NULL) - { - ds_err("calloc is failed. tinyds_input_method_context"); + if (!add_new_input_method_context(input_method, text_input)) return; - } - input_method->context = context; - context->server = text_input->server; - context->context = ds_tizen_input_method_create_context(input_method->input_method); - context->input = text_input; - context->input_method = input_method; // ds_tizen_input_method_send_set_text_input_id(); } @@ -2165,7 +2078,6 @@ input_method_handle_destroy(struct wl_listener *listener, void *data) input_method = wl_container_of(listener, input_method, destroy); wl_list_remove(&input_method->destroy.link); - wl_list_remove(&input_method->new_im_context.link); server = input_method->server; server->input_method = NULL; @@ -2410,71 +2322,152 @@ context_handle_text_direction(struct wl_listener *listener, void *data) ds_tizen_text_input_send_text_direction(text_input->input, event->serial, event->direction); } -static void -input_method_handle_new_im_context(struct wl_listener *listener, void *data) +static bool +add_new_text_input(struct tinyds_server *server) +{ + struct tinyds_text_input *text_input; + + text_input = calloc(1, sizeof *text_input); + if (!text_input) + return false; + + text_input->text_input_mgr = ds_tizen_text_input_manager_create(server->display); + if (!text_input->text_input_mgr) { + free(text_input); + ds_err("Could not create ds_tizen_text_input_manager"); + return false; + } + + wl_list_init(&text_input->input_methods); + + text_input->destroy.notify = text_input_mgr_handle_destroy; + ds_tizen_text_input_manager_add_destroy_listener(text_input->text_input_mgr, + &text_input->destroy); + + text_input->new_text_input.notify = text_input_mgr_handle_new_text_input; + ds_tizen_text_input_manager_add_new_text_input_listener(text_input->text_input_mgr, + &text_input->new_text_input); + + text_input->server = server; + server->text_input = text_input; + + ds_inf("Text_Input (%p) added", text_input); + + return true; +} + +static bool +add_new_input_method(struct tinyds_server *server) { - struct ds_tizen_input_method_context *context = data; struct tinyds_input_method *input_method; - struct tinyds_input_method_context *ctx; - ds_inf("input_method_handle_new_im_context"); + input_method = calloc(1, sizeof *input_method); + if (!input_method) + return false; + + input_method->input_method = ds_tizen_input_method_create(server->display); + if (!input_method->input_method) { + free(input_method); + ds_err("Could not create ds_tizen_input_method"); + return false; + } + input_method->destroy.notify = input_method_handle_destroy; + ds_tizen_input_method_add_destroy_listener(input_method->input_method, + &input_method->destroy); + + input_method->input_method_mgr = ds_tizen_input_method_manager_create(server->display); + if (!input_method->input_method_mgr) { + free(input_method); + ds_err("Could not create ds_tizen_input_method_manager"); + return false; + } - input_method = wl_container_of(listener, input_method, new_im_context); - ctx = input_method->context; + input_method->mgr_destroy.notify = input_method_mgr_handle_destroy; + ds_tizen_input_method_manager_add_destroy_listener(input_method->input_method_mgr, + &input_method->mgr_destroy); - ctx->destroy.notify = context_handle_destroy; - ds_tizen_input_method_context_add_destroy_listener(context, - &ctx->destroy); + input_method->server = server; + server->input_method = input_method; - ctx->im_context_commit_string.notify = context_handle_commit_string; - ds_tizen_input_method_context_add_commit_string_listener(context, - &ctx->im_context_commit_string); + ds_inf("Input_Method (%p) added", input_method); - ctx->im_context_preedit_string.notify = context_handle_preedit_string; - ds_tizen_input_method_context_add_preedit_string_listener(context, - &ctx->im_context_preedit_string); + return true; +} - ctx->im_context_preedit_styling.notify = context_handle_preedit_styling; - ds_tizen_input_method_context_add_preedit_styling_listener(context, - &ctx->im_context_preedit_styling); +static bool +add_new_input_method_context(struct tinyds_input_method *input_method, + struct tinyds_text_input *text_input) +{ + struct tinyds_input_method_context *context; - ctx->im_context_preedit_cursor.notify = context_handle_preedit_cursor; - ds_tizen_input_method_context_add_preedit_cursor_listener(context, - &ctx->im_context_preedit_cursor); + context = calloc(1, sizeof *context); + if (context == NULL) + { + ds_err("calloc is failed. tinyds_input_method_context"); + return false; + } + input_method->context = context; + context->input_method = input_method; + context->server = input_method->server; + context->input = text_input; + + context->context = ds_tizen_input_method_create_context(input_method->input_method); + + context->destroy.notify = context_handle_destroy; + ds_tizen_input_method_context_add_destroy_listener(context->context, + &context->destroy); + + context->im_context_commit_string.notify = context_handle_commit_string; + ds_tizen_input_method_context_add_commit_string_listener(context->context, + &context->im_context_commit_string); - ctx->im_context_delete_surrounding_text.notify = context_handle_delete_surrounding_text; - ds_tizen_input_method_context_add_delete_surrounding_text_listener(context, - &ctx->im_context_delete_surrounding_text); + context->im_context_preedit_string.notify = context_handle_preedit_string; + ds_tizen_input_method_context_add_preedit_string_listener(context->context, + &context->im_context_preedit_string); - ctx->im_context_cursor_position.notify = context_handle_cursor_position; - ds_tizen_input_method_context_add_cursor_position_listener(context, - &ctx->im_context_cursor_position); + context->im_context_preedit_styling.notify = context_handle_preedit_styling; + ds_tizen_input_method_context_add_preedit_styling_listener(context->context, + &context->im_context_preedit_styling); - ctx->im_context_modifiers_map.notify = context_handle_modifiers_map; - ds_tizen_input_method_context_add_modifiers_map_listener(context, - &ctx->im_context_modifiers_map); + context->im_context_preedit_cursor.notify = context_handle_preedit_cursor; + ds_tizen_input_method_context_add_preedit_cursor_listener(context->context, + &context->im_context_preedit_cursor); - ctx->im_context_keysym.notify = context_handle_keysym; - ds_tizen_input_method_context_add_keysym_listener(context, - &ctx->im_context_keysym); + context->im_context_delete_surrounding_text.notify = context_handle_delete_surrounding_text; + ds_tizen_input_method_context_add_delete_surrounding_text_listener(context->context, + &context->im_context_delete_surrounding_text); - ctx->im_context_grab_keyboard.notify = context_handle_grab_keyboard; - ds_tizen_input_method_context_add_grab_keyboard_listener(context, - &ctx->im_context_grab_keyboard); + context->im_context_cursor_position.notify = context_handle_cursor_position; + ds_tizen_input_method_context_add_cursor_position_listener(context->context, + &context->im_context_cursor_position); - ctx->im_context_key.notify = context_handle_key; - ds_tizen_input_method_context_add_key_listener(context, - &ctx->im_context_key); + context->im_context_modifiers_map.notify = context_handle_modifiers_map; + ds_tizen_input_method_context_add_modifiers_map_listener(context->context, + &context->im_context_modifiers_map); - ctx->im_context_modifiers.notify = context_handle_modifiers; - ds_tizen_input_method_context_add_modifiers_listener(context, - &ctx->im_context_modifiers); + context->im_context_keysym.notify = context_handle_keysym; + ds_tizen_input_method_context_add_keysym_listener(context->context, + &context->im_context_keysym); - ctx->im_context_language.notify = context_handle_language; - ds_tizen_input_method_context_add_language_listener(context, - &ctx->im_context_language); + context->im_context_grab_keyboard.notify = context_handle_grab_keyboard; + ds_tizen_input_method_context_add_grab_keyboard_listener(context->context, + &context->im_context_grab_keyboard); - ctx->im_context_text_direction.notify = context_handle_text_direction; - ds_tizen_input_method_context_add_text_direction_listener(context, - &ctx->im_context_text_direction); + context->im_context_key.notify = context_handle_key; + ds_tizen_input_method_context_add_key_listener(context->context, + &context->im_context_key); + + context->im_context_modifiers.notify = context_handle_modifiers; + ds_tizen_input_method_context_add_modifiers_listener(context->context, + &context->im_context_modifiers); + + context->im_context_language.notify = context_handle_language; + ds_tizen_input_method_context_add_language_listener(context->context, + &context->im_context_language); + + context->im_context_text_direction.notify = context_handle_text_direction; + ds_tizen_input_method_context_add_text_direction_listener(context->context, + &context->im_context_text_direction); + + return true; } diff --git a/include/libds-tizen/input_method.h b/include/libds-tizen/input_method.h index 2209026..c6a40c2 100644 --- a/include/libds-tizen/input_method.h +++ b/include/libds-tizen/input_method.h @@ -103,9 +103,6 @@ ds_tizen_input_method_create_context(struct ds_tizen_input_method *input_method) void ds_tizen_input_method_add_destroy_listener( struct ds_tizen_input_method *im, struct wl_listener *listener); -void -ds_tizen_input_method_add_new_input_method_context_listener( - struct ds_tizen_input_method *im, struct wl_listener *listener); // events void ds_tizen_input_method_send_activate(struct ds_tizen_input_method *im, diff --git a/src/input_method/input_method.c b/src/input_method/input_method.c index eb6232b..8eed2f2 100644 --- a/src/input_method/input_method.c +++ b/src/input_method/input_method.c @@ -42,7 +42,6 @@ struct ds_tizen_input_method { struct { struct wl_signal destroy; - struct wl_signal new_input_method_context; } events; }; @@ -115,30 +114,23 @@ static const struct zwp_input_method_manager_v1_interface input_method_mgr_impl }; static void -input_method_mgr_client_handle_destroy(struct wl_resource *resource) -{ - ds_inf("input_method_mgr_client_handle_destroy"); -} - -static void input_method_mgr_bind(struct wl_client *wl_client, void *data, uint32_t version, uint32_t id) { struct ds_tizen_input_method_manager *input_method_mgr = data; - struct wl_resource *resource; ds_inf("input_method_mgr. client binds. (client:%p)", wl_client); - resource = wl_resource_create(wl_client, + input_method_mgr->resource = wl_resource_create(wl_client, &zwp_input_method_manager_v1_interface, version, id); - if (resource == NULL) { + if (input_method_mgr->resource == NULL) { ds_err("input_method_mgr. wl_resource_create() failed."); wl_client_post_no_memory(wl_client); return; } - wl_resource_set_implementation(resource, &input_method_mgr_impl, - input_method_mgr, input_method_mgr_client_handle_destroy); + wl_resource_set_implementation(input_method_mgr->resource, &input_method_mgr_impl, + input_method_mgr, NULL); } WL_EXPORT struct ds_tizen_input_method_manager * @@ -178,13 +170,6 @@ ds_tizen_input_method_add_destroy_listener( } WL_EXPORT void -ds_tizen_input_method_add_new_input_method_context_listener( - struct ds_tizen_input_method *im, struct wl_listener *listener) -{ - wl_signal_add(&im->events.new_input_method_context, listener); -} - -WL_EXPORT void ds_tizen_input_method_send_activate(struct ds_tizen_input_method *im, struct ds_tizen_input_method_context *context) { @@ -243,6 +228,10 @@ ds_tizen_input_method_create_context(struct ds_tizen_input_method *input_method) if (!binding) return NULL; context->resource = wl_resource_create(wl_resource_get_client(binding), &zwp_input_method_context_v1_interface, INPUT_METHOD_VERSION, 0); + if (context->resource == NULL) { + ds_err("context. wl_resource_create() failed."); + return NULL; + } wl_resource_set_implementation(context->resource, &context_impl, context, input_method_context_client_handle_destroy); @@ -261,8 +250,6 @@ ds_tizen_input_method_create_context(struct ds_tizen_input_method *input_method) wl_signal_init(&context->events.language); wl_signal_init(&context->events.text_direction); - wl_signal_emit(&input_method->events.new_input_method_context, context); - ds_tizen_input_method_send_activate(input_method, context); input_method->context = context; @@ -675,12 +662,6 @@ input_method_handle_display_destroy(struct wl_listener *listener, void *data) } static void -input_method_client_handle_destroy(struct wl_resource *resource) -{ - ds_inf("input_method_client_handle_destroy"); -} - -static void input_method_bind(struct wl_client *wl_client, void *data, uint32_t version, uint32_t id) { @@ -697,7 +678,7 @@ input_method_bind(struct wl_client *wl_client, void *data, return; } wl_resource_set_implementation(input_method->resource, NULL, - input_method, input_method_client_handle_destroy); + input_method, NULL); } WL_EXPORT struct ds_tizen_input_method * @@ -719,7 +700,6 @@ ds_tizen_input_method_create(struct wl_display *display) } wl_signal_init(&input_method->events.destroy); - wl_signal_init(&input_method->events.new_input_method_context); input_method->destroy.notify = input_method_handle_display_destroy; wl_display_add_destroy_listener(display, &input_method->destroy); diff --git a/src/text_input/text_input.c b/src/text_input/text_input.c index 7a9c4f2..05adda7 100644 --- a/src/text_input/text_input.c +++ b/src/text_input/text_input.c @@ -472,12 +472,6 @@ static const struct wl_text_input_manager_interface text_input_mgr_impl = }; static void -text_input_mgr_client_handle_destroy(struct wl_resource *resource) -{ - ds_inf("text_input_mgr_client_handle_destroy"); -} - -static void text_input_mgr_bind(struct wl_client *wl_client, void *data, uint32_t version, uint32_t id) { @@ -495,7 +489,7 @@ text_input_mgr_bind(struct wl_client *wl_client, void *data, return; } wl_resource_set_implementation(resource, &text_input_mgr_impl, - text_input_mgr, text_input_mgr_client_handle_destroy); + text_input_mgr, NULL); } WL_EXPORT struct ds_tizen_text_input_manager * diff --git a/tests/tc_input_method.cpp b/tests/tc_input_method.cpp index 1bbc1be..a9b1ecf 100644 --- a/tests/tc_input_method.cpp +++ b/tests/tc_input_method.cpp @@ -41,13 +41,6 @@ public: mockComp->mDestroyListener.parent = mockComp; ds_tizen_input_method_add_destroy_listener(mockComp->mInputMethod, &mockComp->mDestroyListener); - - // new input method context listener - mockComp->mNewInputMethodContextListener.notify = - MockInputMethodCompositor::NewInputMethodContextCallback; - mockComp->mNewInputMethodContextListener.parent = mockComp; - ds_tizen_input_method_add_new_input_method_context_listener(mockComp->mInputMethod, - &mockComp->mNewInputMethodContextListener); } static void DestroyCallback(struct wl_listener *listener, void *data) @@ -60,26 +53,13 @@ public: mockComp->bDestroyed = true; } - static void NewInputMethodContextCallback(struct wl_listener *listener, void *data) - { - ds_inf("%s", __func__); - - MockInputMethodCompositor *mockComp = - reinterpret_cast(listener)->parent; - struct ds_tizen_input_method_context *context = - static_cast(data); - - ds_inf("%s: mockComp(%p), input_method_context(%p)", __func__, mockComp, context); - - mockComp->mInputMethodContext = context; - mockComp->bNewInputMethodContext = true; - } - void CreateInputMethodContext() { ds_inf("%s", __func__); - ds_tizen_input_method_create_context(mInputMethod); + mInputMethodContext = ds_tizen_input_method_create_context(mInputMethod); + if (mInputMethodContext) + bNewInputMethodContext = true; } void SendActivate() @@ -109,11 +89,6 @@ private: MockInputMethodCompositor *parent; }; DestroyListener mDestroyListener; - - struct NewInputMethodContextListener: ::wl_listener { - MockInputMethodCompositor *parent; - }; - NewInputMethodContextListener mNewInputMethodContextListener; }; class MockInputMethodClient : public MockClient -- 2.7.4 From 2c3579b368eabb2b245e902affdbf0def9d06083 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Wed, 24 Aug 2022 13:31:47 +0900 Subject: [PATCH 04/16] Update .gitignore This adds vim swapfiles. Change-Id: Ifce2e25131882a52806f7df06dc6d7c437f4093f --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index c6127b3..7ca031c 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,7 @@ modules.order Module.symvers Mkfile.old dkms.conf + +# Vim swapfiles +.*.sw? +.sw? -- 2.7.4 From fdde359c1102cb86740e77f44e20edd4d60e5c56 Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Wed, 24 Aug 2022 15:40:50 +0900 Subject: [PATCH 05/16] implement ds_tizen_hwc This is the server implementation for tizen_hwc protocol. Change-Id: I4ba3b103efaf6ce2c8863d63f26b40e120ffc327 --- include/libds-tizen/hwc.h | 49 ++++++ packaging/libds-tizen.spec | 32 ++++ src/hwc/hwc.c | 297 +++++++++++++++++++++++++++++++++ src/hwc/meson.build | 29 ++++ src/meson.build | 3 +- tests/meson.build | 22 ++- tests/tc_hwc.cpp | 398 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 828 insertions(+), 2 deletions(-) create mode 100644 include/libds-tizen/hwc.h create mode 100644 src/hwc/hwc.c create mode 100644 src/hwc/meson.build create mode 100644 tests/tc_hwc.cpp diff --git a/include/libds-tizen/hwc.h b/include/libds-tizen/hwc.h new file mode 100644 index 0000000..11ffe9c --- /dev/null +++ b/include/libds-tizen/hwc.h @@ -0,0 +1,49 @@ +#ifndef LIBDS_TIZEN_HWC_H +#define LIBDS_TIZEN_HWC_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tizen_hwc; + +struct ds_tizen_hwc_commit_feedback; + +struct ds_tizen_hwc * +ds_tizen_hwc_create(struct wl_display *display); + +void +ds_tizen_hwc_add_destroy_listener(struct ds_tizen_hwc *hwc, + struct wl_listener *listener); + +void +ds_tizen_hwc_add_new_commit_feedback_listener( + struct ds_tizen_hwc *hwc, + struct wl_listener *listener); + +void +ds_tizen_hwc_commit_feedback_add_destroy_listener( + struct ds_tizen_hwc_commit_feedback *commit_feedback, + struct wl_listener *listener); + +struct ds_surface * +ds_tizen_hwc_commit_feedback_get_surface( + struct ds_tizen_hwc_commit_feedback *commit_feedback); + +void +ds_tizen_hwc_commit_feedback_send_committed( + struct ds_tizen_hwc_commit_feedback *commit_feedback); + +void +ds_tizen_hwc_commit_feedback_send_discarded( + struct ds_tizen_hwc_commit_feedback *commit_feedback); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index fc126c7..53d3d2f 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -32,6 +32,8 @@ BuildRequires: pkgconfig(tizen-dpms-server) BuildRequires: pkgconfig(tizen-dpms-client) BuildRequires: pkgconfig(tizen-surface-server) BuildRequires: pkgconfig(tizen-surface-client) +BuildRequires : pkgconfig(tizen-hwc-server) +BuildRequires : pkgconfig(tizen-hwc-client) BuildRequires: pkgconfig(cynara-client) BuildRequires: pkgconfig(cynara-session) BuildRequires: pkgconfig(libsmack) @@ -295,6 +297,21 @@ Group: Development/Libraries %description input-method-devel Development package for tizen input-method +## libds-tizen-hwc +%package hwc +Summary: Library for tizen hwc +Group: Development/Libraries + +%description hwc +Library for tizen hwc + +%package hwc-devel +Summary: Development package for tizen hwc +Group: Development/Libraries + +%description hwc-devel +Development package for tizen hwc + %prep %setup -q cp %{SOURCE1001} . @@ -571,3 +588,18 @@ ninja -C builddir install %{_bindir}/libds-tizen-input-method-tests %{_bindir}/libds-tizen-input-method-manager-tests %{_bindir}/ime-keyboard + +%files hwc +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_libdir}/libds-tizen-hwc.so* + +%files hwc-devel +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_includedir}/libds-tizen/hwc.h +%{_libdir}/pkgconfig/libds-tizen-hwc.pc +%{_libdir}/libds-tizen-hwc.so* +%{_bindir}/libds-tizen-hwc-tests diff --git a/src/hwc/hwc.c b/src/hwc/hwc.c new file mode 100644 index 0000000..7346911 --- /dev/null +++ b/src/hwc/hwc.c @@ -0,0 +1,297 @@ +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "libds-tizen/hwc.h" + +#define TIZEN_HWC_VERSION 1 + +struct ds_tizen_hwc +{ + struct wl_global *global; + + struct wl_list clients; + + struct wl_listener destroy; + + struct { + struct wl_signal destroy; + struct wl_signal new_commit_feedback; + } events; +}; + +struct ds_tizen_hwc_client +{ + struct ds_tizen_hwc *hwc; + + struct wl_resource *resource; + struct wl_client *wl_client; + + struct { + struct wl_signal destroy; + } events; + + struct wl_list link; +}; + +struct ds_tizen_hwc_commit_feedback +{ + struct wl_resource *resource; + + struct ds_surface *surface; + uint32_t serial; + + struct { + struct wl_listener surface_destroy; + } listener; + + struct { + struct wl_signal destroy; + } events; +}; + +static void +hwc_commit_feedback_handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tizen_hwc_commit_feedback *commit_feedback; + + commit_feedback = wl_container_of(listener, commit_feedback, + listener.surface_destroy); + + if (commit_feedback->listener.surface_destroy.notify) { + wl_list_remove(&commit_feedback->listener.surface_destroy.link); + commit_feedback->listener.surface_destroy.notify = NULL; + } + + commit_feedback->surface = NULL; +} + +static void +_hwc_commit_feedback_cb_resource_destroy(struct wl_resource *commit_feedback_resource) +{ + struct ds_tizen_hwc_commit_feedback *commit_feedback; + + commit_feedback = wl_resource_get_user_data(commit_feedback_resource); + + ds_inf("hwc_commit_feedback:%p destroy", commit_feedback); + + if (commit_feedback->listener.surface_destroy.notify) { + wl_list_remove(&commit_feedback->listener.surface_destroy.link); + commit_feedback->listener.surface_destroy.notify = NULL; + } + + wl_signal_emit(&commit_feedback->events.destroy, commit_feedback); + + free(commit_feedback); +} + +static void +hwc_handle_create_commit_feedback(struct wl_client *client, + struct wl_resource *hwc_client_resource, + struct wl_resource *surface_resource, + uint32_t id, + uint32_t serial) +{ + struct ds_tizen_hwc_client *hwc_client; + struct ds_tizen_hwc_commit_feedback *commit_feedback; + struct ds_surface *surface; + + hwc_client = wl_resource_get_user_data(hwc_client_resource); + + surface = ds_surface_from_resource(surface_resource); + + commit_feedback = calloc(1, sizeof *commit_feedback); + if (!commit_feedback) { + wl_client_post_no_memory(client); + return; + } + + commit_feedback->resource = wl_resource_create(client, &tizen_hwc_commit_feedback_interface, + wl_resource_get_version(hwc_client_resource), id); + if (!commit_feedback->resource) { + wl_client_post_no_memory(client); + free(commit_feedback); + return; + } + + commit_feedback->listener.surface_destroy.notify = hwc_commit_feedback_handle_surface_destroy; + ds_surface_add_destroy_listener(surface, &commit_feedback->listener.surface_destroy); + commit_feedback->surface = surface; + + commit_feedback->serial = serial; + + wl_resource_set_implementation(commit_feedback->resource, NULL, + commit_feedback, _hwc_commit_feedback_cb_resource_destroy); + + ds_inf("hwc_commit_feedback:%p create", commit_feedback); + + wl_signal_init(&commit_feedback->events.destroy); + + wl_signal_emit(&hwc_client->hwc->events.new_commit_feedback, commit_feedback); +} + +static void +hwc_handle_destroy(struct wl_client *wl_client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct tizen_hwc_interface hwc_impl = +{ + .destroy = hwc_handle_destroy, + .create_commit_feedback = hwc_handle_create_commit_feedback, +}; + +static void +_tizen_hwc_client_handle_resource_destroy(struct wl_resource *resource) +{ + struct ds_tizen_hwc_client *client; + + client = wl_resource_get_user_data(resource); + + ds_inf("_tizen_hwc_client_handle_destroy (client:%p)", client); + + wl_list_remove(&client->link); + free(client); +} + +static void +hwc_bind(struct wl_client *wl_client, void *data, uint32_t version, + uint32_t id) +{ + struct ds_tizen_hwc *hwc = data; + struct ds_tizen_hwc_client *hwc_client; + + hwc_client = calloc(1, sizeof *hwc_client); + if (hwc_client == NULL) { + ds_err("calloc() failed. tizen_hwc"); + wl_client_post_no_memory(wl_client); + return; + } + + ds_inf("tizen_hwc_client binds. (hwc_client:%p)", hwc_client); + + hwc_client->hwc = hwc; + hwc_client->wl_client = wl_client; + + hwc_client->resource = wl_resource_create(wl_client, &tizen_hwc_interface, + MIN(version, TIZEN_HWC_VERSION), id); + if (hwc_client->resource == NULL) { + ds_err("tizen_hwc : wl_resource_create() failed."); + free(hwc_client); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(hwc_client->resource, &hwc_impl, hwc_client, + _tizen_hwc_client_handle_resource_destroy); + + wl_signal_init(&hwc_client->events.destroy); + + wl_list_insert(&hwc->clients, &hwc_client->link); +} + +static void +hwc_handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tizen_hwc *hwc; + + hwc = wl_container_of(listener, hwc, destroy); + + ds_inf("Global destroy: hwc(%p)", hwc); + + wl_signal_emit(&hwc->events.destroy, hwc); + wl_list_remove(&hwc->destroy.link); + wl_global_destroy(hwc->global); + free(hwc); +} + +WL_EXPORT struct ds_tizen_hwc * +ds_tizen_hwc_create(struct wl_display *display) +{ + struct ds_tizen_hwc *hwc; + + hwc = calloc(1, sizeof *hwc); + if (!hwc) { + ds_err("calloc() failed."); + return NULL; + } + + hwc->global = wl_global_create(display, &tizen_hwc_interface, + TIZEN_HWC_VERSION, hwc, hwc_bind); + if (!hwc->global) { + ds_err("wl_global_create() failed. tizen_hwc_interface"); + free(hwc); + return NULL; + } + + wl_list_init(&hwc->clients); + + hwc->destroy.notify = hwc_handle_display_destroy; + wl_display_add_destroy_listener(display, &hwc->destroy); + + wl_signal_init(&hwc->events.destroy); + wl_signal_init(&hwc->events.new_commit_feedback); + + ds_inf("Global created: tizen_hwc(%p)", hwc); + + return hwc; +} + +WL_EXPORT void +ds_tizen_hwc_add_destroy_listener( + struct ds_tizen_hwc *hwc, + struct wl_listener *listener) +{ + wl_signal_add(&hwc->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_hwc_add_new_commit_feedback_listener( + struct ds_tizen_hwc *hwc, + struct wl_listener *listener) +{ + wl_signal_add(&hwc->events.new_commit_feedback, listener); +} + +WL_EXPORT void +ds_tizen_hwc_commit_feedback_add_destroy_listener( + struct ds_tizen_hwc_commit_feedback *commit_feedback, + struct wl_listener *listener) +{ + wl_signal_add(&commit_feedback->events.destroy, listener); +} + +WL_EXPORT struct ds_surface * +ds_tizen_hwc_commit_feedback_get_surface( + struct ds_tizen_hwc_commit_feedback *commit_feedback) +{ + return commit_feedback->surface; +} + +WL_EXPORT void +ds_tizen_hwc_commit_feedback_send_committed( + struct ds_tizen_hwc_commit_feedback *commit_feedback) +{ + ds_inf("hwc_commit_feedback:%p send committed", commit_feedback); + + tizen_hwc_commit_feedback_send_committed(commit_feedback->resource, + commit_feedback->serial); + wl_resource_destroy(commit_feedback->resource); +} + +WL_EXPORT void +ds_tizen_hwc_commit_feedback_send_discarded( + struct ds_tizen_hwc_commit_feedback *commit_feedback) +{ + ds_inf("hwc_commit_feedback:%p send discard", commit_feedback); + + tizen_hwc_commit_feedback_send_discarded(commit_feedback->resource, + commit_feedback->serial); + wl_resource_destroy(commit_feedback->resource); +} diff --git a/src/hwc/meson.build b/src/hwc/meson.build new file mode 100644 index 0000000..7f9caa0 --- /dev/null +++ b/src/hwc/meson.build @@ -0,0 +1,29 @@ +libds_tizen_hwc_files = [ + 'hwc.c', +] + +libds_tizen_hwc_deps = [ + deps_libds_tizen, + dependency('tizen-hwc-server', required: true), +] + +lib_libds_tizen_hwc = shared_library('ds-tizen-hwc', libds_tizen_hwc_files, + dependencies: libds_tizen_hwc_deps, + include_directories: [ common_inc, include_directories('.'), include_directories('..') ], + version: meson.project_version(), + install: true +) + +deps_libds_tizen_hwc = declare_dependency( + link_with: lib_libds_tizen_hwc, + dependencies: libds_tizen_hwc_deps, + include_directories: [ common_inc, include_directories('.') ], +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(lib_libds_tizen_hwc, + version: meson.project_version(), + filebase: 'libds-tizen-hwc', + name: 'libds-tizen-hwc', + description: 'tizen hwc extension of libds-tizen for tizen platform', +) diff --git a/src/meson.build b/src/meson.build index aef63ac..8d254fa 100644 --- a/src/meson.build +++ b/src/meson.build @@ -43,4 +43,5 @@ subdir('screen_rotation') subdir('global_resource') subdir('embedded_compositor') subdir('input_method') -subdir('text_input') \ No newline at end of file +subdir('text_input') +subdir('hwc') diff --git a/tests/meson.build b/tests/meson.build index 0405794..1b78a64 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -283,4 +283,24 @@ executable('libds-tizen-text-input-tests', ], install_dir: libds_tizen_bindir, install : true -) \ No newline at end of file +) + +## hwc tests +tc_hwc_files = [ + 'tc_main.cpp', + 'tc_hwc.cpp', +] + +executable('libds-tizen-hwc-tests', + [ + tc_mock_files, + tc_hwc_files + ], + dependencies: [ + deps_test_common, + deps_libds_tizen_hwc, + dependency('tizen-hwc-client', required: true), + ], + install_dir: libds_tizen_bindir, + install : true +) diff --git a/tests/tc_hwc.cpp b/tests/tc_hwc.cpp new file mode 100644 index 0000000..77c93b1 --- /dev/null +++ b/tests/tc_hwc.cpp @@ -0,0 +1,398 @@ +#include "tc_main.h" +#include "mockclient.h" +#include "mockcompositor.h" +#include +#include + +#define TIZEN_HWC_VERSION 1 + +class MockHwcCompositor : public MockCompositor +{ +public: + MockHwcCompositor() + : MockCompositor(&MockHwcCompositor::TestSetup, this) + { + ds_inf("%s : this(%p)", __func__, this); + + bHwcDestroyed = false; + bSurfaceDestroyed = false; + } + + ~MockHwcCompositor() + { + ds_inf("%s : this(%p)", __func__, this); + } + + static void TestSetup(void *data) + { + MockHwcCompositor *mockComp = + static_cast(data); + Compositor *comp = mockComp->compositor; + + ds_inf("%s: mockComp(%p)", __func__, mockComp); + + // new surface listener + mockComp->mNewSurfaceListener.notify = + MockHwcCompositor::NewSurfaceCallback; + mockComp->mNewSurfaceListener.parent = mockComp; + ds_compositor_add_new_surface_listener(comp->compositor, + &mockComp->mNewSurfaceListener); + + mockComp->mHwc = + ds_tizen_hwc_create(comp->display); + + // destroy listener + mockComp->mHwcDestroyListener.notify = + MockHwcCompositor::HwcDestroyCallback; + mockComp->mHwcDestroyListener.parent = mockComp; + ds_tizen_hwc_add_destroy_listener(mockComp->mHwc, + &mockComp->mHwcDestroyListener); + + // add_ignore_output_transform listener + mockComp->mHwcNewCommitFeedbackListener.notify = + MockHwcCompositor::HwcNewCommitFeedbackCallback; + mockComp->mHwcNewCommitFeedbackListener.parent = mockComp; + ds_tizen_hwc_add_new_commit_feedback_listener( + mockComp->mHwc, + &mockComp->mHwcNewCommitFeedbackListener); + } + + static void NewSurfaceCallback(struct wl_listener *listener, void *data) + { + MockHwcCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + mockComp->mSurface = surface; + + // del surface listener + mockComp->mDelSurfaceListener.notify = + MockHwcCompositor::DelSurfaceCallback; + mockComp->mDelSurfaceListener.parent = mockComp; + ds_surface_add_destroy_listener(surface, + &mockComp->mDelSurfaceListener); + } + + static void DelSurfaceCallback(struct wl_listener *listener, void *data) + { + MockHwcCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + if (ds_surface_get_wl_resource(mockComp->mSurface) == + ds_surface_get_wl_resource(surface)) { + ds_inf("%s: surface is deleted.", __func__); + mockComp->bSurfaceDestroyed = true; + } + } + + static void HwcDestroyCallback(struct wl_listener *listener, void *data) + { + ds_inf("%s", __func__); + + MockHwcCompositor *mockComp = + reinterpret_cast(listener)->parent; + + mockComp->bHwcDestroyed = true; + } + + static void HwcNewCommitFeedbackCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockHwcCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_hwc_commit_feedback *commitFeedback = + static_cast(data); + + ds_inf("%s: mockComp(%p), commitFeedback(%p)", __func__, mockComp, commitFeedback); + + mockComp->mCommitFeedback = commitFeedback; + mockComp->mSurface = + ds_tizen_hwc_commit_feedback_get_surface(mockComp->mCommitFeedback); + + mockComp->mHwcCommitFeedbackDestroyListener.notify = + MockHwcCompositor::HwcCommitFeedbackDestroyCallback; + mockComp->mHwcCommitFeedbackDestroyListener.parent = mockComp; + ds_tizen_hwc_commit_feedback_add_destroy_listener(mockComp->mCommitFeedback, + &mockComp->mHwcCommitFeedbackDestroyListener); + } + + static void HwcCommitFeedbackDestroyCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockHwcCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_hwc_commit_feedback *commitFeedback = + static_cast(data); + + ds_inf("%s: mockComp(%p), info(%p)", __func__, mockComp, commitFeedback); + + if (mockComp->mCommitFeedback == commitFeedback) { + ds_inf("%s: commitFeedback is deleted.", __func__); + } + } + + void SendHwcCommitFeedbackCommitted(void) + { + ds_inf("%s", __func__); + + ds_tizen_hwc_commit_feedback_send_committed(mCommitFeedback); + } + + void SendHwcCommitFeedbackDiscarded(void) + { + ds_inf("%s", __func__); + + ds_tizen_hwc_commit_feedback_send_discarded(mCommitFeedback); + } + +public: + bool bHwcDestroyed; + bool bSurfaceDestroyed; + +private: + struct ds_tizen_hwc *mHwc; + + struct HwcDestroyListener : ::wl_listener { + MockHwcCompositor *parent; + }; + HwcDestroyListener mHwcDestroyListener; + + struct ds_surface *mSurface; + + struct NewSurfaceListener : ::wl_listener { + MockHwcCompositor *parent; + }; + NewSurfaceListener mNewSurfaceListener; + + struct DelSurfaceListener : ::wl_listener { + MockHwcCompositor *parent; + }; + DelSurfaceListener mDelSurfaceListener; + + struct ds_tizen_hwc_commit_feedback *mCommitFeedback; + + struct HwcNewCommitFeedbackListener : ::wl_listener { + MockHwcCompositor *parent; + }; + HwcNewCommitFeedbackListener mHwcNewCommitFeedbackListener; + + struct HwcCommitFeedbackDestroyListener : ::wl_listener { + MockHwcCompositor *parent; + }; + HwcCommitFeedbackDestroyListener mHwcCommitFeedbackDestroyListener; +}; + +class MockHwcClient : public MockClient +{ +public: + MockHwcClient() + : bCommittedEvent(false), + bDiscardedEvent(false), + compositorRes(nullptr), + tizenHwcRes(nullptr) + {} + MockHwcClient(const struct wl_registry_listener *listener) + : MockClient(listener, this) + { + ds_inf("%s", __func__); + } + ~MockHwcClient() + { + ds_inf("%s", __func__); + } + + void SetWlCompositor(struct wl_compositor *globalRes) + { + ds_inf("%s", __func__); + + compositorRes = globalRes; + } + + struct wl_compositor *GetWlCompositor() + { + ds_inf("%s", __func__); + + return compositorRes; + } + + void SetTizenHwc(struct tizen_hwc *resource) + { + ds_inf("%s", __func__); + + tizenHwcRes = resource; + } + + struct tizen_hwc *GetTizenHwc() + { + ds_inf("%s", __func__); + + return tizenHwcRes; + } + +public: + bool bCommittedEvent; + bool bDiscardedEvent; +private: + struct wl_compositor *compositorRes; + struct tizen_hwc *tizenHwcRes; +}; + +static void +client_registry_cb_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + ds_inf("%s", __func__); + + MockHwcClient *client = static_cast(data); + struct wl_compositor *compositor_res; + struct tizen_hwc *tizen_hwc_res; + + if (!strcmp(interface, "wl_compositor")) { + compositor_res = (struct wl_compositor *)wl_registry_bind(registry, + name, &wl_compositor_interface, 1); + if (compositor_res == nullptr) { + ds_err("wl_registry_bind() failed. wl_compositor resource."); + return; + } + client->SetWlCompositor(compositor_res); + } else if (!strcmp(interface, "tizen_hwc")) { + tizen_hwc_res = (struct tizen_hwc *)wl_registry_bind(registry, + name, &tizen_hwc_interface, TIZEN_HWC_VERSION); + if (tizen_hwc_res == nullptr) { + ds_err("wl_registry_bind() failed. tizen_hwc resource."); + return; + } + client->SetTizenHwc(tizen_hwc_res); + } +} + +static void +client_registry_cb_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ + ds_inf("%s", __func__); + + MockHwcClient *client = static_cast(data); + struct wl_compositor *compositor_res = client->GetWlCompositor(); + struct tizen_hwc *tizen_hwc_res = client->GetTizenHwc(); + + tizen_hwc_destroy(tizen_hwc_res); + wl_compositor_destroy(compositor_res); +} + +static const struct wl_registry_listener registry_listener = { + .global = client_registry_cb_global, + .global_remove = client_registry_cb_global_remove +}; + +class HwcTest : public ::testing::Test +{ +public: + void SetUp(void) override; + void TearDown(void) override; + + MockHwcCompositor *comp; + MockHwcClient *client; + struct wl_compositor *compositorRes; + struct tizen_hwc *tizenHwcRes; + struct wl_surface *surfaceRes; + struct tizen_hwc_commit_feedback *tizenHwcCommitFeedbackRes; +}; + +static void +tizen_hwc_commit_feedback_cb_committed(void *data, + struct tizen_hwc_commit_feedback *hwc_commit_feedback, + uint32_t serial) +{ + ds_inf("%s", __func__); + + MockHwcClient *client = static_cast(data); + + client->bCommittedEvent = true; + + tizen_hwc_commit_feedback_destroy(hwc_commit_feedback); +} + +static void +tizen_hwc_commit_feedback_cb_discarded(void *data, + struct tizen_hwc_commit_feedback *hwc_commit_feedback, + uint32_t serial) +{ + ds_inf("%s", __func__); + + MockHwcClient *client = static_cast(data); + + client->bDiscardedEvent = true; + + tizen_hwc_commit_feedback_destroy(hwc_commit_feedback); +} + +static const struct tizen_hwc_commit_feedback_listener tizen_hwc_commit_feedback_cb_listener = { + .committed = tizen_hwc_commit_feedback_cb_committed, + .discarded = tizen_hwc_commit_feedback_cb_discarded, +}; + +void +HwcTest::SetUp(void) +{ + ds_inf("%s", __func__); + + comp = new MockHwcCompositor(); + client = new MockHwcClient(®istry_listener); + compositorRes = client->GetWlCompositor(); + tizenHwcRes = client->GetTizenHwc(); + surfaceRes = wl_compositor_create_surface(compositorRes); + + tizenHwcCommitFeedbackRes = + tizen_hwc_create_commit_feedback(tizenHwcRes, surfaceRes, 1); + + tizen_hwc_commit_feedback_add_listener(tizenHwcCommitFeedbackRes, + &tizen_hwc_commit_feedback_cb_listener, client); + + client->RoundTrip(); +} + +void +HwcTest::TearDown(void) +{ + ds_inf("%s", __func__); + + wl_surface_destroy(surfaceRes); + client->RoundTrip(); + EXPECT_TRUE(comp->bSurfaceDestroyed); + + delete client; + delete comp; +} + +TEST_F(HwcTest, Create_P) +{ + EXPECT_TRUE(true); +} + +TEST_F(HwcTest, Ev_TizenHwcCommitFeedbackCommitted) +{ + comp->SendHwcCommitFeedbackCommitted(); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->bCommittedEvent); +} + +TEST_F(HwcTest, Ev_TizenHwcCommitFeedbackDiscared) +{ + comp->SendHwcCommitFeedbackDiscarded(); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->bDiscardedEvent); +} -- 2.7.4 From 4d948ed0eeb40a20867fe962ff4593f1560ccc23 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Fri, 2 Sep 2022 15:28:39 +0900 Subject: [PATCH 06/16] tinyds: use 'rand_r' instead of function 'rand' For thread safety, rand_r is preferred to use. Change-Id: I56fef4a94ee5110b090add7c1449797956c93db3 --- examples/tinyds-tdm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/tinyds-tdm.c b/examples/tinyds-tdm.c index 8ffaec5..26ff72c 100644 --- a/examples/tinyds-tdm.c +++ b/examples/tinyds-tdm.c @@ -430,6 +430,8 @@ view_handle_surface_commit(struct wl_listener *listener, static void server_new_xdg_surface(struct wl_listener *listener, void *data) { + static unsigned int seedx = 1; + static unsigned int seedy = 43210; struct tinyds_server *server; struct tinyds_view *view; struct ds_xdg_surface *xdg_surface; @@ -462,8 +464,8 @@ server_new_xdg_surface(struct wl_listener *listener, void *data) ds_xdg_surface_get_surface(xdg_surface), &view->surface_commit); - view->x = rand() % 1000; - view->y = rand() % 500; + view->x = rand_r(&seedx) % 1000; + view->y = rand_r(&seedy) % 500; view->hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc); assert(view->hwc_window); -- 2.7.4 From 3311099f1ec13a331437383ccb7d5bedfdf8b8c6 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Sun, 4 Sep 2022 10:51:48 +0900 Subject: [PATCH 07/16] text-entry: use memcpy instead of strcpy For better security, do not use vulnerable function 'strcpy' Change-Id: Ib0ac0a253b19df4ce14d0faac233591ecd1d16c4 --- clients/text-entry.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/clients/text-entry.c b/clients/text-entry.c index ce21d02..0561e56 100644 --- a/clients/text-entry.c +++ b/clients/text-entry.c @@ -615,16 +615,22 @@ text_entry_insert_at_cursor(struct text_entry *entry, const char *text, int32_t cursor, int32_t anchor) { fprintf(stderr, "text_entry_insert_at_cursor()\n"); - char *new_text = malloc(strlen(entry->text) + strlen(text) + 1); + char *new_text; + int len_entry_text, len_text; + + len_entry_text = strlen(entry->text); + len_text = strlen(text); + new_text = malloc(len_entry_text + len_text + 1); if (new_text == NULL) { fprintf(stderr, "alloc fail"); return; } - strncpy(new_text, entry->text, entry->cursor); - strcpy(new_text + entry->cursor, text); - strcpy(new_text + entry->cursor + strlen(text), - entry->text + entry->cursor); + memcpy(new_text, entry->text, entry->cursor); + memcpy(new_text + entry->cursor, text, len_text); + memcpy(new_text + entry->cursor + len_text, + entry->text + entry->cursor, len_entry_text - entry->cursor); + new_text[len_entry_text + len_text] = '\0'; free(entry->text); entry->text = new_text; -- 2.7.4 From bcd2f95e229f6aa76765cdd9f914dd71a5936c24 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Mon, 5 Sep 2022 13:19:11 +0900 Subject: [PATCH 08/16] ime: free allocated variables before return statement To fix resource leak. Change-Id: Icf1bdfdecebf14903c89c4f21fa92bbebc19513c --- src/input_method/input_method.c | 5 ++++- src/text_input/text_input.c | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/input_method/input_method.c b/src/input_method/input_method.c index 8eed2f2..138193f 100644 --- a/src/input_method/input_method.c +++ b/src/input_method/input_method.c @@ -221,8 +221,10 @@ ds_tizen_input_method_create_context(struct ds_tizen_input_method *input_method) ds_inf("ds_tizen_input_method_create_context"); context = calloc(1, sizeof *context); - if (context == NULL) + if (context == NULL) { + ds_err("calloc() failed. ds_tizen_input_method_context"); return NULL; + } binding = input_method->resource; if (!binding) return NULL; @@ -230,6 +232,7 @@ ds_tizen_input_method_create_context(struct ds_tizen_input_method *input_method) &zwp_input_method_context_v1_interface, INPUT_METHOD_VERSION, 0); if (context->resource == NULL) { ds_err("context. wl_resource_create() failed."); + free(context); return NULL; } wl_resource_set_implementation(context->resource, &context_impl, diff --git a/src/text_input/text_input.c b/src/text_input/text_input.c index 05adda7..d25b1a4 100644 --- a/src/text_input/text_input.c +++ b/src/text_input/text_input.c @@ -448,6 +448,7 @@ text_input_manager_handle_create_text_input(struct wl_client *wl_client, if (text_input->resource == NULL) { ds_err("text_input. wl_resource_create() failed."); wl_client_post_no_memory(wl_client); + free(text_input); return; } wl_resource_set_implementation(text_input->resource, &text_input_impl, -- 2.7.4 From 92fd0ced30e330e6a237312d31f33c0a5310dd6e Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Tue, 6 Sep 2022 16:07:03 +0900 Subject: [PATCH 09/16] clients: merge ime-keyboard code to input-generator Change-Id: I0e39cef61183833eaf7c06917a42285a2faa24f6 --- clients/ime-keyboard.c | 957 --------------------------------------------- clients/input-generator.c | 740 ++++++++++++++++++++++++++++++++++- clients/meson.build | 14 +- packaging/libds-tizen.spec | 1 - 4 files changed, 739 insertions(+), 973 deletions(-) delete mode 100644 clients/ime-keyboard.c diff --git a/clients/ime-keyboard.c b/clients/ime-keyboard.c deleted file mode 100644 index 4d6346d..0000000 --- a/clients/ime-keyboard.c +++ /dev/null @@ -1,957 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#define MAX_STR 1024 -#define SIZE_EPOLL 16 - -enum keyboard_state { - KEYBOARD_STATE_DEFAULT, - KEYBOARD_STATE_UPPERCASE, - KEYBOARD_STATE_SYMBOLS -}; - -struct display -{ - struct wl_display *display; - struct wl_registry *registry; - struct wl_compositor *compositor; - struct wl_event_queue *queue; - - int run; - int fd_epoll; - int fd_display; - - int enable_log; - - struct zwp_input_method_manager_v1 *input_method_mgr; - struct zwp_input_method_v1 *input_method; - struct zwp_input_method_context_v1 *context; - - char *preedit_string; - uint32_t preedit_style; - struct { - xkb_mod_mask_t shift_mask; - } keysym; - uint32_t serial; - uint32_t content_hint; - int32_t content_purpose; - char *preferred_language; - char *surrounding_text; - uint32_t surrounding_cursor; - enum keyboard_state state; //struct keyboard *keyboard; - - //struct zwp_input_panel_surface_v1 *ips; -}; - -struct layout { - const struct key *keys; - uint32_t count; - - uint32_t columns; - uint32_t rows; - - const char *language; - uint32_t text_direction; -}; - -enum key_type { - keytype_default, - keytype_backspace, - keytype_enter, - keytype_space, - keytype_switch, - keytype_symbols, - keytype_tab, - keytype_arrow_up, - keytype_arrow_left, - keytype_arrow_right, - keytype_arrow_down, - keytype_style -}; - -struct key { - enum key_type key_type; - - char *label; - char *uppercase; - char *symbol; - - unsigned int width; -}; - -static const struct key normal_keys[] = { - { keytype_default, "q", "Q", "1", 1}, - { keytype_default, "w", "W", "2", 1}, - { keytype_default, "e", "E", "3", 1}, - { keytype_default, "r", "R", "4", 1}, - { keytype_default, "t", "T", "5", 1}, - { keytype_default, "y", "Y", "6", 1}, - { keytype_default, "u", "U", "7", 1}, - { keytype_default, "i", "I", "8", 1}, - { keytype_default, "o", "O", "9", 1}, - { keytype_default, "p", "P", "0", 1}, - { keytype_backspace, "<--", "<--", "<--", 2}, - - { keytype_tab, "->|", "->|", "->|", 1}, - { keytype_default, "a", "A", "-", 1}, - { keytype_default, "s", "S", "@", 1}, - { keytype_default, "d", "D", "*", 1}, - { keytype_default, "f", "F", "^", 1}, - { keytype_default, "g", "G", ":", 1}, - { keytype_default, "h", "H", ";", 1}, - { keytype_default, "j", "J", "(", 1}, - { keytype_default, "k", "K", ")", 1}, - { keytype_default, "l", "L", "~", 1}, - { keytype_enter, "Enter", "Enter", "Enter", 2}, - - { keytype_switch, "ABC", "abc", "ABC", 2}, - { keytype_default, "z", "Z", "/", 1}, - { keytype_default, "x", "X", "\'", 1}, - { keytype_default, "c", "C", "\"", 1}, - { keytype_default, "v", "V", "+", 1}, - { keytype_default, "b", "B", "=", 1}, - { keytype_default, "n", "N", "?", 1}, - { keytype_default, "m", "M", "!", 1}, - { keytype_default, ",", ",", "\\", 1}, - { keytype_default, ".", ".", "|", 1}, - { keytype_switch, "ABC", "abc", "ABC", 1}, - - { keytype_symbols, "?123", "?123", "abc", 1}, - { keytype_space, "", "", "", 5}, - { keytype_arrow_up, "/\\", "/\\", "/\\", 1}, - { keytype_arrow_left, "<", "<", "<", 1}, - { keytype_arrow_right, ">", ">", ">", 1}, - { keytype_arrow_down, "\\/", "\\/", "\\/", 1}, - { keytype_style, "", "", "", 2} -}; - -static const struct key numeric_keys[] = { - { keytype_default, "1", "1", "1", 1}, - { keytype_default, "2", "2", "2", 1}, - { keytype_default, "3", "3", "3", 1}, - { keytype_default, "4", "4", "4", 1}, - { keytype_default, "5", "5", "5", 1}, - { keytype_default, "6", "6", "6", 1}, - { keytype_default, "7", "7", "7", 1}, - { keytype_default, "8", "8", "8", 1}, - { keytype_default, "9", "9", "9", 1}, - { keytype_default, "0", "0", "0", 1}, - { keytype_backspace, "<--", "<--", "<--", 2}, - - { keytype_space, "", "", "", 4}, - { keytype_enter, "Enter", "Enter", "Enter", 2}, - { keytype_arrow_up, "/\\", "/\\", "/\\", 1}, - { keytype_arrow_left, "<", "<", "<", 1}, - { keytype_arrow_right, ">", ">", ">", 1}, - { keytype_arrow_down, "\\/", "\\/", "\\/", 1}, - { keytype_style, "", "", "", 2} -}; - -static const struct layout normal_layout = { - normal_keys, - sizeof(normal_keys) / sizeof(*normal_keys), - 12, - 4, - "en", - WL_TEXT_INPUT_TEXT_DIRECTION_LTR -}; - -static const struct layout numeric_layout = { - numeric_keys, - sizeof(numeric_keys) / sizeof(*numeric_keys), - 12, - 2, - "en", - WL_TEXT_INPUT_TEXT_DIRECTION_LTR -}; - -struct display data_wl; -static void -request_key(uint32_t time, const struct key *key, enum wl_pointer_button_state state); - -static void -usage(void) -{ - printf(" This is virtual keyboard. (refer to weston/clients/keyboard.c)\n"); - printf("\n"); -} - -static const struct layout * -get_current_layout(void) -{ - switch (data_wl.content_purpose) { - case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS: - case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER: - return &numeric_layout; - default: - return &normal_layout; - } -} - -static void -stdin_read(void) -{ - int c; - char buf[MAX_STR] = {0, }, *tmp, *buf_ptr; - int count = 0; - static uint32_t time = 12345; - const struct layout *layout; - uint32_t key_type = 0, key_idx = 0; - - while ((c = getchar()) != EOF) { - if (c == '\n') break; - if (count >= MAX_STR) break; - - buf[count] = c; - count++; - } - - count = 0; - tmp = strtok_r(buf, " ", &buf_ptr); - if (!tmp) return; - - if (!strncmp(buf, "q", MAX_STR) || !strncmp(buf, "quit", MAX_STR)) { - data_wl.run = 0; - } else if (!strncmp(buf, "help", MAX_STR)) { - usage(); - } else if (!strncmp(buf, "log", MAX_STR)) { - if (data_wl.enable_log) - printf("Disable detailed logs\n"); - else - printf("Enable detailed logs\n"); - - data_wl.enable_log = !data_wl.enable_log; - } else if (!strncmp(tmp, "key", MAX_STR)) { - while (tmp) { - tmp = strtok_r(NULL, " ", &buf_ptr); - if (tmp) { - switch (count) { - case 0: - key_idx = atoi(tmp); - break; - case 1: - key_type = atoi(tmp); - break; - default: - break; - } - } - count++; - } - if (data_wl.enable_log) - printf("request key() key_idx:%u, key_type:%u\n", key_idx, key_type); - - layout = get_current_layout(); - request_key(time++, &layout->keys[key_idx], key_type); - - } else { - printf("Invalid arguments\n"); - usage(); - } -} - -static const char * -prev_utf8_char(const char *s, const char *p) -{ - for (--p; p >= s; --p) { - if ((*p & 0xc0) != 0x80) - return p; - } - return NULL; -} - -static void -delete_before_cursor(void) -{ - const char *start, *end; - - if (!data_wl.surrounding_text) { - printf("delete_before_cursor: No surrounding text available\n"); - return; - } - - start = prev_utf8_char(data_wl.surrounding_text, - data_wl.surrounding_text + data_wl.surrounding_cursor); - if (!start) { - printf("delete_before_cursor: No previous character to delete\n"); - return; - } - - end = data_wl.surrounding_text + data_wl.surrounding_cursor; - - zwp_input_method_context_v1_delete_surrounding_text(data_wl.context, - (start - data_wl.surrounding_text) - data_wl.surrounding_cursor, - end - start); - zwp_input_method_context_v1_commit_string(data_wl.context, - data_wl.serial, - ""); - - /* Update surrounding text */ - data_wl.surrounding_cursor = start - data_wl.surrounding_text; - data_wl.surrounding_text[data_wl.surrounding_cursor] = '\0'; - if (*end) - memmove(data_wl.surrounding_text + data_wl.surrounding_cursor, end, strlen(end)); -} - -static char * -append(char *s1, const char *s2) -{ - int len1, len2; - char *s = NULL; - - len1 = strlen(s1); - len2 = strlen(s2); - s = realloc(s1, len1 + len2 + 1); - if (s == NULL) { - printf("alloc fail"); - return NULL; - } - memcpy(s + len1, s2, len2); - s[len1 + len2] = '\0'; - - return s; -} - -static void -request_preedit(int32_t cursor) -{ - printf("request_preedit() preedit_string:%s\n", data_wl.preedit_string); - uint32_t index = strlen(data_wl.preedit_string); - - if (!data_wl.context) return; - - if (data_wl.preedit_style) - zwp_input_method_context_v1_preedit_styling(data_wl.context, - 0, - strlen(data_wl.preedit_string), - data_wl.preedit_style); - if (cursor > 0) - index = cursor; - zwp_input_method_context_v1_preedit_cursor(data_wl.context, - index); - zwp_input_method_context_v1_preedit_string(data_wl.context, - data_wl.serial, - data_wl.preedit_string, - data_wl.preedit_string); -} - -static char * -insert_text(const char *text, uint32_t offset, const char *insert) -{ - int tlen = strlen(text), ilen = strlen(insert); - char *new_text = NULL; - - new_text = malloc(tlen + ilen + 1); - if (new_text == NULL) { - printf("alloc fail"); - return NULL; - } - - memcpy(new_text, text, offset); - memcpy(new_text + offset, insert, ilen); - memcpy(new_text + offset + ilen, text + offset, tlen - offset); - new_text[tlen + ilen] = '\0'; - - return new_text; -} - -static void -request_commit_string(void) -{ - char *surrounding_text; - - printf("request_commit_string()\n"); - - if (!data_wl.preedit_string || - strlen(data_wl.preedit_string) == 0) - return; - printf("request_commit_string() preedit_string:%s\n", data_wl.preedit_string); - - if (!data_wl.context) return; - - zwp_input_method_context_v1_cursor_position(data_wl.context, - 0, 0); - zwp_input_method_context_v1_commit_string(data_wl.context, - data_wl.serial, - data_wl.preedit_string); - - if (data_wl.surrounding_text) { - surrounding_text = insert_text(data_wl.surrounding_text, - data_wl.surrounding_cursor, - data_wl.preedit_string); - free(data_wl.surrounding_text); - data_wl.surrounding_text = surrounding_text; - data_wl.surrounding_cursor += strlen(data_wl.preedit_string); - } else { - data_wl.surrounding_text = strdup(data_wl.preedit_string); - data_wl.surrounding_cursor = strlen(data_wl.preedit_string); - } - - free(data_wl.preedit_string); - data_wl.preedit_string = strdup(""); -} - -static void -request_key(uint32_t time, const struct key *key, enum wl_pointer_button_state state) -{ - const char *label = NULL; - static uint32_t serial = 9999; - - switch(data_wl.state) { - case KEYBOARD_STATE_DEFAULT : - label = key->label; - break; - case KEYBOARD_STATE_UPPERCASE : - label = key->uppercase; - break; - case KEYBOARD_STATE_SYMBOLS : - label = key->symbol; - break; - default : - label = key->label; - break; - } - - xkb_mod_mask_t mod_mask = data_wl.state == KEYBOARD_STATE_DEFAULT ? 0 : data_wl.keysym.shift_mask; - uint32_t key_state = (state == WL_POINTER_BUTTON_STATE_PRESSED) ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED; - - printf("request_key() data_wl.state:%d, key->key_type:%d, pressed:%u, label:%s\n", data_wl.state, key->key_type, key_state, label); - switch (key->key_type) { - case keytype_default: - if (state != WL_POINTER_BUTTON_STATE_PRESSED) - break; - - printf("request_key() keytype_default. append label(%s) to preedit_string(%s)\n", label, data_wl.preedit_string); - data_wl.preedit_string = - append(data_wl.preedit_string, - label); - request_preedit(-1); - break; - case keytype_backspace: - if (state != WL_POINTER_BUTTON_STATE_PRESSED) - break; - - if (strlen(data_wl.preedit_string) == 0) { - delete_before_cursor(); - } else { - data_wl.preedit_string[strlen(data_wl.preedit_string) - 1] = '\0'; - request_preedit(-1); - } - break; - case keytype_enter: - request_commit_string(); - - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, - serial++, - time, - XKB_KEY_Return, key_state, mod_mask); - break; - case keytype_space: - if (state != WL_POINTER_BUTTON_STATE_PRESSED) - break; - data_wl.preedit_string = - append(data_wl.preedit_string, " "); - request_commit_string(); - break; - case keytype_switch: - if (state != WL_POINTER_BUTTON_STATE_PRESSED) - break; - switch(data_wl.state) { - case KEYBOARD_STATE_DEFAULT: - data_wl.state = KEYBOARD_STATE_UPPERCASE; - break; - case KEYBOARD_STATE_UPPERCASE: - data_wl.state = KEYBOARD_STATE_DEFAULT; - break; - case KEYBOARD_STATE_SYMBOLS: - data_wl.state = KEYBOARD_STATE_UPPERCASE; - break; - } - break; - case keytype_symbols: - if (state != WL_POINTER_BUTTON_STATE_PRESSED) - break; - switch(data_wl.state) { - case KEYBOARD_STATE_DEFAULT: - data_wl.state = KEYBOARD_STATE_SYMBOLS; - break; - case KEYBOARD_STATE_UPPERCASE: - data_wl.state = KEYBOARD_STATE_SYMBOLS; - break; - case KEYBOARD_STATE_SYMBOLS: - data_wl.state = KEYBOARD_STATE_DEFAULT; - break; - } - break; - case keytype_tab: - request_commit_string(); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, - serial++, - time, - XKB_KEY_Tab, key_state, mod_mask); - break; - case keytype_arrow_up: - request_commit_string(); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, - serial++, - time, - XKB_KEY_Up, key_state, mod_mask); - break; - case keytype_arrow_left: - request_commit_string(); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, - serial++, - time, - XKB_KEY_Left, key_state, mod_mask); - break; - case keytype_arrow_right: - request_commit_string(); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, - serial++, - time, - XKB_KEY_Right, key_state, mod_mask); - break; - case keytype_arrow_down: - request_commit_string(); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, - serial++, - time, - XKB_KEY_Down, key_state, mod_mask); - break; - case keytype_style: - if (state != WL_POINTER_BUTTON_STATE_PRESSED) - break; - data_wl.preedit_style = (data_wl.preedit_style + 1) % 8; /* TODO */ - request_preedit(-1); - break; - } -} - -static void -im_context_cb_surrounding_text (void *data, struct zwp_input_method_context_v1 *im_ctx, const char *text, uint32_t cursor, uint32_t anchor) -{ - printf("im_context_cb_surrounding_text\n"); - free(data_wl.surrounding_text); - data_wl.surrounding_text = strdup(text); - - data_wl.surrounding_cursor = cursor; -} - -static void -im_context_cb_reset (void *data, struct zwp_input_method_context_v1 *im_ctx) -{ - printf("im_context_cb_reset\n"); - - if (strlen(data_wl.preedit_string)) { - free(data_wl.preedit_string); - data_wl.preedit_string = strdup(""); - } -} - -static void -im_context_cb_content_type (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t hint, uint32_t purpose) -{ - printf("im_context_cb_content_type\n"); - - data_wl.content_hint = hint; - data_wl.content_purpose = purpose; -} - -static void -im_context_cb_invoke_action (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t button, uint32_t index) -{ - printf("im_context_cb_invoke_action\n"); - - if (button != BTN_LEFT) - return; - - request_preedit(index); -} - -static void -im_context_cb_commit_state (void *data, struct zwp_input_method_context_v1 *context, uint32_t serial) -{ - printf("im_context_cb_commit_state\n"); - - const struct layout *layout; - - data_wl.serial = serial; - - layout = get_current_layout(); - - if (data_wl.surrounding_text) - printf("Surrounding text updated: %s\n", data_wl.surrounding_text); - - if (!context) return; - zwp_input_method_context_v1_language(context, - data_wl.serial, - layout->language); - zwp_input_method_context_v1_text_direction(context, - data_wl.serial, - layout->text_direction); -} - -static void -im_context_cb_preferred_language (void *data, struct zwp_input_method_context_v1 *context, const char *language) -{ - printf("im_context_cb_preferred_language\n"); - - if (data_wl.preferred_language) - free(data_wl.preferred_language); - - data_wl.preferred_language = NULL; - - if (language) - data_wl.preferred_language = strdup(language); -} - -static const struct zwp_input_method_context_v1_listener input_method_context_cb_listener = { - .surrounding_text = im_context_cb_surrounding_text, - .reset = im_context_cb_reset, - .content_type = im_context_cb_content_type, - .invoke_action = im_context_cb_invoke_action, - .commit_state = im_context_cb_commit_state, - .preferred_language = im_context_cb_preferred_language, - //for tizen only - .return_key_type = NULL, - .return_key_disabled = NULL, - .input_panel_data = NULL, - .bidi_direction = NULL, - .cursor_position = NULL, - .process_input_device_event = NULL, - .filter_key_event = NULL, - .capital_mode = NULL, - .prediction_hint = NULL, - .mime_type = NULL, - .finalized_content = NULL, - .prediction_hint_data = NULL, - .input_panel_enabled = NULL, -}; - -static void -keysym_modifiers_add(struct wl_array *modifiers_map, - const char *name) -{ - size_t len = strlen(name) + 1; - char *p; - - p = wl_array_add(modifiers_map, len); - - if (p == NULL) - return; - - strncpy(p, name, len); -} - -static xkb_mod_index_t -keysym_modifiers_get_index(struct wl_array *modifiers_map, - const char *name) -{ - xkb_mod_index_t index = 0; - char *p = modifiers_map->data; - - while ((const char *)p < (const char *)(modifiers_map->data + modifiers_map->size)) { - if (strcmp(p, name) == 0) - return index; - - index++; - p += strlen(p) + 1; - } - - return XKB_MOD_INVALID; -} - -xkb_mod_mask_t -keysym_modifiers_get_mask(struct wl_array *modifiers_map, - const char *name) -{ - xkb_mod_index_t index = keysym_modifiers_get_index(modifiers_map, name); - - if (index == XKB_MOD_INVALID) - return XKB_MOD_INVALID; - - return 1 << index; -} - -static void -im_cb_activate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *context) -{ - printf("im_cb_activate\n"); - - struct wl_array modifiers_map; - const struct layout *layout; - - if (data_wl.context) - zwp_input_method_context_v1_destroy(data_wl.context); - - if (data_wl.preedit_string) - free(data_wl.preedit_string); - - data_wl.preedit_style = 0; - data_wl.preedit_string = strdup(""); - data_wl.content_hint = 0; - data_wl.content_purpose = 0; - free(data_wl.preferred_language); - data_wl.preferred_language = NULL; - free(data_wl.surrounding_text); - data_wl.surrounding_text = NULL; - - data_wl.serial = 0; - - data_wl.context = context; - zwp_input_method_context_v1_add_listener(context, - &input_method_context_cb_listener, - NULL); - - wl_array_init(&modifiers_map); - keysym_modifiers_add(&modifiers_map, "Shift"); - keysym_modifiers_add(&modifiers_map, "Control"); - keysym_modifiers_add(&modifiers_map, "Mod1"); - zwp_input_method_context_v1_modifiers_map(context, &modifiers_map); - data_wl.keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift"); - wl_array_release(&modifiers_map); - - layout = get_current_layout(); - - zwp_input_method_context_v1_language(context, - data_wl.serial, - layout->language); - zwp_input_method_context_v1_text_direction(context, - data_wl.serial, - layout->text_direction); -} -static void -im_cb_deactivate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx) -{ - printf("im_cb_deactivate\n"); - - if (!data_wl.context) - return; - - zwp_input_method_context_v1_destroy(data_wl.context); - data_wl.context = NULL; -} - -static void -im_cb_destroy (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx) -{ - printf("im_cb_destroy\n"); - zwp_input_method_v1_destroy(data_wl.input_method); - data_wl.input_method = NULL; -} - -static const struct zwp_input_method_v1_listener input_method_cb_listener = { - .activate = im_cb_activate, - .deactivate = im_cb_deactivate, - //for tizen only - .destroy = im_cb_destroy, - .show_input_panel = NULL, - .hide_input_panel = NULL, - .open_connection = NULL, - .close_connection = NULL, - .set_text_input_id = NULL, -}; - -static void -registry_handle_global(void * data, struct wl_registry * registry, uint32_t id, - const char * interface, uint32_t version) -{ - if (strcmp(interface, "wl_compositor") == 0) { - data_wl.compositor = wl_registry_bind(registry, id, - &wl_compositor_interface, version); - if (!data_wl.compositor) { - printf("Failed to bind compositor.\n"); - return; - } - if (data_wl.enable_log) - printf("Success to bind compositor.\n"); - } else if (!strcmp(interface, "zwp_input_method_manager_v1")) { - data_wl.input_method_mgr = wl_registry_bind(registry, id, - &zwp_input_method_manager_v1_interface, version); - } else if (!strcmp(interface, "zwp_input_method_v1")) { - data_wl.input_method = wl_registry_bind(registry, id, - &zwp_input_method_v1_interface, version); - zwp_input_method_v1_add_listener(data_wl.input_method, - &input_method_cb_listener, - NULL); - - //TODO: delte this code. this job should be done in cb_activate - data_wl.preedit_string = strdup(""); - data_wl.content_hint = 0; - data_wl.content_purpose = 0; - free(data_wl.preferred_language); - data_wl.preferred_language = NULL; - free(data_wl.surrounding_text); - data_wl.surrounding_text = NULL; - data_wl.serial = 0; - } -} - -static void -registry_handle_global_remove(void * data, struct wl_registry * registry, uint32_t id) -{ - if (data_wl.enable_log) - printf("registry is removed. id: %d !\n", id); -} - -static const struct wl_registry_listener _registry_listener = { - registry_handle_global, - registry_handle_global_remove -}; - -static int -wayland_init(void) -{ - memset(&data_wl, 0, sizeof(struct display)); - - data_wl.display = wl_display_connect(NULL); - if (!data_wl.display) { - printf("Failed to connect wayland display\n"); - return 0; - } - - data_wl.queue = wl_display_create_queue(data_wl.display); - if (!data_wl.queue) { - printf("Failed to create queue\n"); - return 0; - } - - data_wl.registry = wl_display_get_registry(data_wl.display); - if (!data_wl.registry) { - printf("Failed to get registry\n"); - return 0; - } - - wl_proxy_set_queue((struct wl_proxy*)data_wl.registry, data_wl.queue); - wl_registry_add_listener(data_wl.registry, &_registry_listener, NULL); - - if (wl_display_dispatch_queue(data_wl.display, data_wl.queue) == -1) { - printf("Failed to dispatch display\n"); - return 0; - } - if (wl_display_roundtrip_queue(data_wl.display, data_wl.queue) == -1) { - printf("Failed to roundtrip display\n"); - return 0; - } - - return 1; -} - -static void -wayland_deinit(void) -{ - if (data_wl.enable_log) - printf("Shutdown wayland system\n"); - - if (data_wl.queue) wl_event_queue_destroy(data_wl.queue); - if (data_wl.display) { - if (data_wl.input_method) - zwp_input_method_v1_destroy(data_wl.input_method); - zwp_input_method_manager_v1_destroy(data_wl.input_method_mgr); - wl_registry_destroy(data_wl.registry); - wl_display_flush(data_wl.display); - wl_display_disconnect(data_wl.display); - } -} - -static int -epoll_init(void) -{ - struct epoll_event ep[2]; - - data_wl.fd_epoll = epoll_create(SIZE_EPOLL); - if (data_wl.fd_epoll <= 0) { - printf("Failed to epoll create: %d\n", SIZE_EPOLL); - return 0; - } - - data_wl.fd_display = wl_display_get_fd(data_wl.display); - - memset(ep, 0, sizeof(struct epoll_event)*2); - - ep[0].events = EPOLLIN | EPOLLERR | EPOLLHUP; - ep[0].data.fd = data_wl.fd_display; - epoll_ctl(data_wl.fd_epoll, EPOLL_CTL_ADD, data_wl.fd_display, &ep[0]); - ep[1].events = EPOLLIN | EPOLLERR | EPOLLHUP; - ep[1].data.fd = STDIN_FILENO; - epoll_ctl(data_wl.fd_epoll, EPOLL_CTL_ADD, 0, &ep[1]); - - return 1; -} - -static void -mainloop(void) -{ - struct epoll_event ep[SIZE_EPOLL]; - int res, count, i; - - res = epoll_init(); - if (!res) { - printf("Failed to init epoll\n"); - return; - } - - data_wl.run = 1; - while (data_wl.run) { - res = wl_display_dispatch_queue_pending(data_wl.display, data_wl.queue); - if (res < 0) { - printf("Failed to dispatch pending. result: %d\n", res); - data_wl.run = 0; - break; - } - res = wl_display_flush(data_wl.display); - if (res < 0) { - printf("Failed to flush display. result: %d\n", res); - data_wl.run = 0; - break; - } - - count = epoll_wait(data_wl.fd_epoll, ep, SIZE_EPOLL, -1); - for (i = 0; i < count; i++) { - if (ep[i].events & EPOLLIN) { - if (ep[i].data.fd == data_wl.fd_display) { - wl_display_dispatch_queue(data_wl.display, data_wl.queue); - } else { - stdin_read(); - } - } - if (ep[i].events & EPOLLERR) { - data_wl.run = 0; - } - if (ep[i].events & EPOLLHUP) { - data_wl.run = 0; - } - } - } -} - -int -main(int argc, char **argv) -{ - int res; - - res = wayland_init(); - if (!res) return 0; - - mainloop(); - - wayland_deinit(); - - return 0; -} diff --git a/clients/input-generator.c b/clients/input-generator.c index 73b7ab4..cfa1800 100644 --- a/clients/input-generator.c +++ b/clients/input-generator.c @@ -5,11 +5,22 @@ #include #include +#include +//#include + +#include +#include #include #define MAX_STR 1024 #define SIZE_EPOLL 16 +enum keyboard_state { + KEYBOARD_STATE_DEFAULT, + KEYBOARD_STATE_UPPERCASE, + KEYBOARD_STATE_SYMBOLS +}; + enum enum_key_type { KEY_UP = 0, @@ -43,11 +54,158 @@ struct display int init; int enable_log; + + struct zwp_input_method_manager_v1 *input_method_mgr; + struct zwp_input_method_v1 *input_method; + struct zwp_input_method_context_v1 *context; + + char *preedit_string; + uint32_t preedit_style; + struct { + xkb_mod_mask_t shift_mask; + } keysym; + uint32_t serial; + uint32_t content_hint; + int32_t content_purpose; + char *preferred_language; + char *surrounding_text; + uint32_t surrounding_cursor; + enum keyboard_state state; //struct keyboard *keyboard; + + //struct zwp_input_panel_surface_v1 *ips; +}; + +struct layout { + const struct key *keys; + uint32_t count; + + uint32_t columns; + uint32_t rows; + + const char *language; + uint32_t text_direction; +}; + +enum key_type { + keytype_default, + keytype_backspace, + keytype_enter, + keytype_space, + keytype_switch, + keytype_symbols, + keytype_tab, + keytype_arrow_up, + keytype_arrow_left, + keytype_arrow_right, + keytype_arrow_down, + keytype_style +}; + +struct key { + enum key_type key_type; + + char *label; + char *uppercase; + char *symbol; + + unsigned int width; +}; + +static const struct key normal_keys[] = { + { keytype_default, "q", "Q", "1", 1}, + { keytype_default, "w", "W", "2", 1}, + { keytype_default, "e", "E", "3", 1}, + { keytype_default, "r", "R", "4", 1}, + { keytype_default, "t", "T", "5", 1}, + { keytype_default, "y", "Y", "6", 1}, + { keytype_default, "u", "U", "7", 1}, + { keytype_default, "i", "I", "8", 1}, + { keytype_default, "o", "O", "9", 1}, + { keytype_default, "p", "P", "0", 1}, + { keytype_backspace, "<--", "<--", "<--", 2}, + + { keytype_tab, "->|", "->|", "->|", 1}, + { keytype_default, "a", "A", "-", 1}, + { keytype_default, "s", "S", "@", 1}, + { keytype_default, "d", "D", "*", 1}, + { keytype_default, "f", "F", "^", 1}, + { keytype_default, "g", "G", ":", 1}, + { keytype_default, "h", "H", ";", 1}, + { keytype_default, "j", "J", "(", 1}, + { keytype_default, "k", "K", ")", 1}, + { keytype_default, "l", "L", "~", 1}, + { keytype_enter, "Enter", "Enter", "Enter", 2}, + + { keytype_switch, "ABC", "abc", "ABC", 2}, + { keytype_default, "z", "Z", "/", 1}, + { keytype_default, "x", "X", "\'", 1}, + { keytype_default, "c", "C", "\"", 1}, + { keytype_default, "v", "V", "+", 1}, + { keytype_default, "b", "B", "=", 1}, + { keytype_default, "n", "N", "?", 1}, + { keytype_default, "m", "M", "!", 1}, + { keytype_default, ",", ",", "\\", 1}, + { keytype_default, ".", ".", "|", 1}, + { keytype_switch, "ABC", "abc", "ABC", 1}, + + { keytype_symbols, "?123", "?123", "abc", 1}, + { keytype_space, "", "", "", 5}, + { keytype_arrow_up, "/\\", "/\\", "/\\", 1}, + { keytype_arrow_left, "<", "<", "<", 1}, + { keytype_arrow_right, ">", ">", ">", 1}, + { keytype_arrow_down, "\\/", "\\/", "\\/", 1}, + { keytype_style, "", "", "", 2} +}; + +static const struct key numeric_keys[] = { + { keytype_default, "1", "1", "1", 1}, + { keytype_default, "2", "2", "2", 1}, + { keytype_default, "3", "3", "3", 1}, + { keytype_default, "4", "4", "4", 1}, + { keytype_default, "5", "5", "5", 1}, + { keytype_default, "6", "6", "6", 1}, + { keytype_default, "7", "7", "7", 1}, + { keytype_default, "8", "8", "8", 1}, + { keytype_default, "9", "9", "9", 1}, + { keytype_default, "0", "0", "0", 1}, + { keytype_backspace, "<--", "<--", "<--", 2}, + + { keytype_space, "", "", "", 4}, + { keytype_enter, "Enter", "Enter", "Enter", 2}, + { keytype_arrow_up, "/\\", "/\\", "/\\", 1}, + { keytype_arrow_left, "<", "<", "<", 1}, + { keytype_arrow_right, ">", ">", ">", 1}, + { keytype_arrow_down, "\\/", "\\/", "\\/", 1}, + { keytype_style, "", "", "", 2} +}; + +static const struct layout normal_layout = { + normal_keys, + sizeof(normal_keys) / sizeof(*normal_keys), + 12, + 4, + "en", + WL_TEXT_INPUT_TEXT_DIRECTION_LTR +}; + +static const struct layout numeric_layout = { + numeric_keys, + sizeof(numeric_keys) / sizeof(*numeric_keys), + 12, + 2, + "en", + WL_TEXT_INPUT_TEXT_DIRECTION_LTR }; struct display data_wl; static void +request_key(uint32_t time, const struct key *key, enum wl_keyboard_key_state state); + +static const struct layout * +get_current_layout(void); + +static void usage(void) { printf(" Supported commands: init (Initialize input generator)\n"); @@ -104,6 +262,13 @@ usage(void) printf(" : mouse 1 1 10 10\n"); printf(" : mouse 1 1 -10 -10\n"); printf(" : mouse 1 2 0 0\n"); + printf("ime {key_idx} {type}\n"); + printf(" : key_index\n"); + printf(" : - keys = [q,w,e,r,t,,,]\n"); + printf(" : type:\n"); + printf(" : - default: down & up\n"); + printf(" : - down: 1\n"); + printf(" : - up: 0\n"); printf("\n"); } @@ -305,6 +470,8 @@ stdin_read(void) char buf[MAX_STR] = {0, }, *tmp, *buf_ptr, key_name[MAX_STR] = {0, }; int count = 0; int key_type = KEY_ALL, idx = 0, type = POINTER_ALL, x = 0, y = 0; + static uint32_t time = 12345; + const struct layout *layout; while ((c = getchar()) != EOF) { if (c == '\n') break; @@ -405,6 +572,33 @@ stdin_read(void) count++; } mouse_generate(idx, type, x, y); + } else if (!strncmp(tmp, "ime", MAX_STR)) { + while (tmp) { + tmp = strtok_r(NULL, " ", &buf_ptr); + if (tmp) { + switch (count) { + case 0: + idx = atoi(tmp); + break; + case 1: + key_type = atoi(tmp); + break; + default: + break; + } + } + count++; + } + if (data_wl.enable_log) + printf("request key() key_idx:%u, key_type:%u\n", idx, key_type); + + layout = get_current_layout(); + if (key_type == KEY_ALL) { + request_key(time++, &layout->keys[idx], WL_KEYBOARD_KEY_STATE_PRESSED); + request_key(time++, &layout->keys[idx], WL_KEYBOARD_KEY_STATE_RELEASED); + } + else + request_key(time++, &layout->keys[idx], key_type); } else if (!strncmp(buf, "q", MAX_STR) || !strncmp(buf, "quit", MAX_STR)) { data_wl.run = 0; } else if (!strncmp(buf, "help", MAX_STR)) { @@ -440,6 +634,526 @@ static const struct tizen_input_device_manager_listener _input_device_manager_li .block_expired = NULL, }; +static const struct layout * +get_current_layout(void) +{ + switch (data_wl.content_purpose) { + case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS: + case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER: + return &numeric_layout; + default: + return &normal_layout; + } +} + +static const char * +prev_utf8_char(const char *s, const char *p) +{ + for (--p; p >= s; --p) { + if ((*p & 0xc0) != 0x80) + return p; + } + return NULL; +} + +static void +delete_before_cursor(void) +{ + const char *start, *end; + + if (!data_wl.surrounding_text) { + printf("delete_before_cursor: No surrounding text available\n"); + return; + } + + start = prev_utf8_char(data_wl.surrounding_text, + data_wl.surrounding_text + data_wl.surrounding_cursor); + if (!start) { + printf("delete_before_cursor: No previous character to delete\n"); + return; + } + + end = data_wl.surrounding_text + data_wl.surrounding_cursor; + + zwp_input_method_context_v1_delete_surrounding_text(data_wl.context, + (start - data_wl.surrounding_text) - data_wl.surrounding_cursor, + end - start); + zwp_input_method_context_v1_commit_string(data_wl.context, + data_wl.serial, + ""); + + /* Update surrounding text */ + data_wl.surrounding_cursor = start - data_wl.surrounding_text; + data_wl.surrounding_text[data_wl.surrounding_cursor] = '\0'; + if (*end) + memmove(data_wl.surrounding_text + data_wl.surrounding_cursor, end, strlen(end)); +} + +static char * +append(char *s1, const char *s2) +{ + int len1, len2; + char *s = NULL; + + len1 = strlen(s1); + len2 = strlen(s2); + s = realloc(s1, len1 + len2 + 1); + if (s == NULL) { + printf("alloc fail"); + return NULL; + } + memcpy(s + len1, s2, len2); + s[len1 + len2] = '\0'; + + return s; +} + +static void +request_preedit(int32_t cursor) +{ + printf("request_preedit() preedit_string:%s\n", data_wl.preedit_string); + uint32_t index = strlen(data_wl.preedit_string); + + if (!data_wl.context) return; + + if (data_wl.preedit_style) + zwp_input_method_context_v1_preedit_styling(data_wl.context, + 0, + strlen(data_wl.preedit_string), + data_wl.preedit_style); + if (cursor > 0) + index = cursor; + zwp_input_method_context_v1_preedit_cursor(data_wl.context, + index); + zwp_input_method_context_v1_preedit_string(data_wl.context, + data_wl.serial, + data_wl.preedit_string, + data_wl.preedit_string); +} + +static char * +insert_text(const char *text, uint32_t offset, const char *insert) +{ + int tlen = strlen(text), ilen = strlen(insert); + char *new_text = NULL; + + new_text = malloc(tlen + ilen + 1); + if (new_text == NULL) { + printf("alloc fail"); + return NULL; + } + + memcpy(new_text, text, offset); + memcpy(new_text + offset, insert, ilen); + memcpy(new_text + offset + ilen, text + offset, tlen - offset); + new_text[tlen + ilen] = '\0'; + + return new_text; +} + +static void +request_commit_string(void) +{ + char *surrounding_text; + + printf("request_commit_string()\n"); + + if (!data_wl.preedit_string || + strlen(data_wl.preedit_string) == 0) + return; + printf("request_commit_string() preedit_string:%s\n", data_wl.preedit_string); + + if (!data_wl.context) return; + + zwp_input_method_context_v1_cursor_position(data_wl.context, + 0, 0); + zwp_input_method_context_v1_commit_string(data_wl.context, + data_wl.serial, + data_wl.preedit_string); + + if (data_wl.surrounding_text) { + surrounding_text = insert_text(data_wl.surrounding_text, + data_wl.surrounding_cursor, + data_wl.preedit_string); + free(data_wl.surrounding_text); + data_wl.surrounding_text = surrounding_text; + data_wl.surrounding_cursor += strlen(data_wl.preedit_string); + } else { + data_wl.surrounding_text = strdup(data_wl.preedit_string); + data_wl.surrounding_cursor = strlen(data_wl.preedit_string); + } + + free(data_wl.preedit_string); + data_wl.preedit_string = strdup(""); +} + +static void +request_key(uint32_t time, const struct key *key, enum wl_keyboard_key_state state) +{ + const char *label = NULL; + static uint32_t serial = 9999; + + switch(data_wl.state) { + case KEYBOARD_STATE_DEFAULT : + label = key->label; + break; + case KEYBOARD_STATE_UPPERCASE : + label = key->uppercase; + break; + case KEYBOARD_STATE_SYMBOLS : + label = key->symbol; + break; + default : + label = key->label; + break; + } + + xkb_mod_mask_t mod_mask = data_wl.state == KEYBOARD_STATE_DEFAULT ? 0 : data_wl.keysym.shift_mask; + uint32_t key_state = (state == WL_KEYBOARD_KEY_STATE_PRESSED) ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED; + + printf("request_key() data_wl.state:%d, key->key_type:%d, pressed:%u, label:%s\n", data_wl.state, key->key_type, key_state, label); + switch (key->key_type) { + case keytype_default: + if (state != WL_KEYBOARD_KEY_STATE_PRESSED) + break; + + printf("request_key() keytype_default. append label(%s) to preedit_string(%s)\n", label, data_wl.preedit_string); + data_wl.preedit_string = + append(data_wl.preedit_string, + label); + request_preedit(-1); + break; + case keytype_backspace: + if (state != WL_KEYBOARD_KEY_STATE_PRESSED) + break; + + if (strlen(data_wl.preedit_string) == 0) { + delete_before_cursor(); + } else { + data_wl.preedit_string[strlen(data_wl.preedit_string) - 1] = '\0'; + request_preedit(-1); + } + break; + case keytype_enter: + request_commit_string(); + + if (!data_wl.context) break; + zwp_input_method_context_v1_keysym(data_wl.context, + serial++, + time, + XKB_KEY_Return, key_state, mod_mask); + break; + case keytype_space: + if (state != WL_KEYBOARD_KEY_STATE_PRESSED) + break; + data_wl.preedit_string = + append(data_wl.preedit_string, " "); + request_commit_string(); + break; + case keytype_switch: + if (state != WL_KEYBOARD_KEY_STATE_PRESSED) + break; + switch(data_wl.state) { + case KEYBOARD_STATE_DEFAULT: + data_wl.state = KEYBOARD_STATE_UPPERCASE; + break; + case KEYBOARD_STATE_UPPERCASE: + data_wl.state = KEYBOARD_STATE_DEFAULT; + break; + case KEYBOARD_STATE_SYMBOLS: + data_wl.state = KEYBOARD_STATE_UPPERCASE; + break; + } + break; + case keytype_symbols: + if (state != WL_KEYBOARD_KEY_STATE_PRESSED) + break; + switch(data_wl.state) { + case KEYBOARD_STATE_DEFAULT: + data_wl.state = KEYBOARD_STATE_SYMBOLS; + break; + case KEYBOARD_STATE_UPPERCASE: + data_wl.state = KEYBOARD_STATE_SYMBOLS; + break; + case KEYBOARD_STATE_SYMBOLS: + data_wl.state = KEYBOARD_STATE_DEFAULT; + break; + } + break; + case keytype_tab: + request_commit_string(); + if (!data_wl.context) break; + zwp_input_method_context_v1_keysym(data_wl.context, + serial++, + time, + XKB_KEY_Tab, key_state, mod_mask); + break; + case keytype_arrow_up: + request_commit_string(); + if (!data_wl.context) break; + zwp_input_method_context_v1_keysym(data_wl.context, + serial++, + time, + XKB_KEY_Up, key_state, mod_mask); + break; + case keytype_arrow_left: + request_commit_string(); + if (!data_wl.context) break; + zwp_input_method_context_v1_keysym(data_wl.context, + serial++, + time, + XKB_KEY_Left, key_state, mod_mask); + break; + case keytype_arrow_right: + request_commit_string(); + if (!data_wl.context) break; + zwp_input_method_context_v1_keysym(data_wl.context, + serial++, + time, + XKB_KEY_Right, key_state, mod_mask); + break; + case keytype_arrow_down: + request_commit_string(); + if (!data_wl.context) break; + zwp_input_method_context_v1_keysym(data_wl.context, + serial++, + time, + XKB_KEY_Down, key_state, mod_mask); + break; + case keytype_style: + if (state != WL_KEYBOARD_KEY_STATE_PRESSED) + break; + data_wl.preedit_style = (data_wl.preedit_style + 1) % 8; /* TODO */ + request_preedit(-1); + break; + } +} + +static void +im_context_cb_surrounding_text (void *data, struct zwp_input_method_context_v1 *im_ctx, const char *text, uint32_t cursor, uint32_t anchor) +{ + printf("im_context_cb_surrounding_text\n"); + free(data_wl.surrounding_text); + data_wl.surrounding_text = strdup(text); + + data_wl.surrounding_cursor = cursor; +} + +static void +im_context_cb_reset (void *data, struct zwp_input_method_context_v1 *im_ctx) +{ + printf("im_context_cb_reset\n"); + + if (strlen(data_wl.preedit_string)) { + free(data_wl.preedit_string); + data_wl.preedit_string = strdup(""); + } +} + +static void +im_context_cb_content_type (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t hint, uint32_t purpose) +{ + printf("im_context_cb_content_type\n"); + + data_wl.content_hint = hint; + data_wl.content_purpose = purpose; +} + +static void +im_context_cb_invoke_action (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t button, uint32_t index) +{ + printf("im_context_cb_invoke_action\n"); + + //if (button != BTN_LEFT) + // return; + + request_preedit(index); +} + +static void +im_context_cb_commit_state (void *data, struct zwp_input_method_context_v1 *context, uint32_t serial) +{ + printf("im_context_cb_commit_state\n"); + + const struct layout *layout; + + data_wl.serial = serial; + + layout = get_current_layout(); + + if (data_wl.surrounding_text) + printf("Surrounding text updated: %s\n", data_wl.surrounding_text); + + if (!context) return; + zwp_input_method_context_v1_language(context, + data_wl.serial, + layout->language); + zwp_input_method_context_v1_text_direction(context, + data_wl.serial, + layout->text_direction); +} + +static void +im_context_cb_preferred_language (void *data, struct zwp_input_method_context_v1 *context, const char *language) +{ + printf("im_context_cb_preferred_language\n"); + + if (data_wl.preferred_language) + free(data_wl.preferred_language); + + data_wl.preferred_language = NULL; + + if (language) + data_wl.preferred_language = strdup(language); +} + +static const struct zwp_input_method_context_v1_listener input_method_context_cb_listener = { + .surrounding_text = im_context_cb_surrounding_text, + .reset = im_context_cb_reset, + .content_type = im_context_cb_content_type, + .invoke_action = im_context_cb_invoke_action, + .commit_state = im_context_cb_commit_state, + .preferred_language = im_context_cb_preferred_language, + //for tizen only + .return_key_type = NULL, + .return_key_disabled = NULL, + .input_panel_data = NULL, + .bidi_direction = NULL, + .cursor_position = NULL, + .process_input_device_event = NULL, + .filter_key_event = NULL, + .capital_mode = NULL, + .prediction_hint = NULL, + .mime_type = NULL, + .finalized_content = NULL, + .prediction_hint_data = NULL, + .input_panel_enabled = NULL, +}; + +static void +keysym_modifiers_add(struct wl_array *modifiers_map, + const char *name) +{ + size_t len = strlen(name) + 1; + char *p; + + p = wl_array_add(modifiers_map, len); + + if (p == NULL) + return; + + strncpy(p, name, len); +} + +static xkb_mod_index_t +keysym_modifiers_get_index(struct wl_array *modifiers_map, + const char *name) +{ + xkb_mod_index_t index = 0; + char *p = modifiers_map->data; + + while ((const char *)p < (const char *)(modifiers_map->data + modifiers_map->size)) { + if (strcmp(p, name) == 0) + return index; + + index++; + p += strlen(p) + 1; + } + + return XKB_MOD_INVALID; +} + +static xkb_mod_mask_t +keysym_modifiers_get_mask(struct wl_array *modifiers_map, + const char *name) +{ + xkb_mod_index_t index = keysym_modifiers_get_index(modifiers_map, name); + + if (index == XKB_MOD_INVALID) + return XKB_MOD_INVALID; + + return 1 << index; +} + +static void +im_cb_activate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *context) +{ + printf("im_cb_activate\n"); + + struct wl_array modifiers_map; + const struct layout *layout; + + if (data_wl.context) + zwp_input_method_context_v1_destroy(data_wl.context); + + if (data_wl.preedit_string) + free(data_wl.preedit_string); + + data_wl.preedit_style = 0; + data_wl.preedit_string = strdup(""); + data_wl.content_hint = 0; + data_wl.content_purpose = 0; + free(data_wl.preferred_language); + data_wl.preferred_language = NULL; + free(data_wl.surrounding_text); + data_wl.surrounding_text = NULL; + + data_wl.serial = 0; + + data_wl.context = context; + zwp_input_method_context_v1_add_listener(context, + &input_method_context_cb_listener, + NULL); + + wl_array_init(&modifiers_map); + keysym_modifiers_add(&modifiers_map, "Shift"); + keysym_modifiers_add(&modifiers_map, "Control"); + keysym_modifiers_add(&modifiers_map, "Mod1"); + zwp_input_method_context_v1_modifiers_map(context, &modifiers_map); + data_wl.keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift"); + wl_array_release(&modifiers_map); + + layout = get_current_layout(); + + zwp_input_method_context_v1_language(context, + data_wl.serial, + layout->language); + zwp_input_method_context_v1_text_direction(context, + data_wl.serial, + layout->text_direction); +} +static void +im_cb_deactivate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx) +{ + printf("im_cb_deactivate\n"); + + if (!data_wl.context) + return; + + zwp_input_method_context_v1_destroy(data_wl.context); + data_wl.context = NULL; +} + +static void +im_cb_destroy (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx) +{ + printf("im_cb_destroy\n"); + zwp_input_method_v1_destroy(data_wl.input_method); + data_wl.input_method = NULL; +} + +static const struct zwp_input_method_v1_listener input_method_cb_listener = { + .activate = im_cb_activate, + .deactivate = im_cb_deactivate, + //for tizen only + .destroy = im_cb_destroy, + .show_input_panel = NULL, + .hide_input_panel = NULL, + .open_connection = NULL, + .close_connection = NULL, + .set_text_input_id = NULL, +}; + static void registry_handle_global(void * data, struct wl_registry * registry, uint32_t id, const char * interface, uint32_t version) @@ -448,11 +1162,11 @@ registry_handle_global(void * data, struct wl_registry * registry, uint32_t id, data_wl.compositor = wl_registry_bind(registry, id, &wl_compositor_interface, version); if (!data_wl.compositor) { - printf("Failed to bind compositor."); + printf("Failed to bind compositor.\n"); return; } if (data_wl.enable_log) - printf("Success to bind compositor."); + printf("Success to bind compositor.\n"); } else if (strcmp(interface, "tizen_input_device_manager") == 0) { data_wl.devicemgr = wl_registry_bind(registry, id, &tizen_input_device_manager_interface, version); @@ -464,6 +1178,25 @@ registry_handle_global(void * data, struct wl_registry * registry, uint32_t id, printf("Success to bind tizen input device manager."); tizen_input_device_manager_add_listener(data_wl.devicemgr, &_input_device_manager_listener, data_wl.display); + } else if (!strcmp(interface, "zwp_input_method_manager_v1")) { + data_wl.input_method_mgr = wl_registry_bind(registry, id, + &zwp_input_method_manager_v1_interface, version); + } else if (!strcmp(interface, "zwp_input_method_v1")) { + data_wl.input_method = wl_registry_bind(registry, id, + &zwp_input_method_v1_interface, version); + zwp_input_method_v1_add_listener(data_wl.input_method, + &input_method_cb_listener, + NULL); + + //TODO: delte this code. this job should be done in cb_activate + data_wl.preedit_string = strdup(""); + data_wl.content_hint = 0; + data_wl.content_purpose = 0; + free(data_wl.preferred_language); + data_wl.preferred_language = NULL; + free(data_wl.surrounding_text); + data_wl.surrounding_text = NULL; + data_wl.serial = 0; } } @@ -529,6 +1262,9 @@ wayland_deinit(void) if (data_wl.queue) wl_event_queue_destroy(data_wl.queue); if (data_wl.devicemgr) tizen_input_device_manager_destroy(data_wl.devicemgr); if (data_wl.display) { + if (data_wl.input_method) + zwp_input_method_v1_destroy(data_wl.input_method); + zwp_input_method_manager_v1_destroy(data_wl.input_method_mgr); wl_registry_destroy(data_wl.registry); wl_display_flush(data_wl.display); wl_display_disconnect(data_wl.display); diff --git a/clients/meson.build b/clients/meson.build index 672792a..c825bce 100644 --- a/clients/meson.build +++ b/clients/meson.build @@ -82,19 +82,7 @@ input_generator_deps = [ executable('input-generator', input_generator_files, - dependencies: input_generator_deps, - install_dir: libds_tizen_bindir, - install: true, -) - -ime_keyboard_files = ['ime-keyboard.c'] -ime_keyboard_deps = [ - dependency('wayland-client', required: true), -] - -executable('ime-keyboard', - ime_keyboard_files, - dependencies: [ime_keyboard_deps, + dependencies: [input_generator_deps, deps_libds_tizen_input_method, ], install_dir: libds_tizen_bindir, diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 53d3d2f..37f9559 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -587,7 +587,6 @@ ninja -C builddir install %{_libdir}/libds-tizen-input-method.so %{_bindir}/libds-tizen-input-method-tests %{_bindir}/libds-tizen-input-method-manager-tests -%{_bindir}/ime-keyboard %files hwc %manifest %{name}.manifest -- 2.7.4 From 084e0f7cae704d1ed467609f037f3958bf762705 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Wed, 7 Sep 2022 14:41:25 +0900 Subject: [PATCH 10/16] clients: refactor to prevent access to global variable Change-Id: Ia2283b124fb4b19473d8ca173a017c434153271a --- clients/input-generator.c | 619 ++++++++++++++++++++++++---------------------- 1 file changed, 321 insertions(+), 298 deletions(-) diff --git a/clients/input-generator.c b/clients/input-generator.c index cfa1800..c8aee23 100644 --- a/clients/input-generator.c +++ b/clients/input-generator.c @@ -200,10 +200,10 @@ static const struct layout numeric_layout = { struct display data_wl; static void -request_key(uint32_t time, const struct key *key, enum wl_keyboard_key_state state); +request_key(struct display *d, uint32_t time, const struct key *key, enum wl_keyboard_key_state state); static const struct layout * -get_current_layout(void); +get_current_layout(struct display *d); static void usage(void) @@ -273,77 +273,77 @@ usage(void) } static void -init_input_generator(enum tizen_input_device_manager_clas clas) +init_input_generator(struct display *d, enum tizen_input_device_manager_clas clas) { - if (data_wl.init) { + if (d->init) { printf("Already init input generator\n"); return; } - tizen_input_device_manager_init_generator(data_wl.devicemgr, clas); + tizen_input_device_manager_init_generator(d->devicemgr, clas); - while (data_wl.request_notified == -1) - wl_display_dispatch_queue(data_wl.display, data_wl.queue); + while (d->request_notified == -1) + wl_display_dispatch_queue(d->display, d->queue); - if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { - data_wl.init = 1; + if (d->request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + d->init = 1; printf("Success to init input generator\n"); } else { - printf("Failed to init input generator: %d\n", data_wl.request_notified); + printf("Failed to init input generator: %d\n", d->request_notified); } - data_wl.clas = clas; - data_wl.request_notified = -1; + d->clas = clas; + d->request_notified = -1; } static void -deinit_input_generator(void) +deinit_input_generator(struct display *d) { - if (!data_wl.init) { + if (!d->init) { printf("input generator is not initialized\n"); return; } - tizen_input_device_manager_deinit_generator(data_wl.devicemgr, data_wl.clas); + tizen_input_device_manager_deinit_generator(d->devicemgr, d->clas); - while (data_wl.request_notified == -1) - wl_display_dispatch_queue(data_wl.display, data_wl.queue); + while (d->request_notified == -1) + wl_display_dispatch_queue(d->display, d->queue); - if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { - data_wl.init = 0; + if (d->request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + d->init = 0; printf("Success to deinit input generator\n"); } else { - printf("Failed to deinit input generator: %d\n", data_wl.request_notified); + printf("Failed to deinit input generator: %d\n", d->request_notified); } - data_wl.request_notified = -1; + d->request_notified = -1; } static void -input_generator_key(char *name, int type) +input_generator_key(struct display *d, char *name, int type) { - tizen_input_device_manager_generate_key(data_wl.devicemgr, name, !!type); + tizen_input_device_manager_generate_key(d->devicemgr, name, !!type); - while (data_wl.request_notified == -1) - wl_display_dispatch_queue(data_wl.display, data_wl.queue); + while (d->request_notified == -1) + wl_display_dispatch_queue(d->display, d->queue); - if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { - if (data_wl.enable_log) { + if (d->request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + if (d->enable_log) { printf("Success to generate key: %s key %s\n", name, type?"down":"up"); } } else { - printf("Failed to generate %s key %s: %d\n", name, type?"down":"up", data_wl.request_notified); + printf("Failed to generate %s key %s: %d\n", name, type?"down":"up", d->request_notified); } - data_wl.request_notified = -1; + d->request_notified = -1; } static void -key_generate(char *name, int type) +key_generate(struct display *d, char *name, int type) { printf("name: %s, type: %d\n", name, type); - if (!data_wl.init) { + if (!d->init) { printf("Input generator is not initialized\n"); return; } @@ -354,10 +354,10 @@ key_generate(char *name, int type) } if (type == KEY_ALL) { - input_generator_key(name, 1); - input_generator_key(name, 0); + input_generator_key(d, name, 1); + input_generator_key(d, name, 0); } else { - input_generator_key(name, !!type); + input_generator_key(d, name, !!type); } } @@ -377,94 +377,94 @@ type_string_get(int type) } static void -input_generator_touch(int idx, int type, int x, int y) +input_generator_touch(struct display *d, int idx, int type, int x, int y) { - tizen_input_device_manager_generate_touch(data_wl.devicemgr, type, x, y, idx); + tizen_input_device_manager_generate_touch(d->devicemgr, type, x, y, idx); - while (data_wl.request_notified == -1) - wl_display_dispatch_queue(data_wl.display, data_wl.queue); + while (d->request_notified == -1) + wl_display_dispatch_queue(d->display, d->queue); - if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { - if (data_wl.enable_log) { + if (d->request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + if (d->enable_log) { 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, 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, d->request_notified); } - data_wl.request_notified = -1; + d->request_notified = -1; } static void -touch_generate(int idx, int type, int x, int y) +touch_generate(struct display *d, int idx, int type, int x, int y) { - if (!data_wl.init) { + if (!d->init) { printf("Input generator is not initialized\n"); return; } 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(d, 0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 300, 300); + input_generator_touch(d, 1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 400, 400); + input_generator_touch(d, 2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 500, 500); - 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(d, 0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 310, 310); + input_generator_touch(d, 1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 410, 410); + input_generator_touch(d, 2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 510, 510); - 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(d, 0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 320, 320); + input_generator_touch(d, 1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 420, 420); + input_generator_touch(d, 2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 520, 520); - 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); + input_generator_touch(d, 0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 320, 320); + input_generator_touch(d, 1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 420, 420); + input_generator_touch(d, 2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 520, 520); } else { - input_generator_touch(idx, type, x, y); + input_generator_touch(d, idx, type, x, y); } } static void -input_generator_mouse(int type, int x, int y, int button) +input_generator_mouse(struct display *d, int type, int x, int y, int button) { - tizen_input_device_manager_generate_pointer(data_wl.devicemgr, type, x, y, button); + tizen_input_device_manager_generate_pointer(d->devicemgr, type, x, y, button); - while (data_wl.request_notified == -1) - wl_display_dispatch_queue(data_wl.display, data_wl.queue); + while (d->request_notified == -1) + wl_display_dispatch_queue(d->display, d->queue); - if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { - if (data_wl.enable_log) { + if (d->request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) { + if (d->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); + printf("Failed to generate mouse(%s on (%d, %d)): %d\n", type_string_get(type), x, y, d->request_notified); } - data_wl.request_notified = -1; + d->request_notified = -1; } static void -mouse_generate(int btn, int type, int x, int y) +mouse_generate(struct display *d, int btn, int type, int x, int y) { - if (!data_wl.init) { + if (!d->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); + input_generator_mouse(d, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, -1, -1, 1); + input_generator_mouse(d, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1); + input_generator_mouse(d, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1); + input_generator_mouse(d, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1); + input_generator_mouse(d, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, -1, -1, 1); } else { - input_generator_mouse(type, x, y, btn); + input_generator_mouse(d, type, x, y, btn); } } static void -stdin_read(void) +stdin_read(struct display *d) { int c; char buf[MAX_STR] = {0, }, *tmp, *buf_ptr, key_name[MAX_STR] = {0, }; @@ -492,11 +492,11 @@ stdin_read(void) switch (count) { case 0: if (!strncmp("keyboard", tmp, MAX_STR-1)) - init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD); + init_input_generator(d, TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD); else if (!strncmp("touch", tmp, MAX_STR-1)) - init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN); + init_input_generator(d, TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN); else if (!strncmp("mouse", tmp, MAX_STR-1)) - init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE); + init_input_generator(d, TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE); break; default: break; @@ -505,7 +505,7 @@ stdin_read(void) count++; } } else if (!strncmp(tmp, "deinit", sizeof("deinit"))) { - deinit_input_generator(); + deinit_input_generator(d); } else if (!strncmp(tmp, "key", sizeof("key"))) { while (tmp) { tmp = strtok_r(NULL, " ", &buf_ptr); @@ -523,7 +523,7 @@ stdin_read(void) } count++; } - key_generate(key_name, key_type); + key_generate(d, key_name, key_type); } else if (!strncmp(tmp, "touch", sizeof("touch"))) { while (tmp) { tmp = strtok_r(NULL, " ", &buf_ptr); @@ -547,7 +547,7 @@ stdin_read(void) } count++; } - touch_generate(idx, type, x, y); + touch_generate(d, idx, type, x, y); } else if (!strncmp(tmp, "mouse", sizeof("mouse"))) { while (tmp) { tmp = strtok_r(NULL, " ", &buf_ptr); @@ -571,7 +571,7 @@ stdin_read(void) } count++; } - mouse_generate(idx, type, x, y); + mouse_generate(d, idx, type, x, y); } else if (!strncmp(tmp, "ime", MAX_STR)) { while (tmp) { tmp = strtok_r(NULL, " ", &buf_ptr); @@ -589,27 +589,27 @@ stdin_read(void) } count++; } - if (data_wl.enable_log) + if (d->enable_log) printf("request key() key_idx:%u, key_type:%u\n", idx, key_type); - layout = get_current_layout(); + layout = get_current_layout(d); if (key_type == KEY_ALL) { - request_key(time++, &layout->keys[idx], WL_KEYBOARD_KEY_STATE_PRESSED); - request_key(time++, &layout->keys[idx], WL_KEYBOARD_KEY_STATE_RELEASED); + request_key(d, time++, &layout->keys[idx], WL_KEYBOARD_KEY_STATE_PRESSED); + request_key(d, time++, &layout->keys[idx], WL_KEYBOARD_KEY_STATE_RELEASED); } else - request_key(time++, &layout->keys[idx], key_type); + request_key(d, time++, &layout->keys[idx], key_type); } else if (!strncmp(buf, "q", MAX_STR) || !strncmp(buf, "quit", MAX_STR)) { - data_wl.run = 0; + d->run = 0; } else if (!strncmp(buf, "help", MAX_STR)) { usage(); } else if (!strncmp(buf, "log", MAX_STR)) { - if (data_wl.enable_log) + if (d->enable_log) printf("Disable detailed logs\n"); else printf("Enable detailed logs\n"); - data_wl.enable_log = !data_wl.enable_log; + d->enable_log = !d->enable_log; } else { printf("Invalid arguments\n"); usage(); @@ -621,9 +621,11 @@ input_device_manager_handle_error(void *data, struct tizen_input_device_manager *tizen_input_device_manager, uint32_t errorcode) { - if (data_wl.enable_log) + struct display *d = (struct display *)data; + + if (d->enable_log) printf("errorcode: %d\n", errorcode); - data_wl.request_notified = errorcode; + d->request_notified = errorcode; } static const struct tizen_input_device_manager_listener _input_device_manager_listener = @@ -635,9 +637,9 @@ static const struct tizen_input_device_manager_listener _input_device_manager_li }; static const struct layout * -get_current_layout(void) +get_current_layout(struct display *d) { - switch (data_wl.content_purpose) { + switch (d->content_purpose) { case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS: case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER: return &numeric_layout; @@ -657,36 +659,36 @@ prev_utf8_char(const char *s, const char *p) } static void -delete_before_cursor(void) +delete_before_cursor(struct display *d) { const char *start, *end; - if (!data_wl.surrounding_text) { + if (!d->surrounding_text) { printf("delete_before_cursor: No surrounding text available\n"); return; } - start = prev_utf8_char(data_wl.surrounding_text, - data_wl.surrounding_text + data_wl.surrounding_cursor); + start = prev_utf8_char(d->surrounding_text, + d->surrounding_text + d->surrounding_cursor); if (!start) { printf("delete_before_cursor: No previous character to delete\n"); return; } - end = data_wl.surrounding_text + data_wl.surrounding_cursor; + end = d->surrounding_text + d->surrounding_cursor; - zwp_input_method_context_v1_delete_surrounding_text(data_wl.context, - (start - data_wl.surrounding_text) - data_wl.surrounding_cursor, + zwp_input_method_context_v1_delete_surrounding_text(d->context, + (start - d->surrounding_text) - d->surrounding_cursor, end - start); - zwp_input_method_context_v1_commit_string(data_wl.context, - data_wl.serial, + zwp_input_method_context_v1_commit_string(d->context, + d->serial, ""); /* Update surrounding text */ - data_wl.surrounding_cursor = start - data_wl.surrounding_text; - data_wl.surrounding_text[data_wl.surrounding_cursor] = '\0'; + d->surrounding_cursor = start - d->surrounding_text; + d->surrounding_text[d->surrounding_cursor] = '\0'; if (*end) - memmove(data_wl.surrounding_text + data_wl.surrounding_cursor, end, strlen(end)); + memmove(d->surrounding_text + d->surrounding_cursor, end, strlen(end)); } static char * @@ -709,26 +711,26 @@ append(char *s1, const char *s2) } static void -request_preedit(int32_t cursor) +request_preedit(struct display *d, int32_t cursor) { - printf("request_preedit() preedit_string:%s\n", data_wl.preedit_string); - uint32_t index = strlen(data_wl.preedit_string); + printf("request_preedit() preedit_string:%s\n", d->preedit_string); + uint32_t index = strlen(d->preedit_string); - if (!data_wl.context) return; + if (!d->context) return; - if (data_wl.preedit_style) - zwp_input_method_context_v1_preedit_styling(data_wl.context, + if (d->preedit_style) + zwp_input_method_context_v1_preedit_styling(d->context, 0, - strlen(data_wl.preedit_string), - data_wl.preedit_style); + strlen(d->preedit_string), + d->preedit_style); if (cursor > 0) index = cursor; - zwp_input_method_context_v1_preedit_cursor(data_wl.context, + zwp_input_method_context_v1_preedit_cursor(d->context, index); - zwp_input_method_context_v1_preedit_string(data_wl.context, - data_wl.serial, - data_wl.preedit_string, - data_wl.preedit_string); + zwp_input_method_context_v1_preedit_string(d->context, + d->serial, + d->preedit_string, + d->preedit_string); } static char * @@ -752,48 +754,48 @@ insert_text(const char *text, uint32_t offset, const char *insert) } static void -request_commit_string(void) +request_commit_string(struct display *d) { char *surrounding_text; printf("request_commit_string()\n"); - if (!data_wl.preedit_string || - strlen(data_wl.preedit_string) == 0) + if (!d->preedit_string || + strlen(d->preedit_string) == 0) return; - printf("request_commit_string() preedit_string:%s\n", data_wl.preedit_string); + printf("request_commit_string() preedit_string:%s\n", d->preedit_string); - if (!data_wl.context) return; + if (!d->context) return; - zwp_input_method_context_v1_cursor_position(data_wl.context, + zwp_input_method_context_v1_cursor_position(d->context, 0, 0); - zwp_input_method_context_v1_commit_string(data_wl.context, - data_wl.serial, - data_wl.preedit_string); - - if (data_wl.surrounding_text) { - surrounding_text = insert_text(data_wl.surrounding_text, - data_wl.surrounding_cursor, - data_wl.preedit_string); - free(data_wl.surrounding_text); - data_wl.surrounding_text = surrounding_text; - data_wl.surrounding_cursor += strlen(data_wl.preedit_string); + zwp_input_method_context_v1_commit_string(d->context, + d->serial, + d->preedit_string); + + if (d->surrounding_text) { + surrounding_text = insert_text(d->surrounding_text, + d->surrounding_cursor, + d->preedit_string); + free(d->surrounding_text); + d->surrounding_text = surrounding_text; + d->surrounding_cursor += strlen(d->preedit_string); } else { - data_wl.surrounding_text = strdup(data_wl.preedit_string); - data_wl.surrounding_cursor = strlen(data_wl.preedit_string); + d->surrounding_text = strdup(d->preedit_string); + d->surrounding_cursor = strlen(d->preedit_string); } - free(data_wl.preedit_string); - data_wl.preedit_string = strdup(""); + free(d->preedit_string); + d->preedit_string = strdup(""); } static void -request_key(uint32_t time, const struct key *key, enum wl_keyboard_key_state state) +request_key(struct display *d, uint32_t time, const struct key *key, enum wl_keyboard_key_state state) { const char *label = NULL; static uint32_t serial = 9999; - switch(data_wl.state) { + switch(d->state) { case KEYBOARD_STATE_DEFAULT : label = key->label; break; @@ -808,37 +810,37 @@ request_key(uint32_t time, const struct key *key, enum wl_keyboard_key_state sta break; } - xkb_mod_mask_t mod_mask = data_wl.state == KEYBOARD_STATE_DEFAULT ? 0 : data_wl.keysym.shift_mask; + xkb_mod_mask_t mod_mask = d->state == KEYBOARD_STATE_DEFAULT ? 0 : d->keysym.shift_mask; uint32_t key_state = (state == WL_KEYBOARD_KEY_STATE_PRESSED) ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED; - printf("request_key() data_wl.state:%d, key->key_type:%d, pressed:%u, label:%s\n", data_wl.state, key->key_type, key_state, label); + printf("request_key() d->state:%d, key->key_type:%d, pressed:%u, label:%s\n", d->state, key->key_type, key_state, label); switch (key->key_type) { case keytype_default: if (state != WL_KEYBOARD_KEY_STATE_PRESSED) break; - printf("request_key() keytype_default. append label(%s) to preedit_string(%s)\n", label, data_wl.preedit_string); - data_wl.preedit_string = - append(data_wl.preedit_string, + printf("request_key() keytype_default. append label(%s) to preedit_string(%s)\n", label, d->preedit_string); + d->preedit_string = + append(d->preedit_string, label); - request_preedit(-1); + request_preedit(d, -1); break; case keytype_backspace: if (state != WL_KEYBOARD_KEY_STATE_PRESSED) break; - if (strlen(data_wl.preedit_string) == 0) { - delete_before_cursor(); + if (strlen(d->preedit_string) == 0) { + delete_before_cursor(d); } else { - data_wl.preedit_string[strlen(data_wl.preedit_string) - 1] = '\0'; - request_preedit(-1); + d->preedit_string[strlen(d->preedit_string) - 1] = '\0'; + request_preedit(d, -1); } break; case keytype_enter: - request_commit_string(); + request_commit_string(d); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, + if (!d->context) break; + zwp_input_method_context_v1_keysym(d->context, serial++, time, XKB_KEY_Return, key_state, mod_mask); @@ -846,76 +848,76 @@ request_key(uint32_t time, const struct key *key, enum wl_keyboard_key_state sta case keytype_space: if (state != WL_KEYBOARD_KEY_STATE_PRESSED) break; - data_wl.preedit_string = - append(data_wl.preedit_string, " "); - request_commit_string(); + d->preedit_string = + append(d->preedit_string, " "); + request_commit_string(d); break; case keytype_switch: if (state != WL_KEYBOARD_KEY_STATE_PRESSED) break; - switch(data_wl.state) { + switch(d->state) { case KEYBOARD_STATE_DEFAULT: - data_wl.state = KEYBOARD_STATE_UPPERCASE; + d->state = KEYBOARD_STATE_UPPERCASE; break; case KEYBOARD_STATE_UPPERCASE: - data_wl.state = KEYBOARD_STATE_DEFAULT; + d->state = KEYBOARD_STATE_DEFAULT; break; case KEYBOARD_STATE_SYMBOLS: - data_wl.state = KEYBOARD_STATE_UPPERCASE; + d->state = KEYBOARD_STATE_UPPERCASE; break; } break; case keytype_symbols: if (state != WL_KEYBOARD_KEY_STATE_PRESSED) break; - switch(data_wl.state) { + switch(d->state) { case KEYBOARD_STATE_DEFAULT: - data_wl.state = KEYBOARD_STATE_SYMBOLS; + d->state = KEYBOARD_STATE_SYMBOLS; break; case KEYBOARD_STATE_UPPERCASE: - data_wl.state = KEYBOARD_STATE_SYMBOLS; + d->state = KEYBOARD_STATE_SYMBOLS; break; case KEYBOARD_STATE_SYMBOLS: - data_wl.state = KEYBOARD_STATE_DEFAULT; + d->state = KEYBOARD_STATE_DEFAULT; break; } break; case keytype_tab: - request_commit_string(); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, + request_commit_string(d); + if (!d->context) break; + zwp_input_method_context_v1_keysym(d->context, serial++, time, XKB_KEY_Tab, key_state, mod_mask); break; case keytype_arrow_up: - request_commit_string(); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, + request_commit_string(d); + if (!d->context) break; + zwp_input_method_context_v1_keysym(d->context, serial++, time, XKB_KEY_Up, key_state, mod_mask); break; case keytype_arrow_left: - request_commit_string(); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, + request_commit_string(d); + if (!d->context) break; + zwp_input_method_context_v1_keysym(d->context, serial++, time, XKB_KEY_Left, key_state, mod_mask); break; case keytype_arrow_right: - request_commit_string(); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, + request_commit_string(d); + if (!d->context) break; + zwp_input_method_context_v1_keysym(d->context, serial++, time, XKB_KEY_Right, key_state, mod_mask); break; case keytype_arrow_down: - request_commit_string(); - if (!data_wl.context) break; - zwp_input_method_context_v1_keysym(data_wl.context, + request_commit_string(d); + if (!d->context) break; + zwp_input_method_context_v1_keysym(d->context, serial++, time, XKB_KEY_Down, key_state, mod_mask); @@ -923,8 +925,8 @@ request_key(uint32_t time, const struct key *key, enum wl_keyboard_key_state sta case keytype_style: if (state != WL_KEYBOARD_KEY_STATE_PRESSED) break; - data_wl.preedit_style = (data_wl.preedit_style + 1) % 8; /* TODO */ - request_preedit(-1); + d->preedit_style = (d->preedit_style + 1) % 8; /* TODO */ + request_preedit(d, -1); break; } } @@ -932,79 +934,89 @@ request_key(uint32_t time, const struct key *key, enum wl_keyboard_key_state sta static void im_context_cb_surrounding_text (void *data, struct zwp_input_method_context_v1 *im_ctx, const char *text, uint32_t cursor, uint32_t anchor) { + struct display *d = (struct display *)data; + printf("im_context_cb_surrounding_text\n"); - free(data_wl.surrounding_text); - data_wl.surrounding_text = strdup(text); + free(d->surrounding_text); - data_wl.surrounding_cursor = cursor; + d->surrounding_text = strdup(text); + d->surrounding_cursor = cursor; } static void im_context_cb_reset (void *data, struct zwp_input_method_context_v1 *im_ctx) { + struct display *d = (struct display *)data; + printf("im_context_cb_reset\n"); - if (strlen(data_wl.preedit_string)) { - free(data_wl.preedit_string); - data_wl.preedit_string = strdup(""); + if (strlen(d->preedit_string)) { + free(d->preedit_string); + d->preedit_string = strdup(""); } } static void im_context_cb_content_type (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t hint, uint32_t purpose) { + struct display *d = (struct display *)data; + printf("im_context_cb_content_type\n"); - data_wl.content_hint = hint; - data_wl.content_purpose = purpose; + d->content_hint = hint; + d->content_purpose = purpose; } static void im_context_cb_invoke_action (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t button, uint32_t index) { + struct display *d = (struct display *)data; + printf("im_context_cb_invoke_action\n"); //if (button != BTN_LEFT) // return; - request_preedit(index); + request_preedit(d, index); } static void im_context_cb_commit_state (void *data, struct zwp_input_method_context_v1 *context, uint32_t serial) { - printf("im_context_cb_commit_state\n"); - + struct display *d = (struct display *)data; const struct layout *layout; - data_wl.serial = serial; + printf("im_context_cb_commit_state\n"); + d->serial = serial; - layout = get_current_layout(); + layout = get_current_layout(d); - if (data_wl.surrounding_text) - printf("Surrounding text updated: %s\n", data_wl.surrounding_text); + if (d->surrounding_text) + printf("Surrounding text updated: %s\n", d->surrounding_text); if (!context) return; zwp_input_method_context_v1_language(context, - data_wl.serial, + d->serial, layout->language); zwp_input_method_context_v1_text_direction(context, - data_wl.serial, + d->serial, layout->text_direction); } static void im_context_cb_preferred_language (void *data, struct zwp_input_method_context_v1 *context, const char *language) { + struct display *d = (struct display *)data; + printf("im_context_cb_preferred_language\n"); - if (data_wl.preferred_language) - free(data_wl.preferred_language); + if (d->preferred_language) + free(d->preferred_language); - data_wl.preferred_language = NULL; + d->preferred_language = NULL; if (language) - data_wl.preferred_language = strdup(language); + d->preferred_language = strdup(language); } static const struct zwp_input_method_context_v1_listener input_method_context_cb_listener = { @@ -1078,68 +1090,74 @@ keysym_modifiers_get_mask(struct wl_array *modifiers_map, static void im_cb_activate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *context) { + struct display *d = (struct display *)data; + printf("im_cb_activate\n"); struct wl_array modifiers_map; const struct layout *layout; - if (data_wl.context) - zwp_input_method_context_v1_destroy(data_wl.context); + if (d->context) + zwp_input_method_context_v1_destroy(d->context); - if (data_wl.preedit_string) - free(data_wl.preedit_string); + if (d->preedit_string) + free(d->preedit_string); - data_wl.preedit_style = 0; - data_wl.preedit_string = strdup(""); - data_wl.content_hint = 0; - data_wl.content_purpose = 0; - free(data_wl.preferred_language); - data_wl.preferred_language = NULL; - free(data_wl.surrounding_text); - data_wl.surrounding_text = NULL; + d->preedit_style = 0; + d->preedit_string = strdup(""); + d->content_hint = 0; + d->content_purpose = 0; + free(d->preferred_language); + d->preferred_language = NULL; + free(d->surrounding_text); + d->surrounding_text = NULL; - data_wl.serial = 0; + d->serial = 0; - data_wl.context = context; + d->context = context; zwp_input_method_context_v1_add_listener(context, &input_method_context_cb_listener, - NULL); + d); wl_array_init(&modifiers_map); keysym_modifiers_add(&modifiers_map, "Shift"); keysym_modifiers_add(&modifiers_map, "Control"); keysym_modifiers_add(&modifiers_map, "Mod1"); zwp_input_method_context_v1_modifiers_map(context, &modifiers_map); - data_wl.keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift"); + d->keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift"); wl_array_release(&modifiers_map); - layout = get_current_layout(); + layout = get_current_layout(d); zwp_input_method_context_v1_language(context, - data_wl.serial, + d->serial, layout->language); zwp_input_method_context_v1_text_direction(context, - data_wl.serial, + d->serial, layout->text_direction); } static void im_cb_deactivate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx) { + struct display *d = (struct display *)data; + printf("im_cb_deactivate\n"); - if (!data_wl.context) + if (!d->context) return; - zwp_input_method_context_v1_destroy(data_wl.context); - data_wl.context = NULL; + zwp_input_method_context_v1_destroy(d->context); + d->context = NULL; } static void im_cb_destroy (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx) { + struct display *d = (struct display *)data; + printf("im_cb_destroy\n"); - zwp_input_method_v1_destroy(data_wl.input_method); - data_wl.input_method = NULL; + zwp_input_method_v1_destroy(d->input_method); + d->input_method = NULL; } static const struct zwp_input_method_v1_listener input_method_cb_listener = { @@ -1158,52 +1176,56 @@ static void registry_handle_global(void * data, struct wl_registry * registry, uint32_t id, const char * interface, uint32_t version) { + struct display *d = (struct display *)data; + if (strcmp(interface, "wl_compositor") == 0) { - data_wl.compositor = wl_registry_bind(registry, id, + d->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, version); - if (!data_wl.compositor) { + if (!d->compositor) { printf("Failed to bind compositor.\n"); return; } - if (data_wl.enable_log) + if (d->enable_log) printf("Success to bind compositor.\n"); } else if (strcmp(interface, "tizen_input_device_manager") == 0) { - data_wl.devicemgr = wl_registry_bind(registry, id, + d->devicemgr = wl_registry_bind(registry, id, &tizen_input_device_manager_interface, version); - if (!data_wl.devicemgr) { + if (!d->devicemgr) { printf("Failed to bind input device manager"); return; } - if (data_wl.enable_log) + if (d->enable_log) printf("Success to bind tizen input device manager."); - tizen_input_device_manager_add_listener(data_wl.devicemgr, - &_input_device_manager_listener, data_wl.display); + tizen_input_device_manager_add_listener(d->devicemgr, + &_input_device_manager_listener, d); } else if (!strcmp(interface, "zwp_input_method_manager_v1")) { - data_wl.input_method_mgr = wl_registry_bind(registry, id, + d->input_method_mgr = wl_registry_bind(registry, id, &zwp_input_method_manager_v1_interface, version); } else if (!strcmp(interface, "zwp_input_method_v1")) { - data_wl.input_method = wl_registry_bind(registry, id, + d->input_method = wl_registry_bind(registry, id, &zwp_input_method_v1_interface, version); - zwp_input_method_v1_add_listener(data_wl.input_method, + zwp_input_method_v1_add_listener(d->input_method, &input_method_cb_listener, - NULL); + d); //TODO: delte this code. this job should be done in cb_activate - data_wl.preedit_string = strdup(""); - data_wl.content_hint = 0; - data_wl.content_purpose = 0; - free(data_wl.preferred_language); - data_wl.preferred_language = NULL; - free(data_wl.surrounding_text); - data_wl.surrounding_text = NULL; - data_wl.serial = 0; + d->preedit_string = strdup(""); + d->content_hint = 0; + d->content_purpose = 0; + free(d->preferred_language); + d->preferred_language = NULL; + free(d->surrounding_text); + d->surrounding_text = NULL; + d->serial = 0; } } static void registry_handle_global_remove(void * data, struct wl_registry * registry, uint32_t id) { - if (data_wl.enable_log) + struct display *d = (struct display *)data; + + if (d->enable_log) printf("registry is removed. id: %d !\n", id); } @@ -1213,37 +1235,37 @@ static const struct wl_registry_listener _registry_listener = { }; static int -wayland_init(void) +wayland_init(struct display *d) { - memset(&data_wl, 0, sizeof(struct display)); - data_wl.request_notified = -1; + memset(d, 0, sizeof(struct display)); + d->request_notified = -1; - data_wl.display = wl_display_connect(NULL); - if (!data_wl.display) { + d->display = wl_display_connect(NULL); + if (!d->display) { printf("Failed to connect wayland display\n"); return 0; } - data_wl.queue = wl_display_create_queue(data_wl.display); - if (!data_wl.queue) { + d->queue = wl_display_create_queue(d->display); + if (!d->queue) { printf("Failed to create queue\n"); return 0; } - data_wl.registry = wl_display_get_registry(data_wl.display); - if (!data_wl.registry) { + d->registry = wl_display_get_registry(d->display); + if (!d->registry) { printf("Failed to get registry\n"); return 0; } - wl_proxy_set_queue((struct wl_proxy*)data_wl.registry, data_wl.queue); - wl_registry_add_listener(data_wl.registry, &_registry_listener, NULL); + wl_proxy_set_queue((struct wl_proxy*)d->registry, d->queue); + wl_registry_add_listener(d->registry, &_registry_listener, d); - if (wl_display_dispatch_queue(data_wl.display, data_wl.queue) == -1) { + if (wl_display_dispatch_queue(d->display, d->queue) == -1) { printf("Failed to dispatch display\n"); return 0; } - if (wl_display_roundtrip_queue(data_wl.display, data_wl.queue) == -1) { + if (wl_display_roundtrip_queue(d->display, d->queue) == -1) { printf("Failed to roundtrip display\n"); return 0; } @@ -1252,91 +1274,91 @@ wayland_init(void) } static void -wayland_deinit(void) +wayland_deinit(struct display *d) { - if (data_wl.enable_log) + if (d->enable_log) printf("Shutdown wayland system\n"); - if (data_wl.init) deinit_input_generator(); - - if (data_wl.queue) wl_event_queue_destroy(data_wl.queue); - if (data_wl.devicemgr) tizen_input_device_manager_destroy(data_wl.devicemgr); - if (data_wl.display) { - if (data_wl.input_method) - zwp_input_method_v1_destroy(data_wl.input_method); - zwp_input_method_manager_v1_destroy(data_wl.input_method_mgr); - wl_registry_destroy(data_wl.registry); - wl_display_flush(data_wl.display); - wl_display_disconnect(data_wl.display); + if (d->init) deinit_input_generator(d); + + if (d->queue) wl_event_queue_destroy(d->queue); + if (d->devicemgr) tizen_input_device_manager_destroy(d->devicemgr); + if (d->display) { + if (d->input_method) + zwp_input_method_v1_destroy(d->input_method); + zwp_input_method_manager_v1_destroy(d->input_method_mgr); + wl_registry_destroy(d->registry); + wl_display_flush(d->display); + wl_display_disconnect(d->display); } } static int -epoll_init(void) +epoll_init(struct display *d) { struct epoll_event ep[2]; - data_wl.fd_epoll = epoll_create(SIZE_EPOLL); - if (data_wl.fd_epoll <= 0) { + d->fd_epoll = epoll_create(SIZE_EPOLL); + if (d->fd_epoll <= 0) { printf("Failed to epoll create: %d\n", SIZE_EPOLL); return 0; } - data_wl.fd_display = wl_display_get_fd(data_wl.display); + d->fd_display = wl_display_get_fd(d->display); memset(ep, 0, sizeof(struct epoll_event)*2); ep[0].events = EPOLLIN | EPOLLERR | EPOLLHUP; - ep[0].data.fd = data_wl.fd_display; - epoll_ctl(data_wl.fd_epoll, EPOLL_CTL_ADD, data_wl.fd_display, &ep[0]); + ep[0].data.fd = d->fd_display; + epoll_ctl(d->fd_epoll, EPOLL_CTL_ADD, d->fd_display, &ep[0]); ep[1].events = EPOLLIN | EPOLLERR | EPOLLHUP; ep[1].data.fd = STDIN_FILENO; - epoll_ctl(data_wl.fd_epoll, EPOLL_CTL_ADD, 0, &ep[1]); + epoll_ctl(d->fd_epoll, EPOLL_CTL_ADD, 0, &ep[1]); return 1; } static void -mainloop(void) +mainloop(struct display *d) { struct epoll_event ep[SIZE_EPOLL]; int res, count, i; - res = epoll_init(); + res = epoll_init(d); if (!res) { printf("Failed to init epoll\n"); return; } - data_wl.run = 1; - while (data_wl.run) { - res = wl_display_dispatch_queue_pending(data_wl.display, data_wl.queue); + d->run = 1; + while (d->run) { + res = wl_display_dispatch_queue_pending(d->display, d->queue); if (res < 0) { printf("Failed to dispatch pending. result: %d\n", res); - data_wl.run = 0; + d->run = 0; break; } - res = wl_display_flush(data_wl.display); + res = wl_display_flush(d->display); if (res < 0) { printf("Failed to flush display. result: %d\n", res); - data_wl.run = 0; + d->run = 0; break; } - count = epoll_wait(data_wl.fd_epoll, ep, SIZE_EPOLL, -1); + count = epoll_wait(d->fd_epoll, ep, SIZE_EPOLL, -1); for (i = 0; i < count; i++) { if (ep[i].events & EPOLLIN) { - if (ep[i].data.fd == data_wl.fd_display) { - wl_display_dispatch_queue(data_wl.display, data_wl.queue); + if (ep[i].data.fd == d->fd_display) { + wl_display_dispatch_queue(d->display, d->queue); } else { - stdin_read(); + stdin_read(d); } } if (ep[i].events & EPOLLERR) { - data_wl.run = 0; + d->run = 0; } if (ep[i].events & EPOLLHUP) { - data_wl.run = 0; + d->run = 0; } } } @@ -1346,13 +1368,14 @@ int main(int argc, char **argv) { int res; + struct display *d = &data_wl; - res = wayland_init(); + res = wayland_init(d); if (!res) return 0; - mainloop(); + mainloop(d); - wayland_deinit(); + wayland_deinit(d); return 0; } -- 2.7.4 From 220451ac52d2e72389bb9990e5b42c817abfc8c9 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Wed, 7 Sep 2022 14:56:00 +0900 Subject: [PATCH 11/16] tests: no need to include 'input-method-server-protocol.h' Change-Id: I0b65f6b0b4a089c13ec174076e44dcfdc8ca18dc --- tests/tc_input_method.cpp | 1 - tests/tc_input_method_manager.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/tc_input_method.cpp b/tests/tc_input_method.cpp index a9b1ecf..bb234b8 100644 --- a/tests/tc_input_method.cpp +++ b/tests/tc_input_method.cpp @@ -2,7 +2,6 @@ #include "mockclient.h" #include "mockcompositor.h" #include -#include #include #define INPUT_METHOD_VERSION 1 diff --git a/tests/tc_input_method_manager.cpp b/tests/tc_input_method_manager.cpp index a338d8f..30721dd 100644 --- a/tests/tc_input_method_manager.cpp +++ b/tests/tc_input_method_manager.cpp @@ -2,7 +2,6 @@ #include "mockclient.h" #include "mockcompositor.h" #include -#include #include #define INPUT_METHOD_VERSION 1 -- 2.7.4 From 1bd5d3b200f9c1dc7d7f02c863a0cd21bf206fac Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Wed, 7 Sep 2022 15:44:23 +0900 Subject: [PATCH 12/16] clients: merge text-entry code to simple-tbm Change-Id: I9c74e6155cb570d74cdb24c6b05e0515cc8362bf --- clients/meson.build | 22 +- clients/simple-tbm.c | 605 ++++++++++++++++++++- clients/text-entry.c | 1261 -------------------------------------------- packaging/libds-tizen.spec | 1 - 4 files changed, 596 insertions(+), 1293 deletions(-) delete mode 100644 clients/text-entry.c diff --git a/clients/meson.build b/clients/meson.build index c825bce..aa89a3c 100644 --- a/clients/meson.build +++ b/clients/meson.build @@ -14,13 +14,6 @@ simple_tbm_deps = [ tizen_extension_client, ] -text_entry_files = ['text-entry.c'] -text_entry_deps = [ - dependency('wayland-client', required: true), - wayland_tbm_client, - libtbm, -] - protocols = { 'xdg-shell': wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml', } @@ -35,7 +28,6 @@ foreach name, path : protocols command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'], ) simple_tbm_files += code - text_entry_files += code client_header = custom_target( name.underscorify() + '_client_h', @@ -45,12 +37,13 @@ foreach name, path : protocols build_by_default: false, ) simple_tbm_files += client_header - text_entry_files += client_header endforeach executable('ds-simple-tbm', simple_tbm_files, - dependencies: simple_tbm_deps, + dependencies: [simple_tbm_deps, + deps_libds_tizen_text_input, + ], install_dir: libds_tizen_bindir, install: true, ) @@ -65,15 +58,6 @@ executable('ds-simple-dpms', install: true, ) -executable('text-entry', - text_entry_files, - dependencies: [text_entry_deps, - deps_libds_tizen_text_input, - ], - install_dir: libds_tizen_bindir, - install: true, -) - input_generator_files = ['input-generator.c'] input_generator_deps = [ dependency('wayland-client', required: true), diff --git a/clients/simple-tbm.c b/clients/simple-tbm.c index f68fedb..46d48dd 100644 --- a/clients/simple-tbm.c +++ b/clients/simple-tbm.c @@ -39,9 +39,12 @@ #include #include "xdg-shell-client-protocol.h" #include +#include +#include static uint64_t buffer_info_key; #define BUFFER_INFO_KEY (unsigned long)(&buffer_info_key) +struct text_entry; struct display { struct wl_display *display; @@ -57,6 +60,9 @@ struct display { int notified; bool blocked; struct wl_surface *entered_surface; + + struct wl_text_input_manager *text_input_mgr; + struct text_entry *entry; }; struct window { @@ -75,10 +81,54 @@ struct buffer_info { struct wl_buffer *wl_buffer; }; +struct text_entry { + char *text; + int active; + bool panel_visible; + uint32_t cursor; + uint32_t anchor; + struct { + char *text; + int32_t cursor; + char *commit; + } preedit; + struct { + int32_t cursor; + } preedit_info; + struct { + int32_t cursor; + int32_t anchor; + uint32_t delete_index; + uint32_t delete_length; + bool invalid_delete; + } pending_commit; + struct wl_text_input *text_input; + struct { + xkb_mod_mask_t shift_mask; + } keysym; + uint32_t serial; + uint32_t reset_serial; + uint32_t content_purpose; + bool click_to_show; + char *preferred_language; + bool button_pressed; +}; + +struct rectangle { + int32_t x; + int32_t y; + int32_t width; + int32_t height; +}; + static int running = 1; static void redraw(void *data, struct wl_callback *callback, uint32_t time); +static void +text_entry_activate(struct display *d); +static void +text_entry_deactivate(struct display *d); static void handle_xdg_surface_configure(void *data, struct xdg_surface *surface, @@ -343,20 +393,27 @@ static void pointer_handle_button(void *data, struct wl_pointer *pointer, static int warp_x = 0, warp_y = 0; if (state == WL_POINTER_BUTTON_STATE_PRESSED) { - fprintf(stderr, "pointer_handle_button: PRESSED\n"); - - warp_x += 10; - warp_y += 10; - tizen_input_device_manager_pointer_warp(d->devicemgr, - d->entered_surface, - wl_fixed_from_int(warp_x), - wl_fixed_from_int(warp_y)); - fprintf(stderr, "requesting pointer_warp: surface:%p sx: %d sy: %d\n", - d->entered_surface, - warp_x, warp_y); + fprintf(stderr, "pointer_handle_button: button(%d) PRESSED\n", button); + if (button == 1) { //left button + text_entry_activate(d); + } + else if (button == 3) {//right button + warp_x += 10; + warp_y += 10; + tizen_input_device_manager_pointer_warp(d->devicemgr, + d->entered_surface, + wl_fixed_from_int(warp_x), + wl_fixed_from_int(warp_y)); + fprintf(stderr, "requesting pointer_warp: surface:%p sx: %d sy: %d\n", + d->entered_surface, + warp_x, warp_y); + } } else { - fprintf(stderr, "pointer_handle_button: RELEASED\n"); + fprintf(stderr, "pointer_handle_button: button(%d) RELEASED\n", button); + if (button == 1) { + text_entry_deactivate(d); + } } } @@ -571,6 +628,519 @@ static const struct tizen_input_device_manager_listener _input_device_manager_li .block_expired = input_device_manager_handle_block_expired, }; + +static void +text_entry_get_cursor_rectangle(struct text_entry *entry, struct rectangle *rectangle) +{ + if (entry->preedit.text && entry->preedit.cursor < 0) { + rectangle->x = 0; + rectangle->y = 0; + rectangle->width = 0; + rectangle->height = 0; + return; + } + + rectangle->x = 10; + rectangle->y = 20; + rectangle->width = 50; + rectangle->height = 50; +} + +static void +text_entry_update(struct text_entry *entry) +{ + struct rectangle cursor_rectangle; + + fprintf(stderr, "text_entry_update()\n"); + + wl_text_input_set_content_type(entry->text_input, + WL_TEXT_INPUT_CONTENT_HINT_NONE, + entry->content_purpose); + + if (entry->preferred_language) + wl_text_input_set_preferred_language(entry->text_input, + entry->preferred_language); + + text_entry_get_cursor_rectangle(entry, &cursor_rectangle); + wl_text_input_set_cursor_rectangle(entry->text_input, + cursor_rectangle.x, + cursor_rectangle.y, + cursor_rectangle.width, + cursor_rectangle.height); + + wl_text_input_commit_state(entry->text_input, ++entry->serial); +} + +static void +text_entry_reset_preedit(struct text_entry *entry) +{ + fprintf(stderr, "text_entry_reset_preedit()\n"); + entry->preedit.cursor = 0; + + free(entry->preedit.text); + entry->preedit.text = NULL; + + free(entry->preedit.commit); + entry->preedit.commit = NULL; +} + +static void +text_entry_insert_at_cursor(struct text_entry *entry, const char *text, + int32_t cursor, int32_t anchor) +{ + fprintf(stderr, "text_entry_insert_at_cursor()\n"); + char *new_text; + int len_entry_text, len_text; + + len_entry_text = strlen(entry->text); + len_text = strlen(text); + new_text = malloc(len_entry_text + len_text + 1); + if (new_text == NULL) { + fprintf(stderr, "alloc fail"); + return; + } + + memcpy(new_text, entry->text, entry->cursor); + memcpy(new_text + entry->cursor, text, len_text); + memcpy(new_text + entry->cursor + len_text, + entry->text + entry->cursor, len_entry_text - entry->cursor); + new_text[len_entry_text + len_text] = '\0'; + + free(entry->text); + entry->text = new_text; + if (anchor >= 0) + entry->anchor = entry->cursor + strlen(text) + anchor; + else + entry->anchor = entry->cursor + 1 + anchor; + + if (cursor >= 0) + entry->cursor += strlen(text) + cursor; + else + entry->cursor += 1 + cursor; + + text_entry_update(entry); +} + +static void +text_entry_commit_and_reset(struct text_entry *entry) +{ + char *commit = NULL; + + fprintf(stderr, "text_entry_commit_and_reset()\n"); + + if (entry->preedit.commit) + commit = strdup(entry->preedit.commit); + + text_entry_reset_preedit(entry); + if (commit) { + text_entry_insert_at_cursor(entry, commit, 0, 0); + free(commit); + } + + wl_text_input_reset(entry->text_input); + text_entry_update(entry); + entry->reset_serial = entry->serial; +} + +static void +text_input_enter(void *data, struct wl_text_input *text_input, + struct wl_surface *surface) +{ + fprintf(stderr, "text_input_enter()\n"); + + struct display *d = data; + struct text_entry *entry = d->entry; + + entry->active++; + + text_entry_update(entry); + entry->reset_serial = entry->serial; +} + +static void +text_input_leave(void *data, struct wl_text_input *text_input) +{ + fprintf(stderr, "text_input_leave()\n"); + + struct display *d = data; + struct text_entry *entry = d->entry; + + text_entry_commit_and_reset(entry); + d->entry->active--; + + if (!entry->active) { + wl_text_input_hide_input_panel(text_input); + entry->panel_visible = false; + } +} + +static void +text_input_modifiers_map(void *data, struct wl_text_input *text_input, + struct wl_array *map) +{ + fprintf(stderr, "text_input_modifiers_map()\n"); +} + +static void +text_input_input_panel_state(void *data, struct wl_text_input *text_input, + uint32_t state) +{ + fprintf(stderr, "text_input_input_panel_state() state:%u\n", state); +} + +static void +clear_pending_preedit(struct text_entry *entry) +{ + fprintf(stderr, "clear_pending_preedit()\n"); + + memset(&entry->pending_commit, 0, sizeof entry->pending_commit); + + entry->preedit_info.cursor = 0; + + memset(&entry->preedit_info, 0, sizeof entry->preedit_info); +} + +static void +text_entry_delete_text(struct text_entry *entry, + uint32_t index, uint32_t length) +{ + uint32_t l; + + fprintf(stderr, "text_entry_delete_text()\n"); + + assert(index <= strlen(entry->text)); + assert(index + length <= strlen(entry->text)); + assert(index + length >= length); + + l = strlen(entry->text + index + length); + memmove(entry->text + index, + entry->text + index + length, + l + 1); + + if (entry->cursor > (index + length)) + entry->cursor -= length; + else if (entry->cursor > index) + entry->cursor = index; + + entry->anchor = entry->cursor; + + text_entry_update(entry); +} + +static void +text_entry_delete_selected_text(struct text_entry *entry) +{ + uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor; + uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor; + + fprintf(stderr, "text_entry_delete_selected_text()\n"); + + if (entry->anchor == entry->cursor) + return; + + text_entry_delete_text(entry, start_index, end_index - start_index); + + entry->anchor = entry->cursor; +} + +static void +text_entry_set_preedit(struct text_entry *entry, + const char *preedit_text, + int preedit_cursor) +{ + fprintf(stderr, "text_entry_set_preedit()\n"); + + text_entry_reset_preedit(entry); + + if (!preedit_text) + return; + + entry->preedit.text = strdup(preedit_text); + entry->preedit.cursor = preedit_cursor; +} + +static void +text_input_preedit_string(void *data, struct wl_text_input *text_input, + uint32_t serial, const char *text, const char *commit) +{ + struct display *d = data; + struct text_entry *entry = d->entry; + + fprintf(stderr, "text_input_preedit_string() serial(%u), text(%s), commit(%s)\n", serial, text, commit); + + if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) { + fprintf(stderr, "Ignore preedit_string. Serial: %u, Current: %u, Reset: %u\n", + serial, entry->serial, entry->reset_serial); + clear_pending_preedit(entry); + return; + } + + if (entry->pending_commit.invalid_delete) { + fprintf(stderr, "Ignore preedit_string. Invalid previous delete_surrounding event.\n"); + clear_pending_preedit(entry); + return; + } + + if (entry->pending_commit.delete_length) { + text_entry_delete_text(entry, + entry->pending_commit.delete_index, + entry->pending_commit.delete_length); + } else { + text_entry_delete_selected_text(entry); + } + + text_entry_set_preedit(entry, text, entry->preedit_info.cursor); + entry->preedit.commit = strdup(commit); + + clear_pending_preedit(entry); + + text_entry_update(entry); +} + +static void +text_input_preedit_styling(void *data, struct wl_text_input *text_input, + uint32_t index, uint32_t length, uint32_t style) +{ + fprintf(stderr, "text_input_preedit_styling() index(%u), length(%u), style(%u)\n", index, length, style); + + switch (style) { + case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT: + fprintf(stderr, "text_input_preedit_styling() style:DEFAULT"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE: + fprintf(stderr, "text_input_preedit_styling() style:UNDERLINE"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT: + fprintf(stderr, "text_input_preedit_styling() style:INCORRECT"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION: + fprintf(stderr, "text_input_preedit_styling() style:SELECTION"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT: + fprintf(stderr, "text_input_preedit_styling() style:HIGHLIGHT"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE: + fprintf(stderr, "text_input_preedit_styling() style:ACTIVE"); + break; + case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE: + fprintf(stderr, "text_input_preedit_styling() style:INACTIVE"); + break; + default: + fprintf(stderr, "text_input_preedit_styling() no style enum found"); + break; + } +} + +static void +text_input_preedit_cursor(void *data, struct wl_text_input *text_input, + int32_t index) +{ + struct display *d = data; + struct text_entry *entry = d->entry; + + fprintf(stderr, "text_input_preedit_cursor() index(%u)\n", index); + + entry->preedit_info.cursor = index; +} + +static void +text_input_commit_string(void *data, struct wl_text_input *text_input, + uint32_t serial, const char *text) +{ + struct display *d = data; + struct text_entry *entry = d->entry; + + fprintf(stderr, "text_input_commit_string() serial(%u), text(%s)\n", serial, text); + + if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) { + fprintf(stderr, "Ignore commit. Serial: %u, Current: %u, Reset: %u\n", + serial, entry->serial, entry->reset_serial); + return; + } + + if (entry->pending_commit.invalid_delete) { + fprintf(stderr, "Ignore commit. Invalid previous delete_surrounding event.\n"); + memset(&entry->pending_commit, 0, sizeof entry->pending_commit); + return; + } + + text_entry_reset_preedit(entry); + + if (entry->pending_commit.delete_length) { + text_entry_delete_text(entry, + entry->pending_commit.delete_index, + entry->pending_commit.delete_length); + } else { + text_entry_delete_selected_text(entry); + } + + text_entry_insert_at_cursor(entry, text, + entry->pending_commit.cursor, + entry->pending_commit.anchor); + + memset(&entry->pending_commit, 0, sizeof entry->pending_commit); +} + +static void +text_input_cursor_position(void *data, struct wl_text_input *text_input, + int32_t index, int32_t anchor) +{ + fprintf(stderr, "text_input_cursor_position() index(%d), anchor(%d)\n", index, anchor); +} + +static void +text_input_delete_surrounding_text(void *data, + struct wl_text_input *text_input, int32_t index, uint32_t length) +{ + struct text_entry *entry = data; + uint32_t text_length; + + fprintf(stderr, "text_input_delete_surrounding_text() index(%d), length(%u)\n", index, length); + + entry->pending_commit.delete_index = entry->cursor + index; + entry->pending_commit.delete_length = length; + entry->pending_commit.invalid_delete = false; + + text_length = strlen(entry->text); + + if (entry->pending_commit.delete_index > text_length || + length > text_length || + entry->pending_commit.delete_index + length > text_length) { + fprintf(stderr, "delete_surrounding_text: Invalid index: %d," \ + "length %u'; cursor: %u text length: %u\n", index, length, entry->cursor, text_length); + entry->pending_commit.invalid_delete = true; + return; + } +} + +static void +text_input_keysym(void *data, struct wl_text_input *text_input, + uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, + uint32_t modifiers) +{ + fprintf(stderr, "text_input_keysym() serial(%u), time(%u), sym(%u), state(%u), modifiers(%u)\n", + serial, time, sym, state, modifiers); +} + +static void +text_input_language(void *data, struct wl_text_input *text_input, + uint32_t serial, const char *language) +{ + fprintf(stderr, "text_input_language() serial(%u), language(%s)\n", serial, language); +} + +static void +text_input_text_direction(void *data, struct wl_text_input *text_input, + uint32_t serial, uint32_t direction) +{ + fprintf(stderr, "text_input_text_direction() serial(%d), direction(%d)\n", serial, direction); +} + +static const struct wl_text_input_listener text_input_listener = { + .enter = text_input_enter, + .leave = text_input_leave, + .modifiers_map = text_input_modifiers_map, + .input_panel_state = text_input_input_panel_state, + .preedit_string = text_input_preedit_string, + .preedit_styling = text_input_preedit_styling, + .preedit_cursor = text_input_preedit_cursor, + .commit_string = text_input_commit_string, + .cursor_position = text_input_cursor_position, + .delete_surrounding_text = text_input_delete_surrounding_text, + .keysym = text_input_keysym, + .language = text_input_language, + .text_direction = text_input_text_direction, + // TIZEN_ONLY + .selection_region = NULL, + .private_command = NULL, + .input_panel_geometry = NULL, + .input_panel_data = NULL, + .get_selection_text = NULL, + .get_surrounding_text = NULL, + .filter_key_event_done = NULL, + .hide_permission = NULL, + .recapture_string = NULL, + .input_panel_event = NULL, + .commit_content = NULL, + // +}; + +static void +text_entry_activate(struct display *d) +{ + struct wl_surface *surface = d->entered_surface; + struct text_entry *entry = d->entry; + + fprintf(stderr, "text_entry_activate\n"); + if (entry->click_to_show && entry->active) { + entry->panel_visible = !entry->panel_visible; + + if (entry->panel_visible) + wl_text_input_show_input_panel(entry->text_input); + else + wl_text_input_hide_input_panel(entry->text_input); + + return; + } + + if (!entry->click_to_show) + wl_text_input_show_input_panel(entry->text_input); + + wl_text_input_activate(entry->text_input, + d->seat, + surface); +} + +static void +text_entry_deactivate(struct display *d) +{ + struct text_entry *entry = d->entry; + + fprintf(stderr, "text_entry_deactivate\n"); + wl_text_input_deactivate(entry->text_input, + d->seat); +} + +static void +text_entry_destroy(struct display *d) +{ + struct text_entry *entry; + + entry = d->entry; + d->entry = NULL; + + wl_text_input_destroy(entry->text_input); + free(entry->text); + free(entry->preferred_language); + free(entry); +} + +static struct text_entry* +text_entry_create(struct display *d, const char *text) +{ + struct text_entry *entry; + + entry = calloc(1, sizeof *entry); + if (!entry) + return NULL; + + entry->text = strdup(text); + entry->active = 0; + entry->panel_visible = false; + entry->cursor = strlen(text); + entry->anchor = entry->cursor; + entry->click_to_show = true; + entry->text_input = + wl_text_input_manager_create_text_input(d->text_input_mgr); + wl_text_input_add_listener(entry->text_input, + &text_input_listener, d); + + d->entry = entry; + fprintf(stderr, "text_entry_create() entry(%p) created.\n", entry); + + return entry; +} + static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) @@ -600,6 +1170,12 @@ registry_handle_global(void *data, struct wl_registry *registry, tizen_input_device_manager_add_listener(d->devicemgr, &_input_device_manager_listener, d); fprintf(stderr, "tizen input device manager bound!\n"); + } else if (strcmp(interface, "wl_text_input_manager") == 0) { + d->text_input_mgr = wl_registry_bind(registry, + id, &wl_text_input_manager_interface, version); + fprintf(stderr, "wl_text_input_manager bound!\n"); + + text_entry_create(d, "Entry"); } } @@ -698,6 +1274,11 @@ create_display(void) static void destroy_display(struct display *display) { + text_entry_destroy(display); + + if (display->text_input_mgr) + wl_text_input_manager_destroy(display->text_input_mgr); + if (display->seat) wl_seat_destroy(display->seat); diff --git a/clients/text-entry.c b/clients/text-entry.c deleted file mode 100644 index 0561e56..0000000 --- a/clients/text-entry.c +++ /dev/null @@ -1,1261 +0,0 @@ -/* - * Copyright © 2011 Benjamin Franzke - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "xdg-shell-client-protocol.h" -#include -#include - -static uint64_t buffer_info_key; -#define BUFFER_INFO_KEY (unsigned long)(&buffer_info_key) - -struct display { - struct wl_display *display; - struct wl_registry *registry; - struct wl_compositor *compositor; - struct xdg_wm_base *wm_base; - struct wl_shm *shm; - struct wl_seat *seat; - struct wayland_tbm_client *wl_tbm; - bool has_xrgb; - - struct wl_text_input_manager *text_input_mgr; - int notified; - bool blocked; - struct wl_surface *entered_surface; - - struct text_entry *entry; -}; - -struct window { - struct display *display; - int width, height; - struct wl_surface *surface; - struct xdg_surface *xdg_surface; - struct xdg_toplevel *xdg_toplevel; - struct wl_callback *callback; - tbm_surface_queue_h surface_queue; - bool wait_for_configure; -}; - -struct buffer_info { - struct window *window; - struct wl_buffer *wl_buffer; -}; - -struct text_entry { - char *text; - int active; - bool panel_visible; - uint32_t cursor; - uint32_t anchor; - struct { - char *text; - int32_t cursor; - char *commit; - } preedit; - struct { - int32_t cursor; - } preedit_info; - struct { - int32_t cursor; - int32_t anchor; - uint32_t delete_index; - uint32_t delete_length; - bool invalid_delete; - } pending_commit; - struct wl_text_input *text_input; - struct { - xkb_mod_mask_t shift_mask; - } keysym; - uint32_t serial; - uint32_t reset_serial; - uint32_t content_purpose; - bool click_to_show; - char *preferred_language; - bool button_pressed; -}; - -struct rectangle { - int32_t x; - int32_t y; - int32_t width; - int32_t height; -}; - -static int running = 1; - -static void -redraw(void *data, struct wl_callback *callback, uint32_t time); -static void -text_entry_activate(struct display *d); -static void -text_entry_deactivate(struct display *d); - -static void -handle_xdg_surface_configure(void *data, struct xdg_surface *surface, - uint32_t serial) -{ - struct window *window = data; - - xdg_surface_ack_configure(surface, serial); - - if (window->wait_for_configure) { - redraw(window, NULL, 0); - window->wait_for_configure = false; - } -} - -static const struct xdg_surface_listener xdg_surface_listener = { - handle_xdg_surface_configure, -}; - -static void -handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, - int32_t width, int32_t height, - struct wl_array *state) -{ -} - -static void -handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) -{ - running = 0; -} - -static const struct xdg_toplevel_listener xdg_toplevel_listener = { - handle_xdg_toplevel_configure, - handle_xdg_toplevel_close, -}; - -static struct window * -create_window(struct display *display, int width, int height) -{ - struct window *window; - - window = calloc(1, sizeof *window); - if (!window) - return NULL; - - window->callback = NULL; - window->display = display; - window->width = width; - window->height = height; - window->surface = wl_compositor_create_surface(display->compositor); - - if (display->wm_base) { - window->xdg_surface = - xdg_wm_base_get_xdg_surface(display->wm_base, - window->surface); - assert(window->xdg_surface); - xdg_surface_add_listener(window->xdg_surface, - &xdg_surface_listener, window); - - window->xdg_toplevel = - xdg_surface_get_toplevel(window->xdg_surface); - assert(window->xdg_toplevel); - xdg_toplevel_add_listener(window->xdg_toplevel, - &xdg_toplevel_listener, window); - - xdg_toplevel_set_title(window->xdg_toplevel, "simple-tbm"); - wl_surface_commit(window->surface); - window->wait_for_configure = true; - } else { - assert(0); - } - - window->surface_queue = - wayland_tbm_client_create_surface_queue(display->wl_tbm, - window->surface, - 3, - width, - height, - TBM_FORMAT_XRGB8888); - assert(window->surface_queue); - - return window; -} - -static void -destroy_window(struct window *window) -{ - tbm_surface_queue_destroy(window->surface_queue); - - if (window->callback) - wl_callback_destroy(window->callback); - - if (window->xdg_toplevel) - xdg_toplevel_destroy(window->xdg_toplevel); - if (window->xdg_surface) - xdg_surface_destroy(window->xdg_surface); - wl_surface_destroy(window->surface); - free(window); -} - -static void -paint_pixels(void *image, int padding, int width, int height, uint32_t time) -{ - const int halfh = padding + (height - padding * 2) / 2; - const int halfw = padding + (width - padding * 2) / 2; - int ir, or; - uint32_t *pixel = image; - int y; - - /* squared radii thresholds */ - or = (halfw < halfh ? halfw : halfh) - 8; - ir = or - 32; - or *= or; - ir *= ir; - - pixel += padding * width; - for (y = padding; y < height - padding; y++) { - int x; - int y2 = (y - halfh) * (y - halfh); - - pixel += padding; - for (x = padding; x < width - padding; x++) { - uint32_t v; - - /* squared distance from center */ - int r2 = (x - halfw) * (x - halfw) + y2; - - if (r2 < ir) - v = (r2 / 32 + time / 64) * 0x0080401; - else if (r2 < or) - v = (y + time / 32) * 0x0080401; - else - v = (x + time / 16) * 0x0080401; - v &= 0x00ffffff; - - /* cross if compositor uses X from XRGB as alpha */ - if (abs(x - y) > 6 && abs(x + y - height) > 6) - v |= 0xff000000; - - *pixel++ = v; - } - - pixel += padding; - } -} - -static void -buffer_info_free_cb(void *data) -{ - struct buffer_info *buffer_info = data; - - if (!buffer_info) - return; - - wayland_tbm_client_destroy_buffer(buffer_info->window->display->wl_tbm, - buffer_info->wl_buffer); - free(buffer_info); -} - -static void -buffer_handle_release(void *data, struct wl_buffer *wl_buffer) -{ - tbm_surface_h surface = data; - struct buffer_info *buffer_info; - - tbm_surface_internal_get_user_data(surface, BUFFER_INFO_KEY, - (void **)&buffer_info); - if (buffer_info) - tbm_surface_queue_release(buffer_info->window->surface_queue, surface); -} - -static const struct wl_buffer_listener buffer_listener = { - .release = buffer_handle_release, -}; - -static const struct wl_callback_listener frame_listener; - -static void -redraw(void *data, struct wl_callback *callback, uint32_t time) -{ - struct window *window = data; - struct buffer_info *buffer_info = NULL; - tbm_surface_h surface = NULL; - tbm_surface_info_s surface_info; - - if (!tbm_surface_queue_can_dequeue(window->surface_queue, 0)) - return; - - tbm_surface_queue_dequeue(window->surface_queue, &surface); - assert(surface); - - tbm_surface_internal_get_user_data(surface, BUFFER_INFO_KEY, - (void **)&buffer_info); - if (!buffer_info) { - buffer_info = calloc(1, sizeof *buffer_info); - assert(buffer_info); - - tbm_surface_internal_add_user_data(surface, BUFFER_INFO_KEY, buffer_info_free_cb); - tbm_surface_internal_set_user_data(surface, BUFFER_INFO_KEY, buffer_info); - - buffer_info->wl_buffer = - wayland_tbm_client_create_buffer(window->display->wl_tbm, surface); - assert(buffer_info->wl_buffer); - - wl_buffer_add_listener(buffer_info->wl_buffer, &buffer_listener, - surface); - - buffer_info->window = window; - } - - tbm_surface_map(surface, TBM_SURF_OPTION_WRITE, &surface_info); - - paint_pixels(surface_info.planes[0].ptr, 20, - (surface_info.planes[0].stride/4), surface_info.height, time); - - tbm_surface_unmap(surface); - - wl_surface_attach(window->surface, buffer_info->wl_buffer, 0, 0); - wl_surface_damage(window->surface, - 20, 20, window->width - 40, window->height - 40); - - if (callback) - wl_callback_destroy(callback); - - window->callback = wl_surface_frame(window->surface); - wl_callback_add_listener(window->callback, &frame_listener, window); - wl_surface_commit(window->surface); -} - -static const struct wl_callback_listener frame_listener = { - redraw -}; - -static void -shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) -{ - struct display *d = data; - - if (format == WL_SHM_FORMAT_XRGB8888) - d->has_xrgb = true; -} - -struct wl_shm_listener shm_listener = { - shm_format -}; - -static void -xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial) -{ - xdg_wm_base_pong(shell, serial); -} - -static const struct xdg_wm_base_listener xdg_wm_base_listener = { - xdg_wm_base_ping, -}; - -static void pointer_handle_button(void *data, struct wl_pointer *pointer, - uint32_t serial, uint32_t time, uint32_t button, uint32_t state) -{ - struct display *d = data; - - if (state == WL_POINTER_BUTTON_STATE_PRESSED) { - fprintf(stderr, "pointer_handle_button: PRESSED\n"); - - text_entry_activate(d); - } - else { - fprintf(stderr, "pointer_handle_button: RELEASED\n"); - - text_entry_deactivate(d); - } -} - -static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, - uint32_t serial, struct wl_surface *surface, - wl_fixed_t surface_x, wl_fixed_t surface_y) -{ - struct display *d = data; - - fprintf(stderr, "pointer_handle_enter surface_x:%d, surface_y:%d\n", - wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); - d->entered_surface = surface; -} - -static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer, - uint32_t serial, struct wl_surface *surface) -{ - fprintf(stderr, "pointer_handle_leave\n"); -} - -static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, - uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) -{ - fprintf(stderr, "pointer_handle_motion surface_x:%d, surface_y:%d\n", - wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); -} - -static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) -{ - fprintf(stderr, "pointer_handle_frame\n"); -} - -static struct wl_pointer_listener pointer_listener = { - .enter = pointer_handle_enter, - .leave = pointer_handle_leave, - .motion = pointer_handle_motion, - .button = pointer_handle_button, - .axis = NULL, - .frame = pointer_handle_frame, - .axis_source = NULL, - .axis_stop = NULL, - .axis_discrete = NULL, -}; - -static void touch_handle_down(void *data, struct wl_touch *wl_touch, - uint32_t serial, uint32_t time, struct wl_surface *surface, - int32_t id, wl_fixed_t x, wl_fixed_t y) -{ - fprintf(stderr, "touch_handle_down id:%d, x:%d, y:%d\n", - id, wl_fixed_to_int(x), wl_fixed_to_int(y)); -} - -static void touch_handle_up(void *data, struct wl_touch *wl_touch, - uint32_t serial, uint32_t time, int32_t id) -{ - fprintf(stderr, "touch_handle_up id:%d\n", id); -} - -static void touch_handle_motion(void *data, struct wl_touch *wl_touch, - uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) -{ - fprintf(stderr, "touch_handle_motion id:%d, x:%d, y:%d\n", - id, wl_fixed_to_int(x), wl_fixed_to_int(y)); -} - -static void touch_handle_frame(void *data, struct wl_touch *wl_touch) -{ - fprintf(stderr, "touch_handle_frame\n"); -} - -static struct wl_touch_listener touch_listener = { - .down = touch_handle_down, - .up = touch_handle_up, - .motion = touch_handle_motion, - .frame = touch_handle_frame, - .cancel = NULL, - .shape = NULL, - .orientation = NULL, -}; - -static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, - uint32_t format, int32_t fd, uint32_t size) -{ - fprintf(stderr, "keyboard_handle_keymap\n"); -} -static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, - uint32_t serial, struct wl_surface *surface, struct wl_array *keys) -{ - fprintf(stderr, "keyboard_handle_enter\n"); -} -static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, - uint32_t serial, struct wl_surface *surface) -{ - fprintf(stderr, "keyboard_handle_leave\n"); -} -static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard, - uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, - uint32_t mods_locked, uint32_t group) -{ - fprintf(stderr, "keyboard_handle_modifiers\n"); -} -static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard, - int32_t rate, int32_t delay) -{ - fprintf(stderr, "keyboard_handle_repeat_info\n"); -} - -static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, - uint32_t serial, uint32_t time, uint32_t key, uint32_t state) -{ - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - fprintf(stderr, "keyboard_handle_key: key:%d, PRESSED\n", key); - } else { - fprintf(stderr, "keyboard_handle_key: key:%d, RELEASED\n", key); - } -} - -static struct wl_keyboard_listener keyboard_listener = { - .keymap = keyboard_handle_keymap, - .enter = keyboard_handle_enter, - .leave = keyboard_handle_leave, - .key = keyboard_handle_key, - .modifiers = keyboard_handle_modifiers, - .repeat_info = keyboard_handle_repeat_info, -}; - -static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, - enum wl_seat_capability caps) -{ - struct display *d = data; - if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) { - struct wl_keyboard *keyboard = wl_seat_get_keyboard(wl_seat); - wl_keyboard_add_listener(keyboard, &keyboard_listener, NULL); - fprintf(stderr, "seat_handle_capabilities: keyboard\n"); - } - if ((caps & WL_SEAT_CAPABILITY_POINTER)) { - struct wl_pointer *pointer = wl_seat_get_pointer(wl_seat); - wl_pointer_add_listener(pointer, &pointer_listener, d); - fprintf(stderr, "seat_handle_capabilities: pointer\n"); - } - if ((caps & WL_SEAT_CAPABILITY_TOUCH)) { - struct wl_touch *touch = wl_seat_get_touch(wl_seat); - wl_touch_add_listener(touch, &touch_listener, d); - fprintf(stderr, "seat_handle_capabilities: touch\n"); - } -} - -static void seat_handle_name(void *data, struct wl_seat *wl_seat, - const char *name) -{ - fprintf(stderr, "seat_handle_name name:%s\n", name); -} - -const struct wl_seat_listener seat_listener = { - .capabilities = seat_handle_capabilities, - .name = seat_handle_name, -}; - -static void -text_entry_get_cursor_rectangle(struct text_entry *entry, struct rectangle *rectangle) -{ - if (entry->preedit.text && entry->preedit.cursor < 0) { - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = 0; - rectangle->height = 0; - return; - } - - rectangle->x = 10; - rectangle->y = 20; - rectangle->width = 50; - rectangle->height = 50; -} - -static void -text_entry_update(struct text_entry *entry) -{ - struct rectangle cursor_rectangle; - - fprintf(stderr, "text_entry_update()\n"); - - wl_text_input_set_content_type(entry->text_input, - WL_TEXT_INPUT_CONTENT_HINT_NONE, - entry->content_purpose); - - if (entry->preferred_language) - wl_text_input_set_preferred_language(entry->text_input, - entry->preferred_language); - - text_entry_get_cursor_rectangle(entry, &cursor_rectangle); - wl_text_input_set_cursor_rectangle(entry->text_input, - cursor_rectangle.x, - cursor_rectangle.y, - cursor_rectangle.width, - cursor_rectangle.height); - - wl_text_input_commit_state(entry->text_input, ++entry->serial); -} - -static void -text_entry_reset_preedit(struct text_entry *entry) -{ - fprintf(stderr, "text_entry_reset_preedit()\n"); - entry->preedit.cursor = 0; - - free(entry->preedit.text); - entry->preedit.text = NULL; - - free(entry->preedit.commit); - entry->preedit.commit = NULL; -} - -static void -text_entry_insert_at_cursor(struct text_entry *entry, const char *text, - int32_t cursor, int32_t anchor) -{ - fprintf(stderr, "text_entry_insert_at_cursor()\n"); - char *new_text; - int len_entry_text, len_text; - - len_entry_text = strlen(entry->text); - len_text = strlen(text); - new_text = malloc(len_entry_text + len_text + 1); - if (new_text == NULL) { - fprintf(stderr, "alloc fail"); - return; - } - - memcpy(new_text, entry->text, entry->cursor); - memcpy(new_text + entry->cursor, text, len_text); - memcpy(new_text + entry->cursor + len_text, - entry->text + entry->cursor, len_entry_text - entry->cursor); - new_text[len_entry_text + len_text] = '\0'; - - free(entry->text); - entry->text = new_text; - if (anchor >= 0) - entry->anchor = entry->cursor + strlen(text) + anchor; - else - entry->anchor = entry->cursor + 1 + anchor; - - if (cursor >= 0) - entry->cursor += strlen(text) + cursor; - else - entry->cursor += 1 + cursor; - - text_entry_update(entry); -} - -static void -text_entry_commit_and_reset(struct text_entry *entry) -{ - char *commit = NULL; - - fprintf(stderr, "text_entry_commit_and_reset()\n"); - - if (entry->preedit.commit) - commit = strdup(entry->preedit.commit); - - text_entry_reset_preedit(entry); - if (commit) { - text_entry_insert_at_cursor(entry, commit, 0, 0); - free(commit); - } - - wl_text_input_reset(entry->text_input); - text_entry_update(entry); - entry->reset_serial = entry->serial; -} - -static void -text_input_enter(void *data, struct wl_text_input *text_input, - struct wl_surface *surface) -{ - fprintf(stderr, "text_input_enter()\n"); - - struct display *d = data; - struct text_entry *entry = d->entry; - - entry->active++; - - text_entry_update(entry); - entry->reset_serial = entry->serial; -} - -static void -text_input_leave(void *data, struct wl_text_input *text_input) -{ - fprintf(stderr, "text_input_leave()\n"); - - struct display *d = data; - struct text_entry *entry = d->entry; - - text_entry_commit_and_reset(entry); - d->entry->active--; - - if (!entry->active) { - wl_text_input_hide_input_panel(text_input); - entry->panel_visible = false; - } -} - -static void -text_input_modifiers_map(void *data, struct wl_text_input *text_input, - struct wl_array *map) -{ - fprintf(stderr, "text_input_modifiers_map()\n"); -} - -static void -text_input_input_panel_state(void *data, struct wl_text_input *text_input, - uint32_t state) -{ - fprintf(stderr, "text_input_input_panel_state() state:%u\n", state); -} - -static void -clear_pending_preedit(struct text_entry *entry) -{ - fprintf(stderr, "clear_pending_preedit()\n"); - - memset(&entry->pending_commit, 0, sizeof entry->pending_commit); - - entry->preedit_info.cursor = 0; - - memset(&entry->preedit_info, 0, sizeof entry->preedit_info); -} - -static void -text_entry_delete_text(struct text_entry *entry, - uint32_t index, uint32_t length) -{ - uint32_t l; - - fprintf(stderr, "text_entry_delete_text()\n"); - - assert(index <= strlen(entry->text)); - assert(index + length <= strlen(entry->text)); - assert(index + length >= length); - - l = strlen(entry->text + index + length); - memmove(entry->text + index, - entry->text + index + length, - l + 1); - - if (entry->cursor > (index + length)) - entry->cursor -= length; - else if (entry->cursor > index) - entry->cursor = index; - - entry->anchor = entry->cursor; - - text_entry_update(entry); -} - -static void -text_entry_delete_selected_text(struct text_entry *entry) -{ - uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor; - uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor; - - fprintf(stderr, "text_entry_delete_selected_text()\n"); - - if (entry->anchor == entry->cursor) - return; - - text_entry_delete_text(entry, start_index, end_index - start_index); - - entry->anchor = entry->cursor; -} - -static void -text_entry_set_preedit(struct text_entry *entry, - const char *preedit_text, - int preedit_cursor) -{ - fprintf(stderr, "text_entry_set_preedit()\n"); - - text_entry_reset_preedit(entry); - - if (!preedit_text) - return; - - entry->preedit.text = strdup(preedit_text); - entry->preedit.cursor = preedit_cursor; -} - -static void -text_input_preedit_string(void *data, struct wl_text_input *text_input, - uint32_t serial, const char *text, const char *commit) -{ - struct display *d = data; - struct text_entry *entry = d->entry; - - fprintf(stderr, "text_input_preedit_string() serial(%u), text(%s), commit(%s)\n", serial, text, commit); - - if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) { - fprintf(stderr, "Ignore preedit_string. Serial: %u, Current: %u, Reset: %u\n", - serial, entry->serial, entry->reset_serial); - clear_pending_preedit(entry); - return; - } - - if (entry->pending_commit.invalid_delete) { - fprintf(stderr, "Ignore preedit_string. Invalid previous delete_surrounding event.\n"); - clear_pending_preedit(entry); - return; - } - - if (entry->pending_commit.delete_length) { - text_entry_delete_text(entry, - entry->pending_commit.delete_index, - entry->pending_commit.delete_length); - } else { - text_entry_delete_selected_text(entry); - } - - text_entry_set_preedit(entry, text, entry->preedit_info.cursor); - entry->preedit.commit = strdup(commit); - - clear_pending_preedit(entry); - - text_entry_update(entry); -} - -static void -text_input_preedit_styling(void *data, struct wl_text_input *text_input, - uint32_t index, uint32_t length, uint32_t style) -{ - fprintf(stderr, "text_input_preedit_styling() index(%u), length(%u), style(%u)\n", index, length, style); - - switch (style) { - case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT: - fprintf(stderr, "text_input_preedit_styling() style:DEFAULT"); - break; - case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE: - fprintf(stderr, "text_input_preedit_styling() style:UNDERLINE"); - break; - case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT: - fprintf(stderr, "text_input_preedit_styling() style:INCORRECT"); - break; - case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION: - fprintf(stderr, "text_input_preedit_styling() style:SELECTION"); - break; - case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT: - fprintf(stderr, "text_input_preedit_styling() style:HIGHLIGHT"); - break; - case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE: - fprintf(stderr, "text_input_preedit_styling() style:ACTIVE"); - break; - case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE: - fprintf(stderr, "text_input_preedit_styling() style:INACTIVE"); - break; - default: - fprintf(stderr, "text_input_preedit_styling() no style enum found"); - break; - } -} - -static void -text_input_preedit_cursor(void *data, struct wl_text_input *text_input, - int32_t index) -{ - struct display *d = data; - struct text_entry *entry = d->entry; - - fprintf(stderr, "text_input_preedit_cursor() index(%u)\n", index); - - entry->preedit_info.cursor = index; -} - -static void -text_input_commit_string(void *data, struct wl_text_input *text_input, - uint32_t serial, const char *text) -{ - struct display *d = data; - struct text_entry *entry = d->entry; - - fprintf(stderr, "text_input_commit_string() serial(%u), text(%s)\n", serial, text); - - if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) { - fprintf(stderr, "Ignore commit. Serial: %u, Current: %u, Reset: %u\n", - serial, entry->serial, entry->reset_serial); - return; - } - - if (entry->pending_commit.invalid_delete) { - fprintf(stderr, "Ignore commit. Invalid previous delete_surrounding event.\n"); - memset(&entry->pending_commit, 0, sizeof entry->pending_commit); - return; - } - - text_entry_reset_preedit(entry); - - if (entry->pending_commit.delete_length) { - text_entry_delete_text(entry, - entry->pending_commit.delete_index, - entry->pending_commit.delete_length); - } else { - text_entry_delete_selected_text(entry); - } - - text_entry_insert_at_cursor(entry, text, - entry->pending_commit.cursor, - entry->pending_commit.anchor); - - memset(&entry->pending_commit, 0, sizeof entry->pending_commit); -} - -static void -text_input_cursor_position(void *data, struct wl_text_input *text_input, - int32_t index, int32_t anchor) -{ - fprintf(stderr, "text_input_cursor_position() index(%d), anchor(%d)\n", index, anchor); -} - -static void -text_input_delete_surrounding_text(void *data, - struct wl_text_input *text_input, int32_t index, uint32_t length) -{ - struct text_entry *entry = data; - uint32_t text_length; - - fprintf(stderr, "text_input_delete_surrounding_text() index(%d), length(%u)\n", index, length); - - entry->pending_commit.delete_index = entry->cursor + index; - entry->pending_commit.delete_length = length; - entry->pending_commit.invalid_delete = false; - - text_length = strlen(entry->text); - - if (entry->pending_commit.delete_index > text_length || - length > text_length || - entry->pending_commit.delete_index + length > text_length) { - fprintf(stderr, "delete_surrounding_text: Invalid index: %d," \ - "length %u'; cursor: %u text length: %u\n", index, length, entry->cursor, text_length); - entry->pending_commit.invalid_delete = true; - return; - } -} - -static void -text_input_keysym(void *data, struct wl_text_input *text_input, - uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, - uint32_t modifiers) -{ - fprintf(stderr, "text_input_keysym() serial(%u), time(%u), sym(%u), state(%u), modifiers(%u)\n", - serial, time, sym, state, modifiers); -} - -static void -text_input_language(void *data, struct wl_text_input *text_input, - uint32_t serial, const char *language) -{ - fprintf(stderr, "text_input_language() serial(%u), language(%s)\n", serial, language); -} - -static void -text_input_text_direction(void *data, struct wl_text_input *text_input, - uint32_t serial, uint32_t direction) -{ - fprintf(stderr, "text_input_text_direction() serial(%d), direction(%d)\n", serial, direction); -} - -static const struct wl_text_input_listener text_input_listener = { - .enter = text_input_enter, - .leave = text_input_leave, - .modifiers_map = text_input_modifiers_map, - .input_panel_state = text_input_input_panel_state, - .preedit_string = text_input_preedit_string, - .preedit_styling = text_input_preedit_styling, - .preedit_cursor = text_input_preedit_cursor, - .commit_string = text_input_commit_string, - .cursor_position = text_input_cursor_position, - .delete_surrounding_text = text_input_delete_surrounding_text, - .keysym = text_input_keysym, - .language = text_input_language, - .text_direction = text_input_text_direction, - // TIZEN_ONLY - .selection_region = NULL, - .private_command = NULL, - .input_panel_geometry = NULL, - .input_panel_data = NULL, - .get_selection_text = NULL, - .get_surrounding_text = NULL, - .filter_key_event_done = NULL, - .hide_permission = NULL, - .recapture_string = NULL, - .input_panel_event = NULL, - .commit_content = NULL, - // -}; - -static void -text_entry_activate(struct display *d) -{ - struct wl_surface *surface = d->entered_surface; - struct text_entry *entry = d->entry; - - fprintf(stderr, "text_entry_activate\n"); - if (entry->click_to_show && entry->active) { - entry->panel_visible = !entry->panel_visible; - - if (entry->panel_visible) - wl_text_input_show_input_panel(entry->text_input); - else - wl_text_input_hide_input_panel(entry->text_input); - - return; - } - - if (!entry->click_to_show) - wl_text_input_show_input_panel(entry->text_input); - - wl_text_input_activate(entry->text_input, - d->seat, - surface); -} - -static void -text_entry_deactivate(struct display *d) -{ - struct text_entry *entry = d->entry; - - fprintf(stderr, "text_entry_deactivate\n"); - wl_text_input_deactivate(entry->text_input, - d->seat); -} - -static void -text_entry_destroy(struct display *d) -{ - struct text_entry *entry; - - entry = d->entry; - d->entry = NULL; - - wl_text_input_destroy(entry->text_input); - free(entry->text); - free(entry->preferred_language); - free(entry); -} - -static struct text_entry* -text_entry_create(struct display *d, const char *text) -{ - struct text_entry *entry; - - entry = calloc(1, sizeof *entry); - if (!entry) - return NULL; - - entry->text = strdup(text); - entry->active = 0; - entry->panel_visible = false; - entry->cursor = strlen(text); - entry->anchor = entry->cursor; - entry->click_to_show = true; - entry->text_input = - wl_text_input_manager_create_text_input(d->text_input_mgr); - wl_text_input_add_listener(entry->text_input, - &text_input_listener, d); - - d->entry = entry; - fprintf(stderr, "text_entry_create() entry(%p) created.\n", entry); - - return entry; -} - -static void -registry_handle_global(void *data, struct wl_registry *registry, - uint32_t id, const char *interface, uint32_t version) -{ - struct display *d = data; - - if (strcmp(interface, "wl_compositor") == 0) { - d->compositor = - wl_registry_bind(registry, - id, &wl_compositor_interface, 1); - } else if (strcmp(interface, "xdg_wm_base") == 0) { - d->wm_base = wl_registry_bind(registry, - id, &xdg_wm_base_interface, 1); - xdg_wm_base_add_listener(d->wm_base, &xdg_wm_base_listener, d); - } else if (strcmp(interface, "wl_shm") == 0) { - d->shm = wl_registry_bind(registry, - id, &wl_shm_interface, 1); - wl_shm_add_listener(d->shm, &shm_listener, d); - } else if (strcmp(interface, "wl_seat") == 0) { - d->seat = wl_registry_bind(registry, - id, &wl_seat_interface, 7); - wl_seat_add_listener(d->seat, &seat_listener, d); - fprintf(stderr, "wl_seat bound!\n"); - } else if (strcmp(interface, "wl_text_input_manager") == 0) { - d->text_input_mgr = wl_registry_bind(registry, - id, &wl_text_input_manager_interface, version); - fprintf(stderr, "wl_text_input_manager bound!\n"); - - text_entry_create(d, "Entry"); - } -} - -static void -registry_handle_global_remove(void *data, struct wl_registry *registry, - uint32_t name) -{ -} - -static const struct wl_registry_listener registry_listener = { - registry_handle_global, - registry_handle_global_remove -}; - -static struct display * -create_display(void) -{ - struct display *display; - - display = calloc(1, sizeof *display); - if (display == NULL) { - fprintf(stderr, "out of memory\n"); - exit(1); - } - display->display = wl_display_connect(NULL); - assert(display->display); - - display->has_xrgb = false; - display->registry = wl_display_get_registry(display->display); - wl_registry_add_listener(display->registry, - ®istry_listener, display); - wl_display_roundtrip(display->display); - if (display->shm == NULL) { - fprintf(stderr, "No wl_shm global\n"); - exit(1); - } - - wl_display_roundtrip(display->display); - - /* - * Why do we need two roundtrips here? - * - * wl_display_get_registry() sends a request to the server, to which - * the server replies by emitting the wl_registry.global events. - * The first wl_display_roundtrip() sends wl_display.sync. The server - * first processes the wl_display.get_registry which includes sending - * the global events, and then processes the sync. Therefore when the - * sync (roundtrip) returns, we are guaranteed to have received and - * processed all the global events. - * - * While we are inside the first wl_display_roundtrip(), incoming - * events are dispatched, which causes registry_handle_global() to - * be called for each global. One of these globals is wl_shm. - * registry_handle_global() sends wl_registry.bind request for the - * wl_shm global. However, wl_registry.bind request is sent after - * the first wl_display.sync, so the reply to the sync comes before - * the initial events of the wl_shm object. - * - * The initial events that get sent as a reply to binding to wl_shm - * include wl_shm.format. These tell us which pixel formats are - * supported, and we need them before we can create buffers. They - * don't change at runtime, so we receive them as part of init. - * - * When the reply to the first sync comes, the server may or may not - * have sent the initial wl_shm events. Therefore we need the second - * wl_display_roundtrip() call here. - * - * The server processes the wl_registry.bind for wl_shm first, and - * the second wl_display.sync next. During our second call to - * wl_display_roundtrip() the initial wl_shm events are received and - * processed. Finally, when the reply to the second wl_display.sync - * arrives, it guarantees we have processed all wl_shm initial events. - * - * This sequence contains two examples on how wl_display_roundtrip() - * can be used to guarantee, that all reply events to a request - * have been received and processed. This is a general Wayland - * technique. - */ - - if (!display->has_xrgb) { - fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n"); - exit(1); - } - - display->wl_tbm = wayland_tbm_client_init(display->display); - if (!display->wl_tbm) { - fprintf(stderr, "failed wayland_tbm_client_init()\n"); - exit(1); - } - - display->notified = -1; - - return display; -} - -static void -destroy_display(struct display *display) -{ - text_entry_destroy(display); - - if (display->text_input_mgr) - wl_text_input_manager_destroy(display->text_input_mgr); - - if (display->seat) - wl_seat_destroy(display->seat); - - if (display->shm) - wl_shm_destroy(display->shm); - - if (display->wm_base) - xdg_wm_base_destroy(display->wm_base); - - if (display->compositor) - wl_compositor_destroy(display->compositor); - - wayland_tbm_client_deinit(display->wl_tbm); - wl_registry_destroy(display->registry); - wl_display_flush(display->display); - wl_display_disconnect(display->display); - free(display); -} - -static void -signal_int(int signum) -{ - running = 0; -} - -int -main(int argc, char **argv) -{ - struct sigaction sigint; - struct display *display; - struct window *window; - int ret = 0; - - display = create_display(); - window = create_window(display, 250, 250); - if (!window) - return 1; - - sigint.sa_handler = signal_int; - sigemptyset(&sigint.sa_mask); - sigint.sa_flags = SA_RESETHAND; - sigaction(SIGINT, &sigint, NULL); - - /* Initialise damage to full surface, so the padding gets painted */ - wl_surface_damage(window->surface, 0, 0, - window->width, window->height); - - if (!window->wait_for_configure) - redraw(window, NULL, 0); - - while (running && ret != -1) - ret = wl_display_dispatch(display->display); - - fprintf(stderr, "simple-shm exiting\n"); - - destroy_window(window); - destroy_display(display); - - return 0; -} diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 37f9559..82a0fec 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -570,7 +570,6 @@ ninja -C builddir install %{_libdir}/pkgconfig/libds-tizen-text-input.pc %{_libdir}/libds-tizen-text-input.so %{_bindir}/libds-tizen-text-input-tests -%{_bindir}/text-entry %files input-method %manifest %{name}.manifest -- 2.7.4 From 1b5eb509806e3b880a2a2b66959b14950cd6052e Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Sun, 28 Aug 2022 15:14:09 +0900 Subject: [PATCH 13/16] add .vscode to .gitignore Change-Id: I5ed9158db630465b6766fdf3454dc30d90a7ab68 --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 7ca031c..9aa0a36 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,6 @@ dkms.conf # Vim swapfiles .*.sw? .sw? + +# VS code +.vscode -- 2.7.4 From e8f683006d4fe45cc7a7d5093c3d7c4ead658cbd Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Fri, 12 Aug 2022 17:07:33 +0900 Subject: [PATCH 14/16] implement tizen_policy Change-Id: I1be6f809cba50e8864e3d7ee6059dcefbdf8840a --- include/libds-tizen/policy.h | 686 +++++++++++++ packaging/libds-tizen.spec | 29 + src/meson.build | 1 + src/policy/meson.build | 31 + src/policy/policy.c | 2313 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 3060 insertions(+) create mode 100644 include/libds-tizen/policy.h create mode 100644 src/policy/meson.build create mode 100644 src/policy/policy.c diff --git a/include/libds-tizen/policy.h b/include/libds-tizen/policy.h new file mode 100644 index 0000000..f95e7cf --- /dev/null +++ b/include/libds-tizen/policy.h @@ -0,0 +1,686 @@ +#ifndef LIBDS_TIZEN_POLICY_H +#define LIBDS_TIZEN_POLICY_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tizen_policy; +struct ds_tizen_policy_surface; +struct ds_tizen_policy_visibility; +struct ds_tizen_policy_position; +struct ds_tizen_policy_subsurface_watcher; + +enum ds_tizen_policy_window_type +{ + DS_TIZEN_POLICY_WINDOW_TYPE_NONE, + DS_TIZEN_POLICY_WINDOW_TYPE_TOPLEVEL, + DS_TIZEN_POLICY_WINDOW_TYPE_FULLLSCREEN, + DS_TIZEN_POLICY_WINDOW_TYPE_MAXIMIZED, + DS_TIZEN_POLICY_WINDOW_TYPE_TRANSIENT, + DS_TIZEN_POLICY_WINDOW_TYPE_MENU, + DS_TIZEN_POLICY_WINDOW_TYPE_DND, + DS_TIZEN_POLICY_WINDOW_TYPE_CUSTOM, + DS_TIZEN_POLICY_WINDOW_TYPE_NOTIFICATION, + DS_TIZEN_POLICY_WINDOW_TYPE_UTILITY, + DS_TIZEN_POLICY_WINDOW_TYPE_DIALOG, + DS_TIZEN_POLICY_WINDOW_TYPE_DOCK, + DS_TIZEN_POLICY_WINDOW_TYPE_SPLASH, + DS_TIZEN_POLICY_WINDOW_TYPE_DESKTOP, +}; + +enum ds_tizen_policy_conformant_part +{ + DS_TIZEN_POLICY_CONFORMANT_PART_UNKNOWN, + DS_TIZEN_POLICY_CONFORMANT_PART_INDICATOR, + DS_TIZEN_POLICY_CONFORMANT_PART_KEYBOARD, + DS_TIZEN_POLICY_CONFORMANT_PART_CLIPBOARD, +}; + +enum ds_tizen_policy_error_state +{ + DS_TIZEN_POLICY_ERROR_STATE_NONE, + DS_TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED, +}; + +enum ds_tizen_policy_notification_level +{ + DS_TIZEN_POLICY_NOTIFICATION_LEVEL_1, + DS_TIZEN_POLICY_NOTIFICATION_LEVEL_2, + DS_TIZEN_POLICY_NOTIFICATION_LEVEL_3, + DS_TIZEN_POLICY_NOTIFICATION_LEVEL_NONE, + DS_TIZEN_POLICY_NOTIFICATION_LEVEL_DEFAULT, + DS_TIZEN_POLICY_NOTIFICATION_LEVEL_MEDIUM, + DS_TIZEN_POLICY_NOTIFICATION_LEVEL_HIGH, + DS_TIZEN_POLICY_NOTIFICATION_LEVEL_TOP, +}; + +enum ds_tizen_policy_window_screen_mode +{ + DS_TIZEN_POLICY_WINDOW_SCREEN_MODE_DEFAULT, + DS_TIZEN_POLICY_WINDOW_SCREEN_MODE_ALWAYS_ON, +}; + +enum ds_tizen_policy_stack_mode +{ + DS_TIZEN_POLICY_STACK_MODE_NONE, + DS_TIZEN_POLICY_STACK_MODE_ABOVE, + DS_TIZEN_POLICY_STACK_MODE_BELOW, +}; + +enum ds_tizen_policy_visibility_type +{ + DS_TIZEN_POLICY_VISIBILITY_TYPE_UNKNOWN, + DS_TIZEN_POLICY_VISIBILITY_TYPE_UNOBSCURED, + DS_TIZEN_POLICY_VISIBILITY_TYPE_PARTIALLY_OBSCURED, + DS_TIZEN_POLICY_VISIBILITY_TYPE_FULLY_OBSCURED, + DS_TIZEN_POLICY_VISIBILITY_TYPE_PRE_UNOBSCURED, +}; + +// policy event structures +struct ds_tizen_event_policy_get_surface +{ + struct ds_tizen_policy *policy; + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_activate_below_by_univeral_id +{ + struct ds_tizen_policy *policy; + uint32_t universal_id; + uint32_t below_universal_id; +}; + +struct ds_tizen_event_policy_lower_by_universal_id +{ + struct ds_tizen_policy *policy; + uint32_t universal_id; +}; + +struct ds_tizen_event_policy_set_transient_for +{ + struct ds_tizen_policy *policy; + uint32_t child_universal_id; + uint32_t parent_universal_id; +}; + +struct ds_tizen_event_policy_unset_transient_for +{ + struct ds_tizen_policy *policy; + uint32_t child_universal_id; +}; + +struct ds_tizen_event_policy_place_subsurface_below_parent +{ + struct ds_tizen_policy *policy; + struct ds_subsurface *subsurface; +}; + +struct ds_tizen_event_policy_set_subsurface_stand_alone +{ + struct ds_tizen_policy *policy; + struct ds_subsurface *subsurface; +}; + +struct ds_tizen_event_policy_set_background_state +{ + struct ds_tizen_policy *policy; + int32_t pid; +}; + +struct ds_tizen_event_policy_unset_background_state +{ + struct ds_tizen_policy *policy; + int32_t pid; +}; + +struct ds_tizen_event_policy_activate_above_by_universal_id +{ + struct ds_tizen_policy *policy; + uint32_t universal_id; + uint32_t above_universal_id; +}; + +struct ds_tizen_event_policy_set_appid +{ + struct ds_tizen_policy *policy; + int32_t pid; + const char *appid; +}; + +struct ds_tizen_event_policy_set_transient_for_below +{ + struct ds_tizen_policy *policy; + uint32_t universal_id; + uint32_t parent_universal_id; +}; + +// policy policy_surface event structures +struct ds_tizen_event_policy_surface_get_visibility +{ + struct ds_tizen_policy_surface *policy_surface; + struct ds_tizen_policy_visibility *visibility; +}; + +struct ds_tizen_event_policy_surface_get_position +{ + struct ds_tizen_policy_surface *policy_surface; + struct ds_tizen_policy_position *position; +}; + +struct ds_tizen_event_policy_surface_activate +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_raise +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_lower +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_set_focus_skip +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_unset_focus_skip +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_set_role +{ + struct ds_tizen_policy_surface *policy_surface; + const char *role; +}; + +struct ds_tizen_event_policy_surface_set_window_type +{ + struct ds_tizen_policy_surface *policy_surface; + enum ds_tizen_policy_window_type win_type; +}; + +struct ds_tizen_event_policy_surface_set_conformant +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_unset_conformant +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_get_conformant +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_set_notification_level +{ + struct ds_tizen_policy_surface *policy_surface; + enum ds_tizen_policy_notification_level level; +}; + +struct ds_tizen_event_policy_surface_set_window_screen_mode +{ + struct ds_tizen_policy_surface *policy_surface; + enum ds_tizen_policy_window_screen_mode mode; +}; + +struct ds_tizen_event_policy_surface_get_subsurface +{ + struct ds_tizen_policy_surface *policy_surface; + uint32_t parent_universal_id; +}; + +struct ds_tizen_event_policy_surface_iconify +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_uniconify +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_add_aux_hint +{ + struct ds_tizen_policy_surface *policy_surface; + int32_t id; + const char *name; + const char *value; +}; + +struct ds_tizen_event_policy_surface_change_aux_hint +{ + struct ds_tizen_policy_surface *policy_surface; + int32_t id; + const char *value; +}; + +struct ds_tizen_event_policy_surface_delete_aux_hint +{ + struct ds_tizen_policy_surface *policy_surface; + int32_t id; +}; + +struct ds_tizen_event_policy_surface_get_supported_aux_hints +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_set_floating_mode +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_unset_floating_mode +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_set_stack_mode +{ + struct ds_tizen_policy_surface *policy_surface; + enum ds_tizen_policy_stack_mode mode; +}; + +struct ds_tizen_event_policy_surface_get_subsurface_watcher +{ + struct ds_tizen_policy_surface *policy_surface; + struct ds_tizen_policy_subsurface_watcher *subsurface_watcher; +}; + +struct ds_tizen_event_policy_surface_set_parent +{ + struct ds_tizen_policy_surface *policy_surface; + struct ds_surface *parent_surface; +}; + +struct ds_tizen_event_policy_surface_ack_conformant_region +{ + struct ds_tizen_policy_surface *policy_surface; + uint32_t serial; +}; + +struct ds_tizen_event_policy_surface_set_video +{ + struct ds_tizen_policy_surface *policy_surface; + bool video; +}; + +struct ds_tizen_event_policy_surface_show +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_hide +{ + struct ds_tizen_policy_surface *policy_surface; +}; + +struct ds_tizen_event_policy_surface_set_parent_with_below +{ + struct ds_tizen_policy_surface *policy_surface; + struct ds_surface *parent_surface; +}; + +// policy policy_surface event structures +struct ds_tizen_event_policy_position_set +{ + struct ds_tizen_policy_position *position; + int32_t x; + int32_t y; +}; + +struct ds_tizen_policy * +ds_tizen_policy_create(struct wl_display *display); + +// add listeners for ds_tizen_policy +void +ds_tizen_policy_add_destroy_listener(struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_get_surface_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_activate_below_by_univeral_id_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_lower_by_universal_id_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_set_transient_for_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_unset_transient_for_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_place_subsurface_below_parent_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_set_subsurface_stand_alone_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_set_background_state_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_unset_background_state_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_activate_above_by_universal_id_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_set_appid_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +void +ds_tizen_policy_add_set_transient_for_below_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener); + +// add listeners for ds_tizen_policy_surface +void +ds_tizen_policy_surface_add_destroy_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_get_visibility_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_get_position_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_activate_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_raise_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_lower_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_focus_skip_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_unset_focus_skip_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_role_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_window_type_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_conformant_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_unset_conformant_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_get_conformant_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_notification_level_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_window_screen_mode_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_get_subsurface_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_iconify_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_uniconify_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_add_aux_hint_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_change_aux_hint_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_delete_aux_hint_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_get_supported_aux_hints_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_floating_mode_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_unset_floating_mode_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_stack_mode_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_get_subsurface_watcher_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_parent_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_ack_conformant_region_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_video_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_show_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_hide_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +void +ds_tizen_policy_surface_add_set_parent_with_below_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener); + +// add listeners for ds_tizen_policy_visibility +void +ds_tizen_policy_visibility_add_destroy_listener( + struct ds_tizen_policy_visibility *visibility, + struct wl_listener *listener); + +// add listeners for ds_tizen_policy_position +void +ds_tizen_policy_position_add_destroy_listener( + struct ds_tizen_policy_position *position, + struct wl_listener *listener); + +void +ds_tizen_policy_position_add_set_listener( + struct ds_tizen_policy_position *position, + struct wl_listener *listener); + +// add listeners for ds_tizen_policy_subsurface_watcher +void +ds_tizen_policy_subsurface_watcher_add_destroy_listener( + struct ds_tizen_policy_subsurface_watcher *subsurface_watcher, + struct wl_listener *listener); + +// policy_surface senders to client +void +ds_tizen_policy_surface_send_conformant(struct ds_tizen_policy_surface *policy_surface, + bool active); + +void +ds_tizen_policy_surface_send_conformant_area(struct ds_tizen_policy_surface *policy_surface, + enum ds_tizen_policy_conformant_part part, bool visible, + int32_t x, int32_t y, int32_t w, int32_t h); + +void +ds_tizen_policy_surface_send_notification_done(struct ds_tizen_policy_surface *policy_surface, + enum ds_tizen_policy_notification_level level, + enum ds_tizen_policy_error_state state); + +void +ds_tizen_policy_surface_send_window_screen_mode_done(struct ds_tizen_policy_surface *policy_surface, + enum ds_tizen_policy_window_screen_mode mode, + enum ds_tizen_policy_error_state state); + +void +ds_tizen_policy_surface_send_iconify_state_changed(struct ds_tizen_policy_surface *policy_surface, + bool iconified, bool force); + +void +ds_tizen_policy_surface_send_supported_aux_hints(struct ds_tizen_policy_surface *policy_surface, + struct wl_array *hints, uint32_t force); + +void +ds_tizen_policy_surface_send_allowed_aux_hint(struct ds_tizen_policy_surface *policy_surface, + int32_t hint_id); + +void +ds_tizen_policy_surface_send_aux_message(struct ds_tizen_policy_surface *policy_surface, + const char *key, const char *value, struct wl_array *options); + +void +ds_tizen_policy_surface_send_conformant_region(struct ds_tizen_policy_surface *policy_surface, + enum ds_tizen_policy_conformant_part part, bool visible, + int32_t x, int32_t y, int32_t w, int32_t h, uint32_t serial); + +void +ds_tizen_policy_surface_send_interactive_move_done(struct ds_tizen_policy_surface *policy_surface, + int32_t x, int32_t y, uint32_t w, uint32_t h); + +void +ds_tizen_policy_surface_send_interactive_resize_done(struct ds_tizen_policy_surface *policy_surface, + int32_t x, int32_t y, uint32_t w, uint32_t h); + +// visibility senders to client +void +ds_tizen_policy_visibility_send_notify( + struct ds_tizen_policy_visibility *visibility, + enum ds_tizen_policy_visibility_type type); + +void +ds_tizen_policy_visibility_send_changed( + struct ds_tizen_policy_visibility *visibility, + enum ds_tizen_policy_visibility_type type, uint32_t option); + +// position senders to client +void +ds_tizen_policy_position_send_changed( + struct ds_tizen_policy_position *position, int32_t x, int32_t y); + +// getters for ds_tizen_policy_surface +struct ds_surface * +ds_tizen_policy_surface_get_surface(struct ds_tizen_policy_surface *policy_surface); + +bool +ds_tizen_policy_surface_get_conformant(struct ds_tizen_policy_surface *policy_surface); + +int32_t +ds_tizen_policy_surface_get_opaque_state(struct ds_tizen_policy_surface *policy_surface); + +bool +ds_tizen_policy_surface_get_iconified(struct ds_tizen_policy_surface *policy_surface); + +bool +ds_tizen_policy_surface_get_floating_mode(struct ds_tizen_policy_surface *policy_surface); + +enum ds_tizen_policy_stack_mode +ds_tizen_policy_surface_get_stack_mode(struct ds_tizen_policy_surface *policy_surface); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 82a0fec..1ef64cc 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -312,6 +312,21 @@ Group: Development/Libraries %description hwc-devel Development package for tizen hwc +## libds-tizen-policy +%package policy +Summary: Library for tizen policy +Group: Development/Libraries + +%description policy +Library for tizen policy + +%package policy-devel +Summary: Development package for tizen policy +Group: Development/Libraries + +%description policy-devel +Development package for tizen policy + %prep %setup -q cp %{SOURCE1001} . @@ -601,3 +616,17 @@ ninja -C builddir install %{_libdir}/pkgconfig/libds-tizen-hwc.pc %{_libdir}/libds-tizen-hwc.so* %{_bindir}/libds-tizen-hwc-tests + +%files policy +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_libdir}/libds-tizen-policy.so.* + +%files policy-devel +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_includedir}/libds-tizen/policy.h +%{_libdir}/pkgconfig/libds-tizen-policy.pc +%{_libdir}/libds-tizen-policy.so diff --git a/src/meson.build b/src/meson.build index 8d254fa..227b7a9 100644 --- a/src/meson.build +++ b/src/meson.build @@ -45,3 +45,4 @@ subdir('embedded_compositor') subdir('input_method') subdir('text_input') subdir('hwc') +subdir('policy') diff --git a/src/policy/meson.build b/src/policy/meson.build new file mode 100644 index 0000000..3f4881f --- /dev/null +++ b/src/policy/meson.build @@ -0,0 +1,31 @@ +libds_tizen_policy_files = [ + tizen_security_files, + 'policy.c', +] + +libds_tizen_policy_deps = [ + deps_libds_tizen, + deps_tizen_security, + dependency('tizen-extension-server', required: true), +] + +lib_libds_tizen_policy = shared_library('ds-tizen-policy', libds_tizen_policy_files, + dependencies: libds_tizen_policy_deps, + include_directories: [ common_inc, include_directories('.'), include_directories('..') ], + version: meson.project_version(), + install: true +) + +deps_libds_tizen_policy = declare_dependency( + link_with: lib_libds_tizen_policy, + dependencies: libds_tizen_policy_deps, + include_directories: [ common_inc, include_directories('.') ], +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(lib_libds_tizen_policy, + version: meson.project_version(), + filebase: 'libds-tizen-policy', + name: 'libds-tizen-policy', + description: 'tizen policy extension of libds-tizen for tizen platform', +) diff --git a/src/policy/policy.c b/src/policy/policy.c new file mode 100644 index 0000000..b349d8b --- /dev/null +++ b/src/policy/policy.c @@ -0,0 +1,2313 @@ +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "security.h" +#include "libds-tizen/policy.h" + +#define TIZEN_POLICY_VERSION 11 +#define TIZEN_POLICY_PRIVILEGE_SET_NOTIFICATION_LEVEL \ + "http://tizen.org/privilege/window.priority.set" +#define TIZEN_POLICY_PRIVILEGE_SET_SCREEN_MODE \ + "http://tizen.org/privilege/display" + +struct ds_tizen_policy +{ + struct wl_global *global; + + struct wl_list clients; + + struct wl_listener destroy; + + bool use_security; + + struct { + struct wl_signal destroy; + struct wl_signal get_surface; + struct wl_signal activate_below_by_univeral_id; + struct wl_signal lower_by_universal_id; + struct wl_signal set_transient_for; + struct wl_signal unset_transient_for; + struct wl_signal place_subsurface_below_parent; + struct wl_signal set_subsurface_stand_alone; + struct wl_signal set_background_state; + struct wl_signal unset_background_state; + struct wl_signal activate_above_by_universal_id; + struct wl_signal set_appid; + struct wl_signal set_transient_for_below; + } events; +}; + +struct ds_tizen_policy_client +{ + struct ds_tizen_policy *policy; + + struct wl_resource *resource; + struct wl_client *wl_client; + pid_t pid; + uid_t uid; + + struct wl_list policy_surfaces; + + struct wl_list link; // ds_tizen_policy::clients +}; + +struct ds_tizen_policy_surface +{ + struct ds_tizen_policy_client *client; + + struct ds_surface *surface; + pid_t pid; + uid_t uid; + + struct wl_list visibilities; + struct wl_list positions; + struct wl_list subsurface_watchers; + + bool conformant; + int32_t opaque_state; + bool iconified; + bool floating_mode; + enum ds_tizen_policy_stack_mode stack_mode; + bool video; + + struct { + struct wl_signal destroy; + struct wl_signal get_visibility; + struct wl_signal get_position; + struct wl_signal activate; + struct wl_signal raise; + struct wl_signal lower; + struct wl_signal set_focus_skip; + struct wl_signal unset_focus_skip; + struct wl_signal set_role; + struct wl_signal set_window_type; + struct wl_signal set_conformant; + struct wl_signal unset_conformant; + struct wl_signal get_conformant; + struct wl_signal set_notification_level; + struct wl_signal set_window_screen_mode; + struct wl_signal get_subsurface; + struct wl_signal iconify; + struct wl_signal uniconify; + struct wl_signal add_aux_hint; + struct wl_signal change_aux_hint; + struct wl_signal delete_aux_hint; + struct wl_signal get_supported_aux_hints; + struct wl_signal set_floating_mode; + struct wl_signal unset_floating_mode; + struct wl_signal set_stack_mode; + struct wl_signal get_subsurface_watcher; + struct wl_signal set_parent; + struct wl_signal ack_conformant_region; + struct wl_signal set_video; + struct wl_signal show; + struct wl_signal hide; + struct wl_signal set_parent_with_below; + } events; + + struct wl_list link; // ds_tizen_policy_client::policy_surfaces +}; + +struct ds_tizen_policy_visibility +{ + struct ds_tizen_policy_surface *policy_surface; + + struct wl_resource *resource; + + struct { + struct wl_signal destroy; + } events; + + struct wl_list link; // ds_tizen_policy_surface::visibilities +}; + +struct ds_tizen_policy_position +{ + struct ds_tizen_policy_surface *policy_surface; + + struct wl_resource *resource; + + struct { + struct wl_signal destroy; + struct wl_signal set; + } events; + + struct wl_list link; // ds_tizen_policy_surface::positions +}; + +struct ds_tizen_policy_subsurface_watcher +{ + struct ds_tizen_policy_surface *policy_surface; + + struct wl_resource *resource; + + struct { + struct wl_signal destroy; + } events; + + struct wl_list link; // ds_tizen_policy_surface::subsurface_watchers +}; + +static void policy_handle_display_destroy(struct wl_listener *listener, + void *data); + +static void policy_bind(struct wl_client *wl_client, void *data, + uint32_t version, uint32_t id); + +static struct ds_tizen_policy_surface *tizen_policy_client_find_policy_surface( + struct ds_tizen_policy_client *client, + struct ds_surface *surface); + +static struct ds_tizen_policy_surface *tizen_policy_client_get_surface( + struct wl_resource *resource, + struct wl_resource *surface_resource); + +WL_EXPORT struct ds_tizen_policy * +ds_tizen_policy_create(struct wl_display *display) +{ + struct ds_tizen_policy *policy; + + policy = calloc(1, sizeof *policy); + if (!policy) { + ds_err("calloc() failed."); + return NULL; + } + + policy->global = wl_global_create(display, &tizen_policy_interface, + TIZEN_POLICY_VERSION, policy, policy_bind); + if (!policy->global) { + ds_err("wl_global_create() failed. tizen_policy_interface"); + free(policy); + return NULL; + } + + wl_list_init(&policy->clients); + + policy->destroy.notify = policy_handle_display_destroy; + wl_display_add_destroy_listener(display, &policy->destroy); + + policy->use_security = tizen_security_init(); + if (!policy->use_security) { + ds_inf("tizen_security_init() is not successful. " + "policy works without security."); + } + + wl_signal_init(&policy->events.destroy); + wl_signal_init(&policy->events.get_surface); + wl_signal_init(&policy->events.activate_below_by_univeral_id); + wl_signal_init(&policy->events.lower_by_universal_id); + wl_signal_init(&policy->events.set_transient_for); + wl_signal_init(&policy->events.unset_transient_for); + wl_signal_init(&policy->events.place_subsurface_below_parent); + wl_signal_init(&policy->events.set_subsurface_stand_alone); + wl_signal_init(&policy->events.set_background_state); + wl_signal_init(&policy->events.unset_background_state); + wl_signal_init(&policy->events.activate_above_by_universal_id); + wl_signal_init(&policy->events.set_appid); + wl_signal_init(&policy->events.set_transient_for_below); + + ds_inf("Global created: tizen_policy(%p)", policy); + + return policy; +} + +WL_EXPORT void +ds_tizen_policy_add_destroy_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_get_surface_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.get_surface, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_activate_below_by_univeral_id_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.activate_below_by_univeral_id, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_lower_by_universal_id_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.lower_by_universal_id, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_set_transient_for_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.set_transient_for, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_unset_transient_for_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.unset_transient_for, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_place_subsurface_below_parent_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.place_subsurface_below_parent, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_set_subsurface_stand_alone_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.set_subsurface_stand_alone, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_set_background_state_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.set_background_state, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_unset_background_state_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.unset_background_state, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_activate_above_by_universal_id_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.activate_above_by_universal_id, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_set_appid_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.set_appid, listener); +} + +WL_EXPORT void +ds_tizen_policy_add_set_transient_for_below_listener( + struct ds_tizen_policy *policy, + struct wl_listener *listener) +{ + wl_signal_add(&policy->events.set_transient_for_below, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_destroy_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_get_visibility_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.get_visibility, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_get_position_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.get_position, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_activate_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.activate, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_raise_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.raise, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_lower_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.lower, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_focus_skip_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_focus_skip, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_unset_focus_skip_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.unset_focus_skip, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_role_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_role, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_window_type_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_window_type, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_conformant_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_conformant, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_unset_conformant_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.unset_conformant, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_get_conformant_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.get_conformant, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_notification_level_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_notification_level, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_window_screen_mode_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_window_screen_mode, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_get_subsurface_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.get_subsurface, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_iconify_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.iconify, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_uniconify_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.uniconify, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_add_aux_hint_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.add_aux_hint, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_change_aux_hint_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.change_aux_hint, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_delete_aux_hint_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.delete_aux_hint, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_get_supported_aux_hints_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.get_supported_aux_hints, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_floating_mode_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_floating_mode, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_unset_floating_mode_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.unset_floating_mode, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_stack_mode_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_stack_mode, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_get_subsurface_watcher_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.get_subsurface_watcher, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_parent_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_parent, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_ack_conformant_region_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.ack_conformant_region, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_video_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_video, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_show_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.show, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_hide_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.hide, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_add_set_parent_with_below_listener( + struct ds_tizen_policy_surface *policy_surface, + struct wl_listener *listener) +{ + wl_signal_add(&policy_surface->events.set_parent_with_below, listener); +} + +WL_EXPORT void +ds_tizen_policy_visibility_add_destroy_listener( + struct ds_tizen_policy_visibility *visibility, + struct wl_listener *listener) +{ + wl_signal_add(&visibility->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_policy_position_add_destroy_listener( + struct ds_tizen_policy_position *position, + struct wl_listener *listener) +{ + wl_signal_add(&position->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_policy_position_add_set_listener( + struct ds_tizen_policy_position *position, + struct wl_listener *listener) +{ + wl_signal_add(&position->events.set, listener); +} + +void +ds_tizen_policy_subsurface_watcher_add_destroy_listener( + struct ds_tizen_policy_subsurface_watcher *subsurface_watcher, + struct wl_listener *listener) +{ + wl_signal_add(&subsurface_watcher->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_policy_surface_send_conformant(struct ds_tizen_policy_surface *policy_surface, + bool active) +{ + tizen_policy_send_conformant(policy_surface->client->resource, + ds_surface_get_wl_resource(policy_surface->surface), active); +} + +WL_EXPORT void +ds_tizen_policy_surface_send_conformant_area(struct ds_tizen_policy_surface *policy_surface, + enum ds_tizen_policy_conformant_part part, bool visible, + int32_t x, int32_t y, int32_t w, int32_t h) +{ + uint32_t conformant_part; + + switch (part) { + case DS_TIZEN_POLICY_CONFORMANT_PART_INDICATOR: + conformant_part = TIZEN_POLICY_CONFORMANT_PART_INDICATOR; + break; + case DS_TIZEN_POLICY_CONFORMANT_PART_KEYBOARD: + conformant_part = TIZEN_POLICY_CONFORMANT_PART_KEYBOARD; + break; + case DS_TIZEN_POLICY_CONFORMANT_PART_CLIPBOARD: + conformant_part = TIZEN_POLICY_CONFORMANT_PART_CLIPBOARD; + break; + default: + ds_err("Not supported conformant_part(%d)", part); + return; + } + + tizen_policy_send_conformant_area(policy_surface->client->resource, + ds_surface_get_wl_resource(policy_surface->surface), conformant_part, visible, + x, y, w, h); +} + +WL_EXPORT void +ds_tizen_policy_surface_send_notification_done(struct ds_tizen_policy_surface *policy_surface, + enum ds_tizen_policy_notification_level level, + enum ds_tizen_policy_error_state state) +{ + uint32_t notification_level; + uint32_t error_state; + + switch (level) { + case DS_TIZEN_POLICY_NOTIFICATION_LEVEL_1: + notification_level = TIZEN_POLICY_LEVEL_1; + break; + case DS_TIZEN_POLICY_NOTIFICATION_LEVEL_2: + notification_level = TIZEN_POLICY_LEVEL_2; + break; + case DS_TIZEN_POLICY_NOTIFICATION_LEVEL_3: + notification_level = TIZEN_POLICY_LEVEL_3; + break; + case DS_TIZEN_POLICY_NOTIFICATION_LEVEL_NONE: + notification_level = TIZEN_POLICY_LEVEL_NONE; + break; + case DS_TIZEN_POLICY_NOTIFICATION_LEVEL_DEFAULT: + notification_level = TIZEN_POLICY_LEVEL_DEFAULT; + break; + case DS_TIZEN_POLICY_NOTIFICATION_LEVEL_MEDIUM: + notification_level = TIZEN_POLICY_LEVEL_MEDIUM; + break; + case DS_TIZEN_POLICY_NOTIFICATION_LEVEL_HIGH: + notification_level = TIZEN_POLICY_LEVEL_HIGH; + break; + case DS_TIZEN_POLICY_NOTIFICATION_LEVEL_TOP: + notification_level = TIZEN_POLICY_LEVEL_TOP; + break; + default: + ds_err("Not supported notification_level(%d)", level); + return; + } + + switch (state) { + case DS_TIZEN_POLICY_ERROR_STATE_NONE: + error_state = TIZEN_POLICY_ERROR_STATE_NONE; + break; + case DS_TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED: + error_state = TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED; + break; + default: + ds_err("Not supported error_state(%d)", state); + return; + } + + tizen_policy_send_notification_done(policy_surface->client->resource, + ds_surface_get_wl_resource(policy_surface->surface), + notification_level, error_state); +} + +WL_EXPORT void +ds_tizen_policy_surface_send_window_screen_mode_done(struct ds_tizen_policy_surface *policy_surface, + enum ds_tizen_policy_window_screen_mode mode, + enum ds_tizen_policy_error_state state) +{ + uint32_t window_screen_mode; + uint32_t error_state; + + switch (mode) { + case DS_TIZEN_POLICY_WINDOW_SCREEN_MODE_DEFAULT: + window_screen_mode = TIZEN_POLICY_MODE_DEFAULT; + break; + case DS_TIZEN_POLICY_WINDOW_SCREEN_MODE_ALWAYS_ON: + window_screen_mode = TIZEN_POLICY_MODE_ALWAYS_ON; + break; + default: + ds_err("Not supported window_screen_mode(%d)", mode); + return; + } + + switch (state) { + case DS_TIZEN_POLICY_ERROR_STATE_NONE: + error_state = TIZEN_POLICY_ERROR_STATE_NONE; + break; + case DS_TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED: + error_state = TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED; + break; + default: + ds_err("Not supported error_state(%d)", state); + return; + } + + tizen_policy_send_window_screen_mode_done(policy_surface->client->resource, + ds_surface_get_wl_resource(policy_surface->surface), + window_screen_mode, error_state); +} + +WL_EXPORT void +ds_tizen_policy_surface_send_iconify_state_changed(struct ds_tizen_policy_surface *policy_surface, + bool iconified, bool force) +{ + tizen_policy_send_iconify_state_changed(policy_surface->client->resource, + ds_surface_get_wl_resource(policy_surface->surface), iconified, force); +} + +WL_EXPORT void +ds_tizen_policy_surface_send_supported_aux_hints(struct ds_tizen_policy_surface *policy_surface, + struct wl_array *hints, uint32_t force) +{ + // TODO: +} + +WL_EXPORT void +ds_tizen_policy_surface_send_allowed_aux_hint(struct ds_tizen_policy_surface *policy_surface, + int32_t hint_id) +{ + // TODO: +} + +WL_EXPORT void +ds_tizen_policy_surface_send_aux_message(struct ds_tizen_policy_surface *policy_surface, + const char *key, const char *value, struct wl_array *options) +{ + // TODO: +} + +WL_EXPORT void +ds_tizen_policy_surface_send_conformant_region(struct ds_tizen_policy_surface *policy_surface, + enum ds_tizen_policy_conformant_part part, bool visible, + int32_t x, int32_t y, int32_t w, int32_t h, uint32_t serial) +{ + uint32_t conformant_part; + + switch (part) { + case DS_TIZEN_POLICY_CONFORMANT_PART_INDICATOR: + conformant_part = TIZEN_POLICY_CONFORMANT_PART_INDICATOR; + break; + case DS_TIZEN_POLICY_CONFORMANT_PART_KEYBOARD: + conformant_part = TIZEN_POLICY_CONFORMANT_PART_KEYBOARD; + break; + case DS_TIZEN_POLICY_CONFORMANT_PART_CLIPBOARD: + conformant_part = TIZEN_POLICY_CONFORMANT_PART_CLIPBOARD; + break; + default: + ds_err("Not supported conformant_part(%d)", part); + return; + } + + tizen_policy_send_conformant_region(policy_surface->client->resource, + ds_surface_get_wl_resource(policy_surface->surface), conformant_part, visible, + x, y, w, h, serial); +} + +WL_EXPORT void +ds_tizen_policy_surface_send_interactive_move_done(struct ds_tizen_policy_surface *policy_surface, + int32_t x, int32_t y, uint32_t w, uint32_t h) +{ + // TODO: +} + +WL_EXPORT void +ds_tizen_policy_surface_send_interactive_resize_done(struct ds_tizen_policy_surface *policy_surface, + int32_t x, int32_t y, uint32_t w, uint32_t h) +{ + // TODO: +} + +static int32_t +tizen_policy_visibility_get_type(enum ds_tizen_policy_visibility_type type) +{ + uint32_t vis_type; + + switch (type) { + case DS_TIZEN_POLICY_VISIBILITY_TYPE_UNOBSCURED: + vis_type = TIZEN_VISIBILITY_VISIBILITY_UNOBSCURED; + break; + case DS_TIZEN_POLICY_VISIBILITY_TYPE_PARTIALLY_OBSCURED: + vis_type = TIZEN_VISIBILITY_VISIBILITY_PARTIALLY_OBSCURED; + break; + case DS_TIZEN_POLICY_VISIBILITY_TYPE_FULLY_OBSCURED: + vis_type = TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED; + break; + case DS_TIZEN_POLICY_VISIBILITY_TYPE_PRE_UNOBSCURED: + vis_type = TIZEN_VISIBILITY_VISIBILITY_PRE_UNOBSCURED; + break; + default: + ds_err("Not supported visible type (%d)", type); + vis_type = DS_TIZEN_POLICY_VISIBILITY_TYPE_UNKNOWN; + break; + } + + return vis_type; +} + +WL_EXPORT void +ds_tizen_policy_visibility_send_notify( + struct ds_tizen_policy_visibility *visibility, + enum ds_tizen_policy_visibility_type type) +{ + uint32_t vis_type; + + vis_type = tizen_policy_visibility_get_type(type); + if (vis_type == DS_TIZEN_POLICY_VISIBILITY_TYPE_UNKNOWN) + return; + + tizen_visibility_send_notify(visibility->resource, vis_type); +} + +WL_EXPORT void +ds_tizen_policy_visibility_send_changed( + struct ds_tizen_policy_visibility *visibility, + enum ds_tizen_policy_visibility_type type, uint32_t option) +{ + uint32_t vis_type; + + vis_type = tizen_policy_visibility_get_type(type); + if (vis_type == DS_TIZEN_POLICY_VISIBILITY_TYPE_UNKNOWN) + return; + + tizen_visibility_send_changed(visibility->resource, vis_type, option); +} + +WL_EXPORT void +ds_tizen_policy_position_send_changed( + struct ds_tizen_policy_position *position, int32_t x, int32_t y) +{ + tizen_position_send_changed(position->resource, x, y); +} + +WL_EXPORT struct ds_surface * +ds_tizen_policy_surface_get_surface(struct ds_tizen_policy_surface *policy_surface) +{ + return policy_surface->surface; +} + +WL_EXPORT bool +ds_tizen_policy_surface_get_conformant(struct ds_tizen_policy_surface *policy_surface) +{ + return policy_surface->conformant; +} + +WL_EXPORT int32_t +ds_tizen_policy_surface_get_opaque_state(struct ds_tizen_policy_surface *policy_surface) +{ + return policy_surface->opaque_state; +} + +WL_EXPORT bool +ds_tizen_policy_surface_get_iconified(struct ds_tizen_policy_surface *policy_surface) +{ + return policy_surface->iconified; +} + +WL_EXPORT bool +ds_tizen_policy_surface_get_floating_mode(struct ds_tizen_policy_surface *policy_surface) +{ + return policy_surface->floating_mode; +} + +WL_EXPORT enum ds_tizen_policy_stack_mode +ds_tizen_policy_surface_get_stack_mode(struct ds_tizen_policy_surface *policy_surface) +{ + return policy_surface->stack_mode; +} + +static struct ds_tizen_policy_surface * +tizen_policy_client_find_policy_surface(struct ds_tizen_policy_client *client, + struct ds_surface *surface) +{ + struct ds_tizen_policy_surface *policy_surface; + + wl_list_for_each(policy_surface, &client->policy_surfaces, link) { + if (surface == policy_surface->surface) + return policy_surface; + } + + return NULL; +} + +static struct ds_tizen_policy_surface * +tizen_policy_client_get_surface(struct wl_resource *resource, + struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_client *client; + struct ds_tizen_policy_surface *policy_surface; + struct ds_surface *surface; + + client = wl_resource_get_user_data(resource); + surface = ds_surface_from_resource(surface_resource); + + policy_surface = tizen_policy_client_find_policy_surface(client, surface); + if (policy_surface) + return policy_surface; + + policy_surface = calloc(1, sizeof *policy_surface); + if (policy_surface == NULL) { + ds_err("calloc() failed. tizen_policy"); + return NULL; + } + + policy_surface->client = client; + policy_surface->surface = surface; + wl_client_get_credentials(client->wl_client, &policy_surface->pid, &policy_surface->uid, NULL); + + wl_list_init(&policy_surface->visibilities); + wl_list_init(&policy_surface->positions); + wl_list_init(&policy_surface->subsurface_watchers); + + wl_signal_init(&policy_surface->events.destroy); + wl_signal_init(&policy_surface->events.get_visibility); + wl_signal_init(&policy_surface->events.get_position); + wl_signal_init(&policy_surface->events.activate); + wl_signal_init(&policy_surface->events.raise); + wl_signal_init(&policy_surface->events.lower); + wl_signal_init(&policy_surface->events.set_focus_skip); + wl_signal_init(&policy_surface->events.unset_focus_skip); + wl_signal_init(&policy_surface->events.set_role); + wl_signal_init(&policy_surface->events.set_window_type); + wl_signal_init(&policy_surface->events.set_conformant); + wl_signal_init(&policy_surface->events.unset_conformant); + wl_signal_init(&policy_surface->events.get_conformant); + wl_signal_init(&policy_surface->events.set_notification_level); + wl_signal_init(&policy_surface->events.set_window_screen_mode); + wl_signal_init(&policy_surface->events.get_subsurface); + wl_signal_init(&policy_surface->events.iconify); + wl_signal_init(&policy_surface->events.uniconify); + wl_signal_init(&policy_surface->events.add_aux_hint); + wl_signal_init(&policy_surface->events.change_aux_hint); + wl_signal_init(&policy_surface->events.delete_aux_hint); + wl_signal_init(&policy_surface->events.get_supported_aux_hints); + wl_signal_init(&policy_surface->events.set_floating_mode); + wl_signal_init(&policy_surface->events.unset_floating_mode); + wl_signal_init(&policy_surface->events.set_stack_mode); + wl_signal_init(&policy_surface->events.get_subsurface_watcher); + wl_signal_init(&policy_surface->events.set_parent); + wl_signal_init(&policy_surface->events.ack_conformant_region); + wl_signal_init(&policy_surface->events.set_video); + wl_signal_init(&policy_surface->events.show); + wl_signal_init(&policy_surface->events.hide); + wl_signal_init(&policy_surface->events.set_parent_with_below); + + wl_list_insert(&client->policy_surfaces, &policy_surface->link); + + struct ds_tizen_event_policy_get_surface event = { + .policy = client->policy, + .policy_surface = policy_surface, + }; + wl_signal_emit(&client->policy->events.get_surface, &event); + + return policy_surface; +} + +static void +policy_handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tizen_policy *policy; + + policy = wl_container_of(listener, policy, destroy); + + ds_inf("Global destroy: policy(%p)", policy); + + wl_signal_emit(&policy->events.destroy, policy); + + if (policy->use_security) + tizen_security_finish(); + + wl_list_remove(&policy->destroy.link); + wl_global_destroy(policy->global); + free(policy); +} + +static void +visibility_handle_destroy(struct wl_client *wl_client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct tizen_visibility_interface visibility_impl = +{ + visibility_handle_destroy, +}; + +static void +_tizen_policy_visibility_handle_destroy(struct wl_resource *resource) +{ + struct ds_tizen_policy_visibility *visibility; + + visibility = wl_resource_get_user_data(resource); + + ds_inf("_tizen_policy_visibility_handle_destroy (visibility:%p)", + visibility); + + wl_signal_emit(&visibility->events.destroy, visibility); + wl_list_remove(&visibility->link); + free(visibility); +} + +static void +policy_handle_get_visibility(struct wl_client *wl_client, struct wl_resource *resource, + uint32_t id, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + struct ds_tizen_policy_visibility *visibility; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + visibility = calloc(1, sizeof *visibility); + if (visibility == NULL) { + ds_err("calloc() failed. tizen_policy"); + return; + } + + visibility->policy_surface = policy_surface; + wl_signal_init(&visibility->events.destroy); + + wl_list_insert(&policy_surface->visibilities, &visibility->link); + + visibility->resource = wl_resource_create(wl_client, + &tizen_visibility_interface, wl_resource_get_version(resource), + id); + if (visibility->resource == NULL) { + ds_err("tizen_policy : wl_resource_create() failed."); + wl_list_remove(&visibility->link); + free(visibility); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(visibility->resource, + &visibility_impl, visibility, + _tizen_policy_visibility_handle_destroy); + + struct ds_tizen_event_policy_surface_get_visibility event = { + .policy_surface = policy_surface, + .visibility = visibility, + }; + wl_signal_emit(&policy_surface->events.get_visibility, &event); +} + +static void +position_handle_destroy(struct wl_client *wl_client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +position_handle_set(struct wl_client *wl_client, struct wl_resource *resource, + int32_t x, int32_t y) +{ + struct ds_tizen_policy_position *position; + + position = wl_resource_get_user_data(resource); + + struct ds_tizen_event_policy_position_set event = { + .position = position, + .x = x, + .y = y, + }; + wl_signal_emit(&position->events.set, &event); +} + +static const struct tizen_position_interface position_impl = +{ + position_handle_destroy, + position_handle_set, +}; + +static void +_tizen_policy_position_handle_destroy(struct wl_resource *resource) +{ + struct ds_tizen_policy_position *position; + + position = wl_resource_get_user_data(resource); + + ds_inf("_tizen_policy_position_handle_destroy (position:%p)", + position); + + wl_signal_emit(&position->events.destroy, position); + wl_list_remove(&position->link); + free(position); +} + +static void +policy_handle_get_position(struct wl_client *wl_client, struct wl_resource *resource, + uint32_t id, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + struct ds_tizen_policy_position *position; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + position = calloc(1, sizeof *position); + if (position == NULL) { + ds_err("calloc() failed. tizen_policy"); + return; + } + + position->policy_surface = policy_surface; + wl_signal_init(&position->events.destroy); + wl_signal_init(&position->events.set); + + wl_list_insert(&policy_surface->positions, &position->link); + + position->resource = wl_resource_create(wl_client, + &tizen_position_interface, wl_resource_get_version(resource), + id); + if (position->resource == NULL) { + ds_err("tizen_policy : wl_resource_create() failed."); + wl_list_remove(&position->link); + free(position); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(position->resource, + &position_impl, position, + _tizen_policy_position_handle_destroy); + + struct ds_tizen_event_policy_surface_get_position event = { + .policy_surface = policy_surface, + .position = position, + }; + wl_signal_emit(&policy_surface->events.get_position, &event); +} + +static void +policy_handle_activate(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_activate event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.activate, &event); +} + +static void +policy_handle_activate_below_by_res_id(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t universal_id, + uint32_t below_universal_id) +{ + struct ds_tizen_policy_client *client; + + client = wl_resource_get_user_data(resource); + + struct ds_tizen_event_policy_activate_below_by_univeral_id event = { + .policy = client->policy, + .universal_id = universal_id, + .below_universal_id = below_universal_id, + }; + wl_signal_emit(&client->policy->events.activate_below_by_univeral_id, &event); +} + +static void +policy_handle_raise(struct wl_client *wl_client, struct wl_resource *resource, + struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_raise event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.raise, &event); +} + +static void +policy_handle_lower(struct wl_client *wl_client, struct wl_resource *resource, + struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_lower event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.lower, &event); +} + +static void +policy_handle_lower_by_res_id(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t universal_id) +{ + struct ds_tizen_policy_client *client; + + client = wl_resource_get_user_data(resource); + + struct ds_tizen_event_policy_lower_by_universal_id event = { + .policy = client->policy, + .universal_id = universal_id, + }; + wl_signal_emit(&client->policy->events.lower_by_universal_id, &event); +} + +static void +policy_handle_set_focus_skip(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_set_focus_skip event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.set_focus_skip, &event); +} + +static void +policy_handle_unset_focus_skip(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_unset_focus_skip event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.unset_focus_skip, &event); +} + +static void +policy_handle_set_role(struct wl_client *wl_client, struct wl_resource *resource, + struct wl_resource *surface_resource, const char *role) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_set_role event = { + .policy_surface = policy_surface, + .role = role, + }; + wl_signal_emit(&policy_surface->events.set_role, &event); +} + +static void +policy_handle_set_type(struct wl_client *wl_client, struct wl_resource *resource, + struct wl_resource *surface_resource, uint32_t type) +{ + struct ds_tizen_policy_surface *policy_surface; + enum ds_tizen_policy_window_type win_type; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + switch (type) { + case TIZEN_POLICY_WIN_TYPE_NONE: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_NONE; + break; + case TIZEN_POLICY_WIN_TYPE_TOPLEVEL: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_TOPLEVEL; + break; + case TIZEN_POLICY_WIN_TYPE_FULLSCREEN: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_FULLLSCREEN; + break; + case TIZEN_POLICY_WIN_TYPE_MAXIMIZED: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_MAXIMIZED; + break; + case TIZEN_POLICY_WIN_TYPE_TRANSIENT: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_TRANSIENT; + break; + case TIZEN_POLICY_WIN_TYPE_MENU: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_MENU; + break; + case TIZEN_POLICY_WIN_TYPE_DND: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_DND; + break; + case TIZEN_POLICY_WIN_TYPE_CUSTOM: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_CUSTOM; + break; + case TIZEN_POLICY_WIN_TYPE_NOTIFICATION: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_NOTIFICATION; + break; + case TIZEN_POLICY_WIN_TYPE_UTILITY: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_UTILITY; + break; + case TIZEN_POLICY_WIN_TYPE_DIALOG: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_DIALOG; + break; + case TIZEN_POLICY_WIN_TYPE_DOCK: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_DOCK; + break; + case TIZEN_POLICY_WIN_TYPE_SPLASH: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_SPLASH; + break; + case TIZEN_POLICY_WIN_TYPE_DESKTOP: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_DESKTOP; + break; + default: + win_type = DS_TIZEN_POLICY_WINDOW_TYPE_NONE; + break; + } + + struct ds_tizen_event_policy_surface_set_window_type event = { + .policy_surface = policy_surface, + .win_type = win_type, + }; + wl_signal_emit(&policy_surface->events.set_window_type, &event); +} + +static void +policy_handle_set_conformant(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + if (!policy_surface->conformant) + policy_surface->conformant = true; + + struct ds_tizen_event_policy_surface_set_conformant event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.set_conformant, &event); +} + +static void +policy_handle_unset_conformant(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + if (policy_surface->conformant) + policy_surface->conformant = false; + + struct ds_tizen_event_policy_surface_unset_conformant event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.unset_conformant, &event); +} + +static void +policy_handle_get_conformant(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_get_conformant event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.get_conformant, &event); +} + +static void +policy_handle_set_notification_level(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + int32_t level) +{ + struct ds_tizen_policy_surface *policy_surface; + enum ds_tizen_policy_notification_level noti_level; + bool ret; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + ret = tizen_security_check_privilege(policy_surface->pid, policy_surface->uid, + TIZEN_POLICY_PRIVILEGE_SET_NOTIFICATION_LEVEL); + if (ret == false) { + ds_err("tizen_security_check_privilege() failed. " + "Privilege Denied on set_notification_level."); + + tizen_policy_send_notification_done(resource, surface_resource, + -1, TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED); + + return; + } + + switch (level) { + case TIZEN_POLICY_LEVEL_1: + noti_level = DS_TIZEN_POLICY_NOTIFICATION_LEVEL_1; + break; + case TIZEN_POLICY_LEVEL_2: + noti_level = DS_TIZEN_POLICY_NOTIFICATION_LEVEL_2; + break; + case TIZEN_POLICY_LEVEL_3: + noti_level = DS_TIZEN_POLICY_NOTIFICATION_LEVEL_3; + break; + case TIZEN_POLICY_LEVEL_NONE: + noti_level = DS_TIZEN_POLICY_NOTIFICATION_LEVEL_NONE; + break; + case TIZEN_POLICY_LEVEL_DEFAULT: + noti_level = DS_TIZEN_POLICY_NOTIFICATION_LEVEL_DEFAULT; + break; + case TIZEN_POLICY_LEVEL_MEDIUM: + noti_level = DS_TIZEN_POLICY_NOTIFICATION_LEVEL_MEDIUM; + break; + case TIZEN_POLICY_LEVEL_HIGH: + noti_level = DS_TIZEN_POLICY_NOTIFICATION_LEVEL_HIGH; + break; + case TIZEN_POLICY_LEVEL_TOP: + noti_level = DS_TIZEN_POLICY_NOTIFICATION_LEVEL_TOP; + break; + default: + noti_level = DS_TIZEN_POLICY_NOTIFICATION_LEVEL_NONE; + break; + } + + struct ds_tizen_event_policy_surface_set_notification_level event = { + .policy_surface = policy_surface, + .level = noti_level, + }; + wl_signal_emit(&policy_surface->events.set_notification_level, &event); +} + +static void +policy_handle_set_transient_for(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t child_id, uint32_t parent_id) +{ + struct ds_tizen_policy_client *client; + + client = wl_resource_get_user_data(resource); + + struct ds_tizen_event_policy_set_transient_for event = { + .policy = client->policy, + .child_universal_id = child_id, + .parent_universal_id = parent_id, + }; + wl_signal_emit(&client->policy->events.set_transient_for, &event); + + tizen_policy_send_transient_for_done(resource, child_id); +} + +static void +policy_handle_unset_transient_for(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t child_id) +{ + struct ds_tizen_policy_client *client; + + client = wl_resource_get_user_data(resource); + + struct ds_tizen_event_policy_unset_transient_for event = { + .policy = client->policy, + .child_universal_id = child_id, + }; + wl_signal_emit(&client->policy->events.unset_transient_for, &event); +} + +static void +policy_handle_set_window_screen_mode(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + uint32_t mode) +{ + struct ds_tizen_policy_surface *policy_surface; + enum ds_tizen_policy_window_screen_mode screen_mode; + bool ret; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + ret = tizen_security_check_privilege(policy_surface->pid, policy_surface->uid, + TIZEN_POLICY_PRIVILEGE_SET_SCREEN_MODE); + if (ret == false) { + ds_err("tizen_security_check_privilege() failed. " + "Privilege Denied on set_window_screen_mode."); + + tizen_policy_send_notification_done(resource, surface_resource, + -1, TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED); + + return; + } + + switch (mode) { + case TIZEN_POLICY_MODE_DEFAULT: + screen_mode = DS_TIZEN_POLICY_WINDOW_SCREEN_MODE_DEFAULT; + break; + case TIZEN_POLICY_MODE_ALWAYS_ON: + screen_mode = DS_TIZEN_POLICY_WINDOW_SCREEN_MODE_ALWAYS_ON; + break; + default: + screen_mode = DS_TIZEN_POLICY_WINDOW_SCREEN_MODE_DEFAULT; + break; + } + + struct ds_tizen_event_policy_surface_set_window_screen_mode event = { + .policy_surface = policy_surface, + .mode = screen_mode, + }; + wl_signal_emit(&policy_surface->events.set_window_screen_mode, &event); +} + +static void +policy_handle_place_subsurface_below_parent(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *subsurface_resource) +{ + struct ds_tizen_policy_client *client; + struct ds_subsurface *subsurface; + + client = wl_resource_get_user_data(resource); + subsurface = ds_subsurface_from_resource(subsurface_resource); + + struct ds_tizen_event_policy_place_subsurface_below_parent event = { + .policy = client->policy, + .subsurface = subsurface, + }; + wl_signal_emit( + &client->policy->events.place_subsurface_below_parent, + &event); +} + +static void +policy_handle_set_subsurface_stand_alone(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *subsurface_resource) +{ + struct ds_tizen_policy_client *client; + struct ds_subsurface *subsurface; + + client = wl_resource_get_user_data(resource); + subsurface = ds_subsurface_from_resource(subsurface_resource); + + struct ds_tizen_event_policy_set_subsurface_stand_alone event = { + .policy = client->policy, + .subsurface = subsurface, + }; + wl_signal_emit( + &client->policy->events.set_subsurface_stand_alone, + &event); +} + +static void +policy_handle_get_subsurface(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t id, + struct wl_resource *surface_resource, uint32_t parent_id) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + // TODO: How to create the ds_subsurface with a parent_universal_id. + + struct ds_tizen_event_policy_surface_get_subsurface event = { + .policy_surface = policy_surface, + .parent_universal_id = parent_id, + }; + wl_signal_emit(&policy_surface->events.get_subsurface, &event); +} + +static void +policy_handle_set_opaque_state(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + int32_t state) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + if (policy_surface->opaque_state != state) + policy_surface->opaque_state = state; +} + +static void +policy_handle_iconify(struct wl_client *wl_client, struct wl_resource *resource, + struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + if (!policy_surface->iconified) + policy_surface->iconified = true; + + struct ds_tizen_event_policy_surface_iconify event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.iconify, &event); +} + +static void +policy_handle_uniconify(struct wl_client *wl_client, struct wl_resource *resource, + struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + if (policy_surface->iconified) + policy_surface->iconified = false; + + struct ds_tizen_event_policy_surface_uniconify event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.uniconify, &event); +} + +static void +policy_handle_add_aux_hint(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + int32_t id, const char *name, const char *value) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_add_aux_hint event = { + .policy_surface = policy_surface, + .id = id, + .name = name, + .value = value, + }; + wl_signal_emit(&policy_surface->events.add_aux_hint, &event); +} + +static void +policy_handle_change_aux_hint(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + int32_t id, const char *value) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_change_aux_hint event = { + .policy_surface = policy_surface, + .id = id, + .value = value, + }; + wl_signal_emit(&policy_surface->events.change_aux_hint, &event); +} + +static void +policy_handle_delete_aux_hint(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + int32_t id) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_delete_aux_hint event = { + .policy_surface = policy_surface, + .id = id, + }; + wl_signal_emit(&policy_surface->events.delete_aux_hint, &event); +} + +static void +policy_handle_get_supported_aux_hints(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_get_supported_aux_hints event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.get_supported_aux_hints, &event); +} + +static void +policy_handle_set_background_state(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t pid) +{ + struct ds_tizen_policy_client *client; + struct ds_tizen_policy *policy; + + client = wl_resource_get_user_data(resource); + policy = client->policy; + + wl_list_for_each(client, &policy->clients, link) { + if (pid == client->pid) { + struct ds_tizen_event_policy_set_background_state event = { + .policy = client->policy, + .pid = pid, + }; + wl_signal_emit(&client->policy->events.set_background_state, &event); + } + } +} + +static void +policy_handle_unset_background_state(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t pid) +{ + struct ds_tizen_policy_client *client; + struct ds_tizen_policy *policy; + + client = wl_resource_get_user_data(resource); + policy = client->policy; + + wl_list_for_each(client, &policy->clients, link) { + if (pid == client->pid) { + struct ds_tizen_event_policy_unset_background_state event = { + .policy = client->policy, + .pid = pid, + }; + wl_signal_emit(&client->policy->events.unset_background_state, &event); + } + } +} + +static void +policy_handle_set_floating_mode(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + if (policy_surface->floating_mode == false) + return; + + policy_surface->floating_mode = false; + + struct ds_tizen_event_policy_surface_set_floating_mode event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.set_floating_mode, &event); +} + +static void +policy_handle_unset_floating_mode(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + if (policy_surface->floating_mode == false) + return; + + policy_surface->floating_mode = false; + + struct ds_tizen_event_policy_surface_unset_floating_mode event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.unset_floating_mode, &event); +} + +static void +policy_handle_set_stack_mode(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + uint32_t mode) +{ + struct ds_tizen_policy_surface *policy_surface; + enum ds_tizen_policy_stack_mode stack_mode; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + switch (mode) { + case TIZEN_POLICY_STACK_MODE_ABOVE: + stack_mode = DS_TIZEN_POLICY_STACK_MODE_ABOVE; + break; + case TIZEN_POLICY_STACK_MODE_BELOW: + stack_mode = DS_TIZEN_POLICY_STACK_MODE_BELOW; + break; + default: + stack_mode = DS_TIZEN_POLICY_STACK_MODE_NONE; + break; + } + + if (policy_surface->stack_mode == stack_mode) + return; + + policy_surface->stack_mode = stack_mode; + + struct ds_tizen_event_policy_surface_set_stack_mode event = { + .policy_surface = policy_surface, + .mode = stack_mode, + }; + wl_signal_emit(&policy_surface->events.set_stack_mode, &event); +} + +static void +policy_handle_activate_above_by_res_id(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t universal_id, + uint32_t above_universal_id) +{ + struct ds_tizen_policy_client *client; + + client = wl_resource_get_user_data(resource); + + struct ds_tizen_event_policy_activate_above_by_universal_id event = { + .policy = client->policy, + .universal_id = universal_id, + .above_universal_id = above_universal_id, + }; + wl_signal_emit(&client->policy->events.activate_above_by_universal_id, &event); +} + +static void +subsurface_watcher_handle_destroy(struct wl_client *wl_client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct tizen_subsurface_watcher_interface subsurface_watcher_impl = +{ + subsurface_watcher_handle_destroy, +}; + +static void +_tizen_policy_subsurface_watcher_handle_destroy(struct wl_resource *resource) +{ + struct ds_tizen_policy_subsurface_watcher *subsurface_watcher; + + subsurface_watcher = wl_resource_get_user_data(resource); + + ds_inf("_tizen_policy_subsurface_watcher_handle_destroy (subsurface_watcher:%p)", + subsurface_watcher); + + wl_signal_emit(&subsurface_watcher->events.destroy, subsurface_watcher); + free(subsurface_watcher); +} + +static void +policy_handle_get_subsurface_watcher(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t id, + struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + struct ds_tizen_policy_subsurface_watcher *subsurface_watcher; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + subsurface_watcher = calloc(1, sizeof *subsurface_watcher); + if (!subsurface_watcher) { + ds_err("calloc() failed. tizen_policy"); + return; + } + + subsurface_watcher->policy_surface = policy_surface; + wl_signal_init(&subsurface_watcher->events.destroy); + + wl_list_insert(&policy_surface->subsurface_watchers, &subsurface_watcher->link); + + subsurface_watcher->resource = wl_resource_create(wl_client, + &tizen_subsurface_watcher_interface, wl_resource_get_version(resource), + id); + if (subsurface_watcher->resource == NULL) { + ds_err("tizen_policy : wl_resource_create() failed."); + free(subsurface_watcher); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(subsurface_watcher->resource, + &subsurface_watcher_impl, subsurface_watcher, + _tizen_policy_subsurface_watcher_handle_destroy); + + struct ds_tizen_event_policy_surface_get_subsurface_watcher event = { + .policy_surface = policy_surface, + .subsurface_watcher = subsurface_watcher, + }; + wl_signal_emit(&policy_surface->events.get_subsurface_watcher, &event); +} + +static void +policy_handle_set_parent(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + struct wl_resource *parent_surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + struct ds_surface *parent_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + parent_surface = ds_surface_from_resource(parent_surface_resource); + + struct ds_tizen_event_policy_surface_set_parent event = { + .policy_surface = policy_surface, + .parent_surface = parent_surface, + }; + wl_signal_emit(&policy_surface->events.set_parent, &event); +} + +static void +policy_handle_ack_conformant_region(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + uint32_t serial) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_ack_conformant_region event = { + .policy_surface = policy_surface, + .serial = serial, + }; + wl_signal_emit(&policy_surface->events.ack_conformant_region, &event); +} + +static void +policy_handle_destroy(struct wl_client *wl_client, struct wl_resource *resource) +{ + struct ds_tizen_policy_client *client; + + client = wl_resource_get_user_data(resource); + + if (!wl_list_empty(&client->policy_surfaces)) { + ds_err("tizen_policy was destroyed before children"); + return; + } + + wl_resource_destroy(resource); +} + +static void +policy_handle_has_video(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + uint32_t has) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + if (policy_surface->video == has) + return; + + policy_surface->video = has; + + struct ds_tizen_event_policy_surface_set_video event = { + .policy_surface = policy_surface, + .video = has, + }; + wl_signal_emit(&policy_surface->events.set_video, &event); +} + +static void +policy_handle_set_appid(struct wl_client *wl_client, + struct wl_resource *resource, int32_t pid, const char *appid) +{ + struct ds_tizen_policy_client *client; + + client = wl_resource_get_user_data(resource); + + struct ds_tizen_event_policy_set_appid event = { + .policy = client->policy, + .pid = pid, + .appid = appid, + }; + wl_signal_emit(&client->policy->events.set_appid, &event); +} + +static void +policy_handle_show(struct wl_client *wl_client, struct wl_resource *resource, + struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_show event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.show, &event); +} + +static void +policy_handle_hide(struct wl_client *wl_client, struct wl_resource *resource, + struct wl_resource *surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + struct ds_tizen_event_policy_surface_hide event = { + .policy_surface = policy_surface, + }; + wl_signal_emit(&policy_surface->events.hide, &event); +} + +static void +policy_handle_set_transient_for_below(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t universal_id, + uint32_t parent_universal_id) +{ + struct ds_tizen_policy_client *client; + + client = wl_resource_get_user_data(resource); + + struct ds_tizen_event_policy_set_transient_for_below event = { + .policy = client->policy, + .universal_id = universal_id, + .parent_universal_id = parent_universal_id, + }; + wl_signal_emit(&client->policy->events.set_transient_for_below, &event); +} + +static void +policy_handle_set_parent_with_below(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource, + struct wl_resource *parent_surface_resource) +{ + struct ds_tizen_policy_surface *policy_surface; + struct ds_surface *parent_surface; + + policy_surface = tizen_policy_client_get_surface(resource, surface_resource); + if (policy_surface == NULL) { + ds_err("tizen_policy_client_get_surface() failed."); + wl_client_post_no_memory(wl_client); + return; + } + + parent_surface = ds_surface_from_resource(parent_surface_resource); + + struct ds_tizen_event_policy_surface_set_parent_with_below event = { + .policy_surface = policy_surface, + .parent_surface = parent_surface, + }; + wl_signal_emit(&policy_surface->events.set_parent_with_below, &event); +} + +static const struct tizen_policy_interface policy_impl = +{ + policy_handle_get_visibility, + policy_handle_get_position, + policy_handle_activate, + policy_handle_activate_below_by_res_id, + policy_handle_raise, + policy_handle_lower, + policy_handle_lower_by_res_id, + policy_handle_set_focus_skip, + policy_handle_unset_focus_skip, + policy_handle_set_role, + policy_handle_set_type, + policy_handle_set_conformant, + policy_handle_unset_conformant, + policy_handle_get_conformant, + policy_handle_set_notification_level, + policy_handle_set_transient_for, + policy_handle_unset_transient_for, + policy_handle_set_window_screen_mode, + policy_handle_place_subsurface_below_parent, + policy_handle_set_subsurface_stand_alone, + policy_handle_get_subsurface, + policy_handle_set_opaque_state, + policy_handle_iconify, + policy_handle_uniconify, + policy_handle_add_aux_hint, + policy_handle_change_aux_hint, + policy_handle_delete_aux_hint, + policy_handle_get_supported_aux_hints, + policy_handle_set_background_state, + policy_handle_unset_background_state, + policy_handle_set_floating_mode, + policy_handle_unset_floating_mode, + policy_handle_set_stack_mode, + policy_handle_activate_above_by_res_id, + policy_handle_get_subsurface_watcher, + policy_handle_set_parent, + policy_handle_ack_conformant_region, + policy_handle_destroy, + policy_handle_has_video, + policy_handle_set_appid, + policy_handle_show, + policy_handle_hide, + policy_handle_set_transient_for_below, + policy_handle_set_parent_with_below, +}; + +static void +_tizen_policy_client_handle_destroy(struct wl_resource *resource) +{ + struct ds_tizen_policy_client *client; + struct ds_tizen_policy_surface *policy_surface, *tmp; + + client = wl_resource_get_user_data(resource); + + ds_inf("_tizen_policy_client_handle_destroy (client:%p)", client); + + wl_list_for_each_safe(policy_surface, tmp, &client->policy_surfaces, link) { + wl_signal_emit(&policy_surface->events.destroy, policy_surface); + wl_list_remove(&policy_surface->link); + free(policy_surface); + } + + wl_list_remove(&client->link); + free(client); +} + +static void +policy_bind(struct wl_client *wl_client, void *data, uint32_t version, + uint32_t id) +{ + struct ds_tizen_policy *policy = data; + struct ds_tizen_policy_client *client; + + client = calloc(1, sizeof *client); + if (client == NULL) { + ds_err("calloc() failed. tizen_policy"); + wl_client_post_no_memory(wl_client); + return; + } + + ds_inf("tizen_policy_client binds. (client:%p)", client); + + client->policy = policy; + client->wl_client = wl_client; + wl_client_get_credentials(client->wl_client, &client->pid, &client->uid, NULL); + + wl_list_init(&client->policy_surfaces); + + client->resource = wl_resource_create(wl_client, &tizen_policy_interface, + MIN(version, TIZEN_POLICY_VERSION), id); + + if (client->resource == NULL) { + ds_err("tizen_policy : wl_resource_create() failed."); + free(client); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(client->resource, &policy_impl, client, + _tizen_policy_client_handle_destroy); + + wl_list_insert(&policy->clients, &client->link); +} -- 2.7.4 From a19d23162d919defba77e0be189803d68de51fb3 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Sun, 28 Aug 2022 13:05:36 +0900 Subject: [PATCH 15/16] add testcases for ds_tizen_policy Change-Id: Ia93e8f7caf52713beaf6dd175f2443337252266e --- packaging/libds-tizen.spec | 1 + tests/meson.build | 20 + tests/tc_policy.cpp | 2989 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 3010 insertions(+) create mode 100644 tests/tc_policy.cpp diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 1ef64cc..e1d4c25 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -630,3 +630,4 @@ ninja -C builddir install %{_includedir}/libds-tizen/policy.h %{_libdir}/pkgconfig/libds-tizen-policy.pc %{_libdir}/libds-tizen-policy.so +%{_bindir}/libds-tizen-policy-tests diff --git a/tests/meson.build b/tests/meson.build index 1b78a64..030c3b0 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -304,3 +304,23 @@ executable('libds-tizen-hwc-tests', install_dir: libds_tizen_bindir, install : true ) + +## policy tests +tc_policy_files = [ + 'tc_main.cpp', + 'tc_policy.cpp', +] + +executable('libds-tizen-policy-tests', + [ + tc_mock_files, + tc_policy_files + ], + dependencies: [ + deps_test_common, + deps_libds_tizen_policy, + dependency('tizen-extension-client', required: true), + ], + install_dir: libds_tizen_bindir, + install : true +) diff --git a/tests/tc_policy.cpp b/tests/tc_policy.cpp new file mode 100644 index 0000000..e099014 --- /dev/null +++ b/tests/tc_policy.cpp @@ -0,0 +1,2989 @@ +#include "tc_main.h" +#include "mockclient.h" +#include "mockcompositor.h" +#include +#include + +#define TIZEN_POLICY_VERSION 11 + +class MockPolicyVisibility +{ +public: + MockPolicyVisibility() + : mVisibility(nullptr) + {} + MockPolicyVisibility(struct ds_tizen_policy_visibility *visibility) + : mVisibility(visibility) + { + ds_inf("%s", __func__); + + // policy_surface destroy listener + mDestroyListener.notify = MockPolicyVisibility::DestroyCallback; + mDestroyListener.parent = this; + ds_tizen_policy_visibility_add_destroy_listener(visibility, &mDestroyListener); + } + ~MockPolicyVisibility() + { + ds_inf("%s", __func__); + + if (mDestroyListener.notify) { + wl_list_remove(&mDestroyListener.link); + mDestroyListener.notify = nullptr; + } + } + + static void DestroyCallback(struct wl_listener *listener, void *data) + { + MockPolicyVisibility *policyVisibility = + reinterpret_cast(listener)->parent; + struct ds_tizen_policy_visibility *visibility = + static_cast(data); + + ds_inf("%s: policyVisibility(%p), visibility(%p)", __func__, + policyVisibility, visibility); + + wl_list_remove(&policyVisibility->mDestroyListener.link); + policyVisibility->mDestroyListener.notify = nullptr; + + policyVisibility->bDestroyed = true; + } + + void SendNotify(enum ds_tizen_policy_visibility_type type) + { + ds_tizen_policy_visibility_send_notify(mVisibility, type); + } + + void SendChanged(enum ds_tizen_policy_visibility_type type, uint32_t option) + { + ds_tizen_policy_visibility_send_changed(mVisibility, type, option); + } + +public: + bool bDestroyed; + +private: + struct ds_tizen_policy_visibility *mVisibility; + + struct DestroyListener : ::wl_listener { + MockPolicyVisibility *parent; + }; + DestroyListener mDestroyListener; +}; + +class MockPolicyPosition +{ +public: + MockPolicyPosition() + : mX(-1), + mY(-1), + mPosition(nullptr) + {} + MockPolicyPosition(struct ds_tizen_policy_position *position) + : mX(-1), + mY(-1), + mPosition(position) + { + ds_inf("%s", __func__); + + // policy_surface destroy listener + mDestroyListener.notify = MockPolicyPosition::DestroyCallback; + mDestroyListener.parent = this; + ds_tizen_policy_position_add_destroy_listener(position, &mDestroyListener); + + // position listener + mSetListener.notify = MockPolicyPosition::SetCallback; + mSetListener.parent = this; + ds_tizen_policy_position_add_set_listener(position, &mSetListener); + } + ~MockPolicyPosition() + { + ds_inf("%s", __func__); + + if (mSetListener.notify) { + wl_list_remove(&mSetListener.link); + mSetListener.notify = nullptr; + } + + if (mDestroyListener.notify) { + wl_list_remove(&mDestroyListener.link); + mDestroyListener.notify = nullptr; + } + } + + static void DestroyCallback(struct wl_listener *listener, void *data) + { + MockPolicyPosition *policyPosition = + reinterpret_cast(listener)->parent; + struct ds_tizen_policy_position *position = + static_cast(data); + + ds_inf("%s: policyPosition(%p), position(%p)", __func__, + policyPosition, position); + + wl_list_remove(&policyPosition->mSetListener.link); + policyPosition->mSetListener.notify = nullptr; + + wl_list_remove(&policyPosition->mDestroyListener.link); + policyPosition->mDestroyListener.notify = nullptr; + + policyPosition->bDestroyed = true; + } + + static void SetCallback(struct wl_listener *listener, void *data) + { + MockPolicyPosition *mockPosition = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_position_set *event = + static_cast(data); + + EXPECT_TRUE(mockPosition->mPosition == event->position); + mockPosition->mX = event->x; + mockPosition->mY = event->y; + } + + void SendChanged(int32_t x, int32_t y) + { + ds_tizen_policy_position_send_changed(mPosition, x, y); + mX = x; + mY = y; + } + +public: + bool bDestroyed; + + int32_t mX; + int32_t mY; + +private: + struct ds_tizen_policy_position *mPosition; + + struct DestroyListener : ::wl_listener { + MockPolicyPosition *parent; + }; + DestroyListener mDestroyListener; + + struct SetListener : ::wl_listener { + MockPolicyPosition *parent; + }; + SetListener mSetListener; +}; + +class MockPolicySubsurfaceWatcher +{ +public: + MockPolicySubsurfaceWatcher() + : mSubsurfaceWatcher(nullptr) + {} + MockPolicySubsurfaceWatcher(struct ds_tizen_policy_subsurface_watcher *subsurface_watcher) + : mSubsurfaceWatcher(subsurface_watcher) + { + ds_inf("%s", __func__); + + // policy_surface destroy listener + mDestroyListener.notify = MockPolicySubsurfaceWatcher::DestroyCallback; + mDestroyListener.parent = this; + ds_tizen_policy_subsurface_watcher_add_destroy_listener(subsurface_watcher, &mDestroyListener); + } + ~MockPolicySubsurfaceWatcher() + { + ds_inf("%s", __func__); + + if (mDestroyListener.notify) { + wl_list_remove(&mDestroyListener.link); + mDestroyListener.notify = nullptr; + } + } + + static void DestroyCallback(struct wl_listener *listener, void *data) + { + MockPolicySubsurfaceWatcher *policySubsurfaceWatcher = + reinterpret_cast(listener)->parent; + struct ds_tizen_policy_subsurface_watcher *subsurface_watcher = + static_cast(data); + + ds_inf("%s: policySubsurfaceWatcher(%p), subsurface_watcher(%p)", __func__, + policySubsurfaceWatcher, subsurface_watcher); + + wl_list_remove(&policySubsurfaceWatcher->mDestroyListener.link); + policySubsurfaceWatcher->mDestroyListener.notify = nullptr; + + policySubsurfaceWatcher->bDestroyed = true; + } + +#if 0 // TODO: + void SendMessage(enum ds_tizen_policy_subsurface_watcher_message message) + { + ds_tizen_policy_subsurface_watcher_send_message(mSubsurfaceWatcher, message); + } +#endif + +public: + bool bDestroyed; + +private: + struct ds_tizen_policy_subsurface_watcher *mSubsurfaceWatcher; + + struct DestroyListener : ::wl_listener { + MockPolicySubsurfaceWatcher *parent; + }; + DestroyListener mDestroyListener; +}; + +class MockPolicySurface +{ +public: + MockPolicySurface(struct ds_tizen_policy_surface *policy_surface) + : mPolicySurface(policy_surface), + mPolicyVisibility(nullptr), + mPolicyPosition(nullptr), + mPolicySubsurfaceWatcher(nullptr) + { + ds_inf("%s", __func__); + + // policy_surface destroy listener + mDestroyListener.notify = MockPolicySurface::DestroyCallback; + mDestroyListener.parent = this; + ds_tizen_policy_surface_add_destroy_listener(policy_surface, &mDestroyListener); + + // policy_surface listeners + mGetVisibilityListener.notify = MockPolicySurface::GetVisibilityCallback; + mGetVisibilityListener.parent = this; + ds_tizen_policy_surface_add_get_visibility_listener(policy_surface, + &mGetVisibilityListener); + + mGetPositionListener.notify = MockPolicySurface::GetPositionCallback; + mGetPositionListener.parent = this; + ds_tizen_policy_surface_add_get_position_listener(policy_surface, + &mGetPositionListener); + + mActivateListener.notify = MockPolicySurface::ActivateCallback; + mActivateListener.parent = this; + ds_tizen_policy_surface_add_activate_listener(policy_surface, + &mActivateListener); + + mRaiseListener.notify = MockPolicySurface::RaiseCallback; + mRaiseListener.parent = this; + ds_tizen_policy_surface_add_raise_listener(policy_surface, + &mRaiseListener); + + mLowerListener.notify = MockPolicySurface::LowerCallback; + mLowerListener.parent = this; + ds_tizen_policy_surface_add_lower_listener(policy_surface, + &mLowerListener); + + mSetFocusSkipListener.notify = MockPolicySurface::SetFocusSkipCallback; + mSetFocusSkipListener.parent = this; + ds_tizen_policy_surface_add_set_focus_skip_listener(policy_surface, + &mSetFocusSkipListener); + + mUnsetFocusSkipListener.notify = MockPolicySurface::UnsetFocusSkipCallback; + mUnsetFocusSkipListener.parent = this; + ds_tizen_policy_surface_add_unset_focus_skip_listener(policy_surface, + &mUnsetFocusSkipListener); + + mSetRoleListener.notify = MockPolicySurface::SetRoleCallback; + mSetRoleListener.parent = this; + ds_tizen_policy_surface_add_set_role_listener(policy_surface, + &mSetRoleListener); + + mWindowTypeListener.notify = MockPolicySurface::WindowTypeCallback; + mWindowTypeListener.parent = this; + ds_tizen_policy_surface_add_set_window_type_listener(policy_surface, + &mWindowTypeListener); + + mSetConformantListener.notify = MockPolicySurface::SetConformantCallback; + mSetConformantListener.parent = this; + ds_tizen_policy_surface_add_set_conformant_listener(policy_surface, + &mSetConformantListener); + + mUnsetConformantListener.notify = MockPolicySurface::UnsetConformantCallback; + mUnsetConformantListener.parent = this; + ds_tizen_policy_surface_add_unset_conformant_listener(policy_surface, + &mUnsetConformantListener); + + mGetConformantListener.notify = MockPolicySurface::GetConformantCallback; + mGetConformantListener.parent = this; + ds_tizen_policy_surface_add_get_conformant_listener(policy_surface, + &mGetConformantListener); + + mSetNotificationLevelListener.notify = MockPolicySurface::SetNotificationLevelCallback; + mSetNotificationLevelListener.parent = this; + ds_tizen_policy_surface_add_set_notification_level_listener(policy_surface, + &mSetNotificationLevelListener); + + mSetWindowScreenModeListener.notify = MockPolicySurface::SetWindowScreenModeCallback; + mSetWindowScreenModeListener.parent = this; + ds_tizen_policy_surface_add_set_window_screen_mode_listener(policy_surface, + &mSetWindowScreenModeListener); + + mGetSubsurfaceListener.notify = MockPolicySurface::GetSubsurfaceCallback; + mGetSubsurfaceListener.parent = this; + ds_tizen_policy_surface_add_get_subsurface_listener(policy_surface, + &mGetSubsurfaceListener); + + mIconifyListener.notify = MockPolicySurface::IconifyCallback; + mIconifyListener.parent = this; + ds_tizen_policy_surface_add_iconify_listener(policy_surface, + &mIconifyListener); + + mUniconifyListener.notify = MockPolicySurface::UniconifyCallback; + mUniconifyListener.parent = this; + ds_tizen_policy_surface_add_uniconify_listener(policy_surface, + &mUniconifyListener); + + mAddAuxHintListener.notify = MockPolicySurface::AddAuxHintCallback; + mAddAuxHintListener.parent = this; + ds_tizen_policy_surface_add_add_aux_hint_listener(policy_surface, + &mAddAuxHintListener); + + mChangeAuxHintListener.notify = MockPolicySurface::ChangeAuxHintCallback; + mChangeAuxHintListener.parent = this; + ds_tizen_policy_surface_add_change_aux_hint_listener(policy_surface, + &mChangeAuxHintListener); + + mDeleteAuxHintListener.notify = MockPolicySurface::DeleteAuxHintCallback; + mDeleteAuxHintListener.parent = this; + ds_tizen_policy_surface_add_delete_aux_hint_listener(policy_surface, + &mDeleteAuxHintListener); + + mGetSupportAuxHintsListener.notify = MockPolicySurface::GetSupportAuxHintsCallback; + mGetSupportAuxHintsListener.parent = this; + ds_tizen_policy_surface_add_get_supported_aux_hints_listener(policy_surface, + &mGetSupportAuxHintsListener); + + mSetFloatingModeListener.notify = MockPolicySurface::SetFloatingModeCallback; + mSetFloatingModeListener.parent = this; + ds_tizen_policy_surface_add_set_floating_mode_listener(policy_surface, + &mSetFloatingModeListener); + + mUnsetFloatingModeListener.notify = MockPolicySurface::UnsetFloatingModeCallback; + mUnsetFloatingModeListener.parent = this; + ds_tizen_policy_surface_add_unset_floating_mode_listener(policy_surface, + &mUnsetFloatingModeListener); + + mSetStackModeListener.notify = MockPolicySurface::SetStackModeCallback; + mSetStackModeListener.parent = this; + ds_tizen_policy_surface_add_set_stack_mode_listener(policy_surface, + &mSetStackModeListener); + + mGetSubsurfaceWatcherListener.notify = MockPolicySurface::GetSubsurfaceWatcherCallback; + mGetSubsurfaceWatcherListener.parent = this; + ds_tizen_policy_surface_add_get_subsurface_watcher_listener(policy_surface, + &mGetSubsurfaceWatcherListener); + + mSetParentListener.notify = MockPolicySurface::SetParentCallback; + mSetParentListener.parent = this; + ds_tizen_policy_surface_add_set_parent_listener(policy_surface, + &mSetParentListener); + + mAckConformantRegionListener.notify = MockPolicySurface::AckConformantRegionCallback; + mAckConformantRegionListener.parent = this; + ds_tizen_policy_surface_add_ack_conformant_region_listener(policy_surface, + &mAckConformantRegionListener); + + mSetVideoListener.notify = MockPolicySurface::SetVideoCallback; + mSetVideoListener.parent = this; + ds_tizen_policy_surface_add_set_video_listener(policy_surface, + &mSetVideoListener); + + mShowListener.notify = MockPolicySurface::ShowCallback; + mShowListener.parent = this; + ds_tizen_policy_surface_add_show_listener(policy_surface, + &mShowListener); + + mHideListener.notify = MockPolicySurface::HideCallback; + mHideListener.parent = this; + ds_tizen_policy_surface_add_hide_listener(policy_surface, + &mHideListener); + + mSetParentWithBelowListener.notify = MockPolicySurface::SetParentWithBelowCallback; + mSetParentWithBelowListener.parent = this; + ds_tizen_policy_surface_add_set_parent_with_below_listener(policy_surface, + &mSetParentWithBelowListener); + } + ~MockPolicySurface() + { + ds_inf("%s", __func__); + + if (mGetVisibilityListener.notify) { + wl_list_remove(&mGetVisibilityListener.link); + mGetVisibilityListener.notify = nullptr; + } + + if (mDestroyListener.notify) { + wl_list_remove(&mDestroyListener.link); + mDestroyListener.notify = nullptr; + } + + if (mPolicySubsurfaceWatcher) + delete mPolicySubsurfaceWatcher; + + if (mPolicyPosition) + delete mPolicyPosition; + + if (mPolicyVisibility) + delete mPolicyVisibility; + } + + static void DestroyCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_policy_surface *policy_surface = + static_cast(data); + + ds_inf("%s: policySurface(%p), policy_surface(%p)", __func__, policySurface, policy_surface); + + wl_list_remove(&policySurface->mDestroyListener.link); + policySurface->mDestroyListener.notify = nullptr; + + policySurface->bDestroyed = true; + } + + static void GetVisibilityCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_get_visibility *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + EXPECT_TRUE(event->visibility != NULL); + + policySurface->bGetVisibility = true; + + MockPolicyVisibility *policyVisibility = + new MockPolicyVisibility(event->visibility); + + policySurface->mPolicyVisibility = policyVisibility; + } + + static void GetPositionCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_get_position *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + EXPECT_TRUE(event->position != NULL); + + policySurface->bGetPosition = true; + + MockPolicyPosition *policyPosition = + new MockPolicyPosition(event->position); + + policySurface->mPolicyPosition = policyPosition; + } + + static void ActivateCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_activate *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bActivate = true; + } + + static void RaiseCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_raise *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bRaise = true; + } + + static void LowerCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_lower *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bLower = true; + } + + static void SetFocusSkipCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_focus_skip *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bSetFocusSkip = true; + } + + static void UnsetFocusSkipCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_unset_focus_skip *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bSetFocusSkip = false; + } + + static void SetRoleCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_role *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + policySurface->mRole = event->role; // char -> string + } + + static void WindowTypeCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_window_type *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mWinType = event->win_type; + } + + static void SetConformantCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_conformant *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bSetConformant = true; + } + + static void UnsetConformantCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_unset_conformant *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bSetConformant = false; + } + + static void GetConformantCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_get_conformant *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bGetConformant = true; + } + + static void SetNotificationLevelCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_notification_level *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mNotificationLevel = event->level; + } + + static void SetWindowScreenModeCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_window_screen_mode *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mWindowScreenMode = event->mode; + } + + static void GetSubsurfaceCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_get_subsurface *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mParentUniversalId = event->parent_universal_id; + } + + static void IconifyCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_iconify *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bIconify = true; + } + + static void UniconifyCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_uniconify *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bIconify = false; + } + + static void AddAuxHintCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_add_aux_hint *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mAuxHintId = event->id; + policySurface->mAuxHintName = event->name; + policySurface->mAuxHintValue = event->value; + } + + static void ChangeAuxHintCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_change_aux_hint *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mAuxHintId = event->id; + policySurface->mAuxHintValue = event->value; + } + + static void DeleteAuxHintCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_delete_aux_hint *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mAuxHintId = event->id; + } + + static void GetSupportAuxHintsCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_get_supported_aux_hints *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bGetSupportedAuxHints = true; + } + + static void SetFloatingModeCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_floating_mode *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bSetFloatingMode = true; + } + + static void UnsetFloatingModeCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_unset_floating_mode *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bSetFloatingMode = false; + } + + static void SetStackModeCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_stack_mode *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mStackMode = event->mode; + } + + static void GetSubsurfaceWatcherCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_get_subsurface_watcher *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + EXPECT_TRUE(event->subsurface_watcher != NULL); + + policySurface->bGetSubsurfaceWatcher = true; + + MockPolicySubsurfaceWatcher *policySubsurfaceWatcher = + new MockPolicySubsurfaceWatcher(event->subsurface_watcher); + + policySurface->mPolicySubsurfaceWatcher = policySubsurfaceWatcher; + } + + static void SetParentCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_parent *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mParentSurface = event->parent_surface; + } + + static void AckConformantRegionCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_ack_conformant_region *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mSerial = event->serial; + } + + static void SetVideoCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_video *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bVideo = event->video; + } + + static void ShowCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_show *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bShow = true; + } + + static void HideCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_hide *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->bHide = true; + } + + static void SetParentWithBelowCallback(struct wl_listener *listener, void *data) + { + MockPolicySurface *policySurface = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_surface_set_parent_with_below *event = + static_cast(data); + + EXPECT_TRUE(policySurface->mPolicySurface == event->policy_surface); + + policySurface->mParentSurface = event->parent_surface; + } + + uint32_t GetSurfaceResId() + { + struct ds_surface *surface = ds_tizen_policy_surface_get_surface(mPolicySurface); + struct wl_resource *surface_res = ds_surface_get_wl_resource(surface); + + return wl_resource_get_id(surface_res); + } + + MockPolicyVisibility *GetVisibility() + { + return mPolicyVisibility; + } + + MockPolicyPosition *GetPosition() + { + return mPolicyPosition; + } + + MockPolicySubsurfaceWatcher*GetSubsurfaceWatcher() + { + return mPolicySubsurfaceWatcher; + } + + void SendConformant(bool active) + { + ds_inf("%s", __func__); + + ds_tizen_policy_surface_send_conformant(mPolicySurface, active); + } + + void SendConformantArea(enum ds_tizen_policy_conformant_part part, + bool visible, int32_t x, int32_t y, int32_t w, int32_t h) + { + ds_inf("%s", __func__); + + ds_tizen_policy_surface_send_conformant_area(mPolicySurface, part, visible, + x, y, w, h); + } + + void SendNotificationDone( + enum ds_tizen_policy_notification_level notification_level, + enum ds_tizen_policy_error_state error_state) + { + ds_inf("%s", __func__); + + ds_tizen_policy_surface_send_notification_done(mPolicySurface, notification_level, + error_state); + } + + void SendWindowScreenModeDone( + enum ds_tizen_policy_window_screen_mode window_screen_mode, + enum ds_tizen_policy_error_state error_state) + { + ds_inf("%s", __func__); + + ds_tizen_policy_surface_send_window_screen_mode_done(mPolicySurface, window_screen_mode, + error_state); + } + + void SendIconifyStateChanged(bool iconified, bool force) + { + ds_inf("%s", __func__); + + ds_tizen_policy_surface_send_iconify_state_changed(mPolicySurface, iconified, force); + } + +public: + bool bDestroyed; + + bool bGetVisibility; + bool bGetPosition; + bool bActivate; + bool bRaise; + bool bLower; + bool bSetFocusSkip; + std::string mRole; + enum ds_tizen_policy_window_type mWinType; + bool bSetConformant; + bool bGetConformant; + enum ds_tizen_policy_notification_level mNotificationLevel; + enum ds_tizen_policy_window_screen_mode mWindowScreenMode; + uint32_t mUniversalId; + uint32_t mParentUniversalId; + bool bIconify; + int32_t mAuxHintId; + std::string mAuxHintName; + std::string mAuxHintValue; + bool bGetSupportedAuxHints; + bool bSetFloatingMode; + enum ds_tizen_policy_stack_mode mStackMode; + bool bGetSubsurfaceWatcher; + struct ds_surface *mParentSurface; + uint32_t mSerial; + bool bVideo; + bool bShow; + bool bHide; + +private: + struct ds_tizen_policy_surface *mPolicySurface; + MockPolicyVisibility *mPolicyVisibility; + MockPolicyPosition *mPolicyPosition; + MockPolicySubsurfaceWatcher *mPolicySubsurfaceWatcher; + + struct DestroyListener : ::wl_listener { + MockPolicySurface *parent; + }; + DestroyListener mDestroyListener; + + // policy policy_surface listener structure + struct GetVisibilityListener : ::wl_listener { + MockPolicySurface *parent; + }; + GetVisibilityListener mGetVisibilityListener; + + struct GetPositionListener : ::wl_listener { + MockPolicySurface *parent; + }; + GetPositionListener mGetPositionListener; + + struct ActivateListener : ::wl_listener { + MockPolicySurface *parent; + }; + ActivateListener mActivateListener; + + struct RaiseListener : ::wl_listener { + MockPolicySurface *parent; + }; + RaiseListener mRaiseListener; + + struct LowerListener : ::wl_listener { + MockPolicySurface *parent; + }; + LowerListener mLowerListener; + + struct SetFocusSkipListener : ::wl_listener { + MockPolicySurface *parent; + }; + SetFocusSkipListener mSetFocusSkipListener; + + struct UnsetFocusSkipListener : ::wl_listener { + MockPolicySurface *parent; + }; + UnsetFocusSkipListener mUnsetFocusSkipListener; + + struct SetRoleListener : ::wl_listener { + MockPolicySurface *parent; + }; + SetRoleListener mSetRoleListener; + + struct WindowTypeListener : ::wl_listener { + MockPolicySurface *parent; + }; + WindowTypeListener mWindowTypeListener; + + struct SetConformantListener : ::wl_listener { + MockPolicySurface *parent; + }; + SetConformantListener mSetConformantListener; + + struct UnsetConformantListener : ::wl_listener { + MockPolicySurface *parent; + }; + UnsetConformantListener mUnsetConformantListener; + + struct GetConformantListener : ::wl_listener { + MockPolicySurface *parent; + }; + GetConformantListener mGetConformantListener; + + struct SetNotificationLevelListener : ::wl_listener { + MockPolicySurface *parent; + }; + SetNotificationLevelListener mSetNotificationLevelListener; + + struct SetWindowScreenModeListener : ::wl_listener { + MockPolicySurface *parent; + }; + SetWindowScreenModeListener mSetWindowScreenModeListener; + + struct GetSubsurfaceListener : ::wl_listener { + MockPolicySurface *parent; + }; + GetSubsurfaceListener mGetSubsurfaceListener; + + struct IconifyListener : ::wl_listener { + MockPolicySurface *parent; + }; + IconifyListener mIconifyListener; + + struct UniconifyListener : ::wl_listener { + MockPolicySurface *parent; + }; + UniconifyListener mUniconifyListener; + + struct AddAuxHintListener : ::wl_listener { + MockPolicySurface *parent; + }; + AddAuxHintListener mAddAuxHintListener; + + struct ChangeAuxHintListener : ::wl_listener { + MockPolicySurface *parent; + }; + ChangeAuxHintListener mChangeAuxHintListener; + + struct DeleteAuxHintListener : ::wl_listener { + MockPolicySurface *parent; + }; + DeleteAuxHintListener mDeleteAuxHintListener; + + struct GetSupportAuxHintsListener : ::wl_listener { + MockPolicySurface *parent; + }; + GetSupportAuxHintsListener mGetSupportAuxHintsListener; + + struct SetFloatingModeListener : ::wl_listener { + MockPolicySurface *parent; + }; + SetFloatingModeListener mSetFloatingModeListener; + + struct UnsetFloatingModeListener : ::wl_listener { + MockPolicySurface *parent; + }; + UnsetFloatingModeListener mUnsetFloatingModeListener; + + struct SetStackModeListener : ::wl_listener { + MockPolicySurface *parent; + }; + SetStackModeListener mSetStackModeListener; + + struct GetSubsurfaceWatcherListener : ::wl_listener { + MockPolicySurface *parent; + }; + GetSubsurfaceWatcherListener mGetSubsurfaceWatcherListener; + + struct SetParentListener : ::wl_listener { + MockPolicySurface *parent; + }; + SetParentListener mSetParentListener; + + struct AckConformantRegionListener : ::wl_listener { + MockPolicySurface *parent; + }; + AckConformantRegionListener mAckConformantRegionListener; + + struct SetVideoListener : ::wl_listener { + MockPolicySurface *parent; + }; + SetVideoListener mSetVideoListener; + + struct ShowListener : ::wl_listener { + MockPolicySurface *parent; + }; + ShowListener mShowListener; + + struct HideListener : ::wl_listener { + MockPolicySurface *parent; + }; + HideListener mHideListener; + + struct SetParentWithBelowListener : ::wl_listener { + MockPolicySurface *parent; + }; + SetParentWithBelowListener mSetParentWithBelowListener; +}; + +class MockSurface +{ +public: + MockSurface(struct ds_surface *surface) + : mSurface(surface) + { + ds_inf("%s", __func__); + + // del surface listener + mDestroyListener.notify = MockSurface::DestroyCallback; + mDestroyListener.parent = this; + ds_surface_add_destroy_listener(surface, &mDestroyListener); + } + ~MockSurface() + { + ds_inf("%s", __func__); + + if (mDestroyListener.notify) { + wl_list_remove(&mDestroyListener.link); + mDestroyListener.notify = nullptr; + } + } + + static void DestroyCallback(struct wl_listener *listener, void *data) + { + MockSurface *mockSurface = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + + ds_inf("%s: mockSurface(%p), surface(%p)", __func__, mockSurface, surface); + + wl_list_remove(&mockSurface->mDestroyListener.link); + mockSurface->mDestroyListener.notify = nullptr; + } + +private: + struct ds_surface *mSurface; + + struct DestroyListener : ::wl_listener { + MockSurface *parent; + }; + DestroyListener mDestroyListener; +}; + +class MockPolicyCompositor : public MockCompositor +{ +public: + MockPolicyCompositor() + : MockCompositor(&MockPolicyCompositor::TestSetup, this) + { + ds_inf("%s : this(%p)", __func__, this); + + // initialize the flags to check + bDestroyed = false; + bGetPolicySurface = false; + } + + ~MockPolicyCompositor() + { + ds_inf("%s : this(%p)", __func__, this); + + auto removeSurfaces = [&](MockSurface* s)->void {delete s;}; + for_each(mMockSurfaces.begin(), mMockSurfaces.end(), removeSurfaces); + mMockSurfaces.clear(); + + auto removePolicySurfaces = [&](MockPolicySurface* i)->void {delete i;}; + for_each(mPolicySurfaces.begin(), mPolicySurfaces.end(), removePolicySurfaces); + mPolicySurfaces.clear(); + + wl_list_remove(&mNewSurfaceListener.link); + } + + static void TestSetup(void *data) + { + MockPolicyCompositor *mockComp = + static_cast(data); + Compositor *comp = mockComp->compositor; + + ds_inf("%s: mockComp(%p)", __func__, mockComp); + + // new surface listener + mockComp->mNewSurfaceListener.notify = + MockPolicyCompositor::NewSurfaceCallback; + mockComp->mNewSurfaceListener.parent = mockComp; + ds_compositor_add_new_surface_listener(comp->compositor, + &mockComp->mNewSurfaceListener); + + mockComp->mPolicy = + ds_tizen_policy_create(comp->display); + + // policy destroy listener + mockComp->mDestroyListener.notify = + MockPolicyCompositor::DestroyCallback; + mockComp->mDestroyListener.parent = mockComp; + ds_tizen_policy_add_destroy_listener(mockComp->mPolicy, + &mockComp->mDestroyListener); + + // policy listeners + mockComp->mGetPolicySurfaceListener.notify = + MockPolicyCompositor::GetPolicySurfaceCallback; + mockComp->mGetPolicySurfaceListener.parent = mockComp; + ds_tizen_policy_add_get_surface_listener( + mockComp->mPolicy, + &mockComp->mGetPolicySurfaceListener); + + mockComp->mActivateBelowByUniversalIdListener.notify = + MockPolicyCompositor::ActivateBelowByUniversalIdCallback; + mockComp->mActivateBelowByUniversalIdListener.parent = mockComp; + ds_tizen_policy_add_activate_below_by_univeral_id_listener( + mockComp->mPolicy, + &mockComp->mActivateBelowByUniversalIdListener); + + mockComp->mLowerByUniversalIdListener.notify = + MockPolicyCompositor::LowerByUniversalIdCallback; + mockComp->mLowerByUniversalIdListener.parent = mockComp; + ds_tizen_policy_add_lower_by_universal_id_listener( + mockComp->mPolicy, + &mockComp->mLowerByUniversalIdListener); + + mockComp->mSetTransientForListener.notify = + MockPolicyCompositor::SetTransientForCallback; + mockComp->mSetTransientForListener.parent = mockComp; + ds_tizen_policy_add_set_transient_for_listener( + mockComp->mPolicy, + &mockComp->mSetTransientForListener); + + mockComp->mUnsetTransientForListener.notify = + MockPolicyCompositor::UnsetTransientForCallback; + mockComp->mUnsetTransientForListener.parent = mockComp; + ds_tizen_policy_add_unset_transient_for_listener( + mockComp->mPolicy, + &mockComp->mUnsetTransientForListener); + + mockComp->mPlaceSubsurfaceBelowParentListener.notify = + MockPolicyCompositor::PlaceSubsurfaceBelowParentCallback; + mockComp->mPlaceSubsurfaceBelowParentListener.parent = mockComp; + ds_tizen_policy_add_place_subsurface_below_parent_listener( + mockComp->mPolicy, + &mockComp->mPlaceSubsurfaceBelowParentListener); + + mockComp->mSetSubsurfaceStandAloneListener.notify = + MockPolicyCompositor::SetSubsurfaceStandAloneCallback; + mockComp->mSetSubsurfaceStandAloneListener.parent = mockComp; + ds_tizen_policy_add_set_subsurface_stand_alone_listener( + mockComp->mPolicy, + &mockComp->mSetSubsurfaceStandAloneListener); + + mockComp->mSetBackgroundStateListener.notify = + MockPolicyCompositor::SetBackgroundStateCallback; + mockComp->mSetBackgroundStateListener.parent = mockComp; + ds_tizen_policy_add_set_background_state_listener( + mockComp->mPolicy, + &mockComp->mSetBackgroundStateListener); + + mockComp->mUnsetBackgroundStateListener.notify = + MockPolicyCompositor::UnsetBackgroundStateCallback; + mockComp->mUnsetBackgroundStateListener.parent = mockComp; + ds_tizen_policy_add_unset_background_state_listener( + mockComp->mPolicy, + &mockComp->mUnsetBackgroundStateListener); + + mockComp->mActivateAboveByUniversalIdListener.notify = + MockPolicyCompositor::ActivateAboveByUniversalIdCallback; + mockComp->mActivateAboveByUniversalIdListener.parent = mockComp; + ds_tizen_policy_add_activate_above_by_universal_id_listener( + mockComp->mPolicy, + &mockComp->mActivateAboveByUniversalIdListener); + + mockComp->mSetAppIdListener.notify = + MockPolicyCompositor::SetAppIdCallback; + mockComp->mSetAppIdListener.parent = mockComp; + ds_tizen_policy_add_set_appid_listener( + mockComp->mPolicy, + &mockComp->mSetAppIdListener); + + mockComp->mSetTransientForBelowListener.notify = + MockPolicyCompositor::SetTransientForBelowCallback; + mockComp->mSetTransientForBelowListener.parent = mockComp; + ds_tizen_policy_add_set_transient_for_below_listener( + mockComp->mPolicy, + &mockComp->mSetTransientForBelowListener); + } + + static void NewSurfaceCallback(struct wl_listener *listener, void *data) + { + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_surface *surface = static_cast(data); + MockSurface *mockSurf = new MockSurface(surface); + + ds_inf("%s: mockComp(%p), surface(%p)", __func__, mockComp, surface); + + mockComp->mMockSurfaces.push_back(mockSurf); + } + + static void DestroyCallback(struct wl_listener *listener, void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + + mockComp->bDestroyed = true; + } + + static void GetPolicySurfaceCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_get_surface *event = + static_cast(data); + + struct ds_tizen_policy_surface *policy_surface = event->policy_surface; + + ds_inf("%s: mockComp(%p), policy_surface(%p)", __func__, mockComp, policy_surface); + + mockComp->bGetPolicySurface = true; + + MockPolicySurface *policySurface = new MockPolicySurface(event->policy_surface); + mockComp->mPolicySurfaces.push_back(policySurface); + } + + static void ActivateBelowByUniversalIdCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_activate_below_by_univeral_id *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->mUniversalId = event->universal_id; + mockComp->mBelowUniversalId = event->below_universal_id; + } + + static void LowerByUniversalIdCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_lower_by_universal_id *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->mUniversalId = event->universal_id; + } + + static void SetTransientForCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_set_transient_for *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->mChildUniversalId = event->child_universal_id; + mockComp->mParentUniversalId = event->parent_universal_id; + } + + static void UnsetTransientForCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_unset_transient_for *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->mChildUniversalId = event->child_universal_id; + } + + static void PlaceSubsurfaceBelowParentCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_place_subsurface_below_parent *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->bPlaceSubsurfaceBelowParent = true; + } + + static void SetSubsurfaceStandAloneCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_set_subsurface_stand_alone *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->bSetSubsurfaceStandAlone = true; + } + + static void SetBackgroundStateCallback(struct wl_listener *listener, void *data) + { + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_set_background_state *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->mPid = event->pid; + } + + static void UnsetBackgroundStateCallback(struct wl_listener *listener, void *data) + { + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_unset_background_state *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->mPid = event->pid; + } + + static void ActivateAboveByUniversalIdCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_activate_above_by_universal_id *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->mUniversalId = event->universal_id; + mockComp->mAboveUniversalId = event->above_universal_id; + } + + static void SetAppIdCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_set_appid *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->mPid = event->pid; + mockComp->mAppId = event->appid; // char -> string + } + + static void SetTransientForBelowCallback(struct wl_listener *listener, + void *data) + { + ds_inf("%s", __func__); + + MockPolicyCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_event_policy_set_transient_for_below *event = + static_cast(data); + + EXPECT_TRUE(mockComp->mPolicy == event->policy); + mockComp->mUniversalId = event->universal_id; + mockComp->mParentUniversalId = event->parent_universal_id; + } + + MockPolicySurface* FindPolicySurfaceWidthResId(uint32_t res_id) + { + auto is_matched = [&](MockPolicySurface* i)->bool { + return (i->GetSurfaceResId() == res_id); + }; + auto result = std::find_if(begin(mPolicySurfaces), end(mPolicySurfaces), + is_matched); + if (result != std::end(mPolicySurfaces)) + return *result; + + return nullptr; + } + +public: + bool bDestroyed; + bool bGetPolicySurface; + int32_t mPid; + std::string mAppId; + uint32_t mUniversalId; + uint32_t mAboveUniversalId; + uint32_t mBelowUniversalId; + uint32_t mParentUniversalId; + uint32_t mChildUniversalId; + bool bPlaceSubsurfaceBelowParent; + bool bSetSubsurfaceStandAlone; + +private: + struct ds_tizen_policy *mPolicy; + + std::vector mMockSurfaces; + std::vector mPolicySurfaces; + + struct NewSurfaceListener : ::wl_listener { + MockPolicyCompositor *parent; + }; + NewSurfaceListener mNewSurfaceListener; + + struct DestroyListener : ::wl_listener { + MockPolicyCompositor *parent; + }; + DestroyListener mDestroyListener; + + // policy listener structure + struct GetPolicySurfaceListener : ::wl_listener { + MockPolicyCompositor *parent; + }; + GetPolicySurfaceListener mGetPolicySurfaceListener; + + struct ActivateBelowByUniversalIdListener: ::wl_listener { + MockPolicyCompositor *parent; + }; + ActivateBelowByUniversalIdListener mActivateBelowByUniversalIdListener; + + struct LowerByUniversalIdListener: ::wl_listener { + MockPolicyCompositor *parent; + }; + LowerByUniversalIdListener mLowerByUniversalIdListener; + + struct SetTransientForListener: ::wl_listener { + MockPolicyCompositor *parent; + }; + SetTransientForListener mSetTransientForListener; + + struct UnsetTransientForListener: ::wl_listener { + MockPolicyCompositor *parent; + }; + UnsetTransientForListener mUnsetTransientForListener; + + struct PlaceSubsurfaceBelowParentListener: ::wl_listener { + MockPolicyCompositor *parent; + }; + PlaceSubsurfaceBelowParentListener mPlaceSubsurfaceBelowParentListener; + + struct SetSubsurfaceStandAloneListener: ::wl_listener { + MockPolicyCompositor *parent; + }; + SetSubsurfaceStandAloneListener mSetSubsurfaceStandAloneListener; + + struct SetBackgroundStateListener : ::wl_listener { + MockPolicyCompositor *parent; + }; + SetBackgroundStateListener mSetBackgroundStateListener; + + struct UnsetBackgroundStateListener : ::wl_listener { + MockPolicyCompositor *parent; + }; + UnsetBackgroundStateListener mUnsetBackgroundStateListener; + + struct ActivateAboveByUniversalIdListener: ::wl_listener { + MockPolicyCompositor *parent; + }; + ActivateAboveByUniversalIdListener mActivateAboveByUniversalIdListener; + + struct SetAppIdListener: ::wl_listener { + MockPolicyCompositor *parent; + }; + SetAppIdListener mSetAppIdListener; + + struct SetTransientForBelowListener: ::wl_listener { + MockPolicyCompositor *parent; + }; + SetTransientForBelowListener mSetTransientForBelowListener; + + // policy_surface listener structure + struct PolicySurfaceDestroyListener : ::wl_listener { + MockPolicyCompositor *parent; + }; + PolicySurfaceDestroyListener mPolicySurfaceDestroyListener; +}; + +class MockPolicyClient : public MockClient +{ +public: + MockPolicyClient() + : mSurfaceRes(nullptr), + mIsConformant(0), + mLevel(-1), + mErrorState(0), + mChildId(0), + mWindowScreenMode(0), + mIconified(0), + mForce(0), + mHints(nullptr), + mNumHints(0), + mHintId(-1), + mKey(nullptr), + mValue(nullptr), + mOptions(nullptr), + mConformantPart(0), + mState(0), + mX(-1), mY(-1), mW(0), mH(0), + mSerial(0), + mVisibilityType(0), + mVisibilityOption(0), + mPositionX(-1), mPositionY(-1) + {} + MockPolicyClient(const struct wl_registry_listener *listener) + : MockClient(listener, this) + { + ds_inf("%s", __func__); + } + ~MockPolicyClient() + { + ds_inf("%s", __func__); + } + + void SetWlCompositor(struct wl_compositor *global_res) + { + ds_inf("%s", __func__); + + compositor_res = global_res; + } + + void SetWlSubCompositor(struct wl_subcompositor *global_res) + { + ds_inf("%s", __func__); + + subcompositor_res = global_res; + } + + struct wl_compositor *GetWlCompositor() + { + ds_inf("%s", __func__); + + return compositor_res; + } + + struct wl_subcompositor *GetWlSubCompositor() + { + ds_inf("%s", __func__); + + return subcompositor_res; + } + + void SetTizenPolicy(struct tizen_policy *resource) + { + ds_inf("%s", __func__); + + policy_res = resource; + } + + struct tizen_policy *GetTizenPolicy() + { + ds_inf("%s", __func__); + + return policy_res; + } + +public: + struct wl_surface *mSurfaceRes; + uint32_t mIsConformant; + int32_t mLevel; + uint32_t mErrorState; + uint32_t mChildId; + uint32_t mWindowScreenMode; + uint32_t mIconified; + uint32_t mForce; + struct wl_array *mHints; + uint32_t mNumHints; + int32_t mHintId; + const char *mKey; + const char *mValue; + struct wl_array *mOptions; + uint32_t mConformantPart; + uint32_t mState; + int32_t mX, mY, mW, mH; + uint32_t mSerial; + uint32_t mVisibilityType; + uint32_t mVisibilityOption; + int32_t mPositionX; + int32_t mPositionY; + +private: + struct wl_compositor *compositor_res; + struct wl_subcompositor *subcompositor_res; + struct tizen_policy *policy_res; +}; + +static void +client_tizen_policy_cb_conformant(void *data, struct tizen_policy *policy_res, + struct wl_surface *surface_resource, uint32_t is_conformant) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mIsConformant = is_conformant; +} + +static void +client_tizen_policy_cb_conformant_area(void *data, + struct tizen_policy *policy_res, + struct wl_surface *surface_resource, uint32_t conformant_part, + uint32_t state, int32_t x, int32_t y, int32_t w, int32_t h) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mConformantPart = conformant_part; + client->mState = state; + client->mX = x; + client->mY = y; + client->mW = w; + client->mH = h; +} + +static void +client_tizen_policy_cb_notification_done(void *data, + struct tizen_policy *policy_res, + struct wl_surface *surface_resource, int32_t level, uint32_t error_state) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mLevel = level; + client->mErrorState = error_state; +} + +static void +client_tizen_policy_cb_transient_for_done(void *data, + struct tizen_policy *policy_res, uint32_t child_id) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mChildId = child_id; +} + +static void +client_tizen_policy_cb_window_screen_mode_done(void *data, + struct tizen_policy *policy_res, struct wl_surface *surface_resource, + uint32_t mode, uint32_t error_state) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mWindowScreenMode = mode; + client->mErrorState = error_state; +} + +static void +client_tizen_policy_cb_iconify_state_changed(void *data, + struct tizen_policy *policy_res, struct wl_surface *surface_resource, + uint32_t iconified, uint32_t force) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mIconified = iconified; + client->mForce = force; +} + +static void +client_tizen_policy_cb_supported_aux_hints(void *data, + struct tizen_policy *policy_res, struct wl_surface *surface_resource, + struct wl_array *hints, uint32_t num_hints) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mHints = hints; + client->mNumHints = num_hints; +} + +static void +client_tizen_policy_cb_allowed_aux_hint(void *data, + struct tizen_policy *policy_res, struct wl_surface *surface_resource, + int32_t id) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mHintId = id; +} + +static void +client_tizen_policy_cb_aux_message(void *data, + struct tizen_policy *policy_res, struct wl_surface *surface_resource, + const char *key, const char *value, struct wl_array *options) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mKey = key; + client->mValue = value; + client->mOptions = options; +} + +static void +client_tizen_policy_cb_conformant_region(void *data, + struct tizen_policy *policy_res, struct wl_surface *surface_resource, + uint32_t conformant_part, uint32_t state, + int32_t x, int32_t y, int32_t w, int32_t h, uint32_t serial) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mConformantPart = conformant_part; + client->mState = state; + client->mX = x; + client->mY = y; + client->mW = w; + client->mH = h; + client->mSerial = serial; +} + +static void +client_tizen_policy_cb_interactive_mode_done(void *data, + struct tizen_policy *policy_res, struct wl_surface *surface_resource, + int32_t x, int32_t y, uint32_t w, uint32_t h) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mX = x; + client->mY = y; + client->mW = w; + client->mH = h; +} + +static void +client_tizen_policy_cb_interactive_resize_done(void *data, + struct tizen_policy *policy_res, struct wl_surface *surface_resource, + int32_t x, int32_t y, uint32_t w, uint32_t h) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mSurfaceRes = surface_resource; + client->mX = x; + client->mY = y; + client->mW = w; + client->mH = h; +} + +static const struct +tizen_policy_listener policy_cb_listener = +{ + .conformant = client_tizen_policy_cb_conformant, + .conformant_area = client_tizen_policy_cb_conformant_area, + .notification_done = client_tizen_policy_cb_notification_done, + .transient_for_done = client_tizen_policy_cb_transient_for_done, + .window_screen_mode_done = client_tizen_policy_cb_window_screen_mode_done, + .iconify_state_changed = client_tizen_policy_cb_iconify_state_changed, + .supported_aux_hints = client_tizen_policy_cb_supported_aux_hints, + .allowed_aux_hint = client_tizen_policy_cb_allowed_aux_hint, + .aux_message = client_tizen_policy_cb_aux_message, + .conformant_region = client_tizen_policy_cb_conformant_region, + .interactive_move_done = client_tizen_policy_cb_interactive_mode_done, + .interactive_resize_done = client_tizen_policy_cb_interactive_resize_done, +}; + +static void +client_registry_cb_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + struct wl_compositor *compositor_res; + struct wl_subcompositor *subcompositor_res; + struct tizen_policy *policy_res; + + if (!strcmp(interface, "wl_compositor")) { + compositor_res = (struct wl_compositor *)wl_registry_bind(registry, + name, &wl_compositor_interface, 1); + if (compositor_res == nullptr) { + ds_err("wl_registry_bind() failed. wl_compositor resource."); + return; + } + client->SetWlCompositor(compositor_res); + } else if (!strcmp(interface, "wl_subcompositor")) { + subcompositor_res = (struct wl_subcompositor *) + wl_registry_bind(registry, name, &wl_subcompositor_interface, 1); + if (subcompositor_res == nullptr) { + ds_err("wl_registry_bind() failed. wl_subcompositor resource."); + return; + } + client->SetWlSubCompositor(subcompositor_res); + } else if (!strcmp(interface, "tizen_policy")) { + policy_res = (struct tizen_policy *)wl_registry_bind(registry, + name, &tizen_policy_interface, TIZEN_POLICY_VERSION); + if (policy_res == nullptr) { + ds_err("wl_registry_bind() failed. tizen_policy resource."); + return; + } + client->SetTizenPolicy(policy_res); + + tizen_policy_add_listener(policy_res, + &policy_cb_listener, client); + } +} + +static void +client_registry_cb_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + struct wl_compositor *compositor_res = client->GetWlCompositor(); + struct tizen_policy *policy_res = client->GetTizenPolicy(); + + tizen_policy_destroy(policy_res); + wl_compositor_destroy(compositor_res); +} + +static const struct wl_registry_listener registry_listener = { + .global = client_registry_cb_global, + .global_remove = client_registry_cb_global_remove +}; + +class PolicyTest : public ::testing::Test +{ +public: + void SetUp(void) override; + void TearDown(void) override; + + MockPolicyCompositor *comp; + MockPolicyClient *client; + struct wl_compositor *compositor_res; + struct wl_subcompositor *subcompositor_res; + struct tizen_policy *policy_res; + struct wl_surface *surface_res; +}; + +void +PolicyTest::SetUp(void) +{ + //ds_log_init(DS_DBG, NULL); + + ds_inf("%s", __func__); + + comp = new MockPolicyCompositor(); + client = new MockPolicyClient(®istry_listener); + compositor_res = client->GetWlCompositor(); + subcompositor_res = client->GetWlSubCompositor(); + policy_res = client->GetTizenPolicy(); + surface_res = wl_compositor_create_surface(compositor_res); + + client->RoundTrip(); +} + +void +PolicyTest::TearDown(void) +{ + ds_inf("%s", __func__); + + wl_surface_destroy(surface_res); + client->RoundTrip(); + + delete client; + delete comp; +} + +TEST_F(PolicyTest, Create_P) +{ + EXPECT_TRUE(true); +} + +TEST_F(PolicyTest, Req_ActivateBelowByUniversalId) +{ + uint32_t universal_id = 100; + uint32_t below_universal_id = 200; + + tizen_policy_activate_below_by_res_id(policy_res, + universal_id, below_universal_id); + client->RoundTrip(); + + EXPECT_TRUE(comp->mUniversalId == universal_id) + << comp->mUniversalId << ", " << universal_id; + EXPECT_TRUE(comp->mBelowUniversalId == below_universal_id) + << comp->mBelowUniversalId << ", " << below_universal_id; +} + +TEST_F(PolicyTest, Req_LowerByUniversalId) +{ + uint32_t universal_id = 100; + + tizen_policy_lower_by_res_id(policy_res,universal_id); + client->RoundTrip(); + + EXPECT_TRUE(comp->mUniversalId == universal_id) + << comp->mUniversalId << ", " << universal_id; +} + +TEST_F(PolicyTest, Req_SetTransientFor) +{ + uint32_t child_universal_id = 100; + uint32_t parent_universal_id = 200; + + tizen_policy_set_transient_for(policy_res, + child_universal_id, parent_universal_id); + client->RoundTrip(); + + EXPECT_TRUE(comp->mChildUniversalId == child_universal_id) + << comp->mChildUniversalId << ", " << child_universal_id; + EXPECT_TRUE(comp->mParentUniversalId == parent_universal_id) + << comp->mParentUniversalId << ", " << parent_universal_id; + + EXPECT_TRUE(client->mChildId == child_universal_id); +} + +TEST_F(PolicyTest, Req_UnsetTransientFor) +{ + uint32_t child_universal_id = 100; + + tizen_policy_unset_transient_for(policy_res, child_universal_id); + client->RoundTrip(); + + EXPECT_TRUE(comp->mChildUniversalId == child_universal_id) + << comp->mChildUniversalId << ", " << child_universal_id; + + EXPECT_TRUE(client->mChildId == child_universal_id); +} + +TEST_F(PolicyTest, Req_PlaceSubsurfaceBelowParent) +{ + struct wl_surface *parent_surface_res; + struct wl_subsurface *subsurface_res; + + parent_surface_res = wl_compositor_create_surface(compositor_res); + if (!parent_surface_res) + return; + + subsurface_res = wl_subcompositor_get_subsurface(subcompositor_res, + surface_res, parent_surface_res); + if (!subsurface_res) { + wl_surface_destroy(parent_surface_res); + return; + } + + tizen_policy_place_subsurface_below_parent(policy_res, subsurface_res); + client->RoundTrip(); + + EXPECT_TRUE(comp->bPlaceSubsurfaceBelowParent); + + wl_subsurface_destroy(subsurface_res); + wl_surface_destroy(parent_surface_res); +} + +TEST_F(PolicyTest, Req_SetSubsurfaceStandAlone) +{ + struct wl_surface *parent_surface_res; + struct wl_subsurface *subsurface_res; + + parent_surface_res = wl_compositor_create_surface(compositor_res); + if (!parent_surface_res) + return; + + subsurface_res = wl_subcompositor_get_subsurface(subcompositor_res, + surface_res, parent_surface_res); + if (!subsurface_res) { + wl_surface_destroy(parent_surface_res); + return; + } + + tizen_policy_set_subsurface_stand_alone(policy_res, subsurface_res); + client->RoundTrip(); + + EXPECT_TRUE(comp->bSetSubsurfaceStandAlone); + + wl_subsurface_destroy(subsurface_res); + wl_surface_destroy(parent_surface_res); +} + +TEST_F(PolicyTest, Req_ActivateAboveByUniversalId) +{ + uint32_t universal_id = 100; + uint32_t above_universal_id = 100; + + tizen_policy_activate_above_by_res_id(policy_res, universal_id, + above_universal_id); + client->RoundTrip(); + + EXPECT_TRUE(comp->mUniversalId == universal_id) + << comp->mUniversalId << ", " << universal_id; + EXPECT_TRUE(comp->mAboveUniversalId == above_universal_id) + << comp->mAboveUniversalId << ", " << above_universal_id; +} + +TEST_F(PolicyTest, Req_SetAppId) +{ + int32_t pid = getpid(); + std::string appid("APPLICATION_ID"); + char* c_appid = const_cast(appid.c_str()); + + tizen_policy_set_appid(policy_res, pid, c_appid); + client->RoundTrip(); + + EXPECT_TRUE(comp->mPid == pid) + << comp->mPid << ", " << pid; + EXPECT_TRUE(comp->mAppId.compare(appid) == false) + << comp->mAppId << ", " << appid; +} + +TEST_F(PolicyTest, Req_SetTransientForBelow) +{ + uint32_t universal_id = 100; + uint32_t parent_universal_id = 200; + + tizen_policy_set_transient_for_below(policy_res, universal_id, + parent_universal_id); + client->RoundTrip(); + + EXPECT_TRUE(comp->mUniversalId == universal_id) + << comp->mUniversalId << ", " << universal_id; + EXPECT_TRUE(comp->mParentUniversalId == parent_universal_id) + << comp->mParentUniversalId << ", " << parent_universal_id; +} + +static void +client_tizen_visibility_cb_notify(void *data, + struct tizen_visibility *visibility_res, uint32_t visibility) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mVisibilityType = visibility; +} + +static void +client_tizen_visibility_cb_changed(void *data, + struct tizen_visibility *visibility_res, uint32_t type, uint32_t option) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mVisibilityType = type; + client->mVisibilityOption = option; +} + +static const struct +tizen_visibility_listener visibility_cb_listener = +{ + .notify = client_tizen_visibility_cb_notify, + .changed = client_tizen_visibility_cb_changed, +}; + +TEST_F(PolicyTest, Req_PolicySurfaceGetVisibility) +{ + MockPolicySurface *policy_surface; + MockPolicyVisibility *visibility; + struct tizen_visibility *visibility_res; + uint32_t surface_res_id; + + visibility_res = tizen_policy_get_visibility(policy_res, surface_res); + EXPECT_TRUE(visibility_res != NULL); + + tizen_visibility_add_listener(visibility_res, + &visibility_cb_listener, client); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bGetVisibility); + + visibility = policy_surface->GetVisibility(); + + tizen_visibility_destroy(visibility_res); + client->RoundTrip(); + + EXPECT_TRUE(visibility->bDestroyed); +} + +TEST_F(PolicyTest, Ev_VisibilityNotify) +{ + MockPolicySurface *policy_surface; + MockPolicyVisibility *visibility; + struct tizen_visibility *visibility_res; + enum ds_tizen_policy_visibility_type type = + DS_TIZEN_POLICY_VISIBILITY_TYPE_FULLY_OBSCURED; + uint32_t surface_res_id; + + visibility_res = tizen_policy_get_visibility(policy_res, surface_res); + EXPECT_TRUE(visibility_res != NULL); + + tizen_visibility_add_listener(visibility_res, + &visibility_cb_listener, client); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bGetVisibility); + + visibility = policy_surface->GetVisibility(); + visibility->SendNotify(type); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->mVisibilityType == + TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED); + + tizen_visibility_destroy(visibility_res); + client->RoundTrip(); + + EXPECT_TRUE(visibility->bDestroyed); +} + +TEST_F(PolicyTest, Ev_VisibilityChanged) +{ + MockPolicySurface *policy_surface; + MockPolicyVisibility *visibility; + struct tizen_visibility *visibility_res; + enum ds_tizen_policy_visibility_type type = + DS_TIZEN_POLICY_VISIBILITY_TYPE_FULLY_OBSCURED; + uint32_t surface_res_id; + uint32_t option = 4; + + visibility_res = tizen_policy_get_visibility(policy_res, surface_res); + EXPECT_TRUE(visibility_res != NULL); + + tizen_visibility_add_listener(visibility_res, + &visibility_cb_listener, client); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bGetVisibility); + + visibility = policy_surface->GetVisibility(); + visibility->SendChanged(type, option); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->mVisibilityType == + TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED); + EXPECT_TRUE(client->mVisibilityOption == option); + + tizen_visibility_destroy(visibility_res); + client->RoundTrip(); + + EXPECT_TRUE(visibility->bDestroyed); +} + +static void +client_tizen_position_cb_changed(void *data, + struct tizen_position *position_res, int32_t x, int32_t y) +{ + ds_inf("%s", __func__); + + MockPolicyClient *client = static_cast(data); + + client->mPositionX = x; + client->mPositionY = y; +} + +static const struct +tizen_position_listener position_cb_listener = +{ + .changed = client_tizen_position_cb_changed, +}; + +TEST_F(PolicyTest, Req_PolicySurfaceGetPosition) +{ + MockPolicySurface *policy_surface; + struct tizen_position *position_res; + uint32_t surface_res_id; + + position_res = tizen_policy_get_position(policy_res, surface_res); + EXPECT_TRUE(position_res != NULL); + + tizen_position_add_listener(position_res, + &position_cb_listener, client); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bGetPosition); + + tizen_position_destroy(position_res); +} + +TEST_F(PolicyTest, Req_PositionSet) +{ + MockPolicySurface *policy_surface; + MockPolicyPosition *position; + struct tizen_position *position_res; + uint32_t surface_res_id; + int32_t x = 100, y = 200; + + position_res = tizen_policy_get_position(policy_res, surface_res); + EXPECT_TRUE(position_res != NULL); + + tizen_position_add_listener(position_res, + &position_cb_listener, client); + + tizen_position_set(position_res, x, y); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bGetPosition); + + position = policy_surface->GetPosition(); + EXPECT_TRUE(position->mX == x); + EXPECT_TRUE(position->mY == y); + + tizen_position_destroy(position_res); +} + +TEST_F(PolicyTest, Ev_PositionChanged) +{ + MockPolicySurface *policy_surface; + MockPolicyPosition *position; + struct tizen_position *position_res; + uint32_t surface_res_id; + int32_t x = 100, y = 200; + + position_res = tizen_policy_get_position(policy_res, surface_res); + EXPECT_TRUE(position_res != NULL); + + tizen_position_add_listener(position_res, + &position_cb_listener, client); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bGetPosition); + + position = policy_surface->GetPosition(); + position->SendChanged(x, y); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->mPositionX == x); + EXPECT_TRUE(client->mPositionY == y); + + tizen_position_destroy(position_res); +} + +TEST_F(PolicyTest, Req_PolicySurfaceActivate) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_activate(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bActivate); +} + +TEST_F(PolicyTest, Req_PolicySurfaceRaise) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_raise(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bRaise); +} + +TEST_F(PolicyTest, Req_PolicySurfaceLower) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_lower(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bLower); +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetFocusSkip) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_set_focus_skip(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bSetFocusSkip); +} + +TEST_F(PolicyTest, Req_PolicySurfaceUnsetFocusSkip) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_unset_focus_skip(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bSetFocusSkip == false); +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetRole) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + std::string role("APPLICATION_ID"); + char* c_role = const_cast(role.c_str()); + + tizen_policy_set_role(policy_res, surface_res, c_role); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->mRole.compare(role) == false) + << policy_surface->mRole << ", " << role; +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetType) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + uint32_t win_type = TIZEN_POLICY_WIN_TYPE_TOPLEVEL; + + tizen_policy_set_type(policy_res, surface_res, win_type); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->mWinType == DS_TIZEN_POLICY_WINDOW_TYPE_TOPLEVEL); +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetConformant) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_set_conformant(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bSetConformant == true); +} + +TEST_F(PolicyTest, Req_PolicySurfaceUnsetConformant) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_unset_conformant(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bSetConformant == false); +} + +TEST_F(PolicyTest, Req_Ev_PolicySurfaceGetConformant) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_get_conformant(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bGetConformant == true); +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetNotificationLevel) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + uint32_t noti_level = TIZEN_POLICY_LEVEL_HIGH; + + tizen_policy_set_notification_level(policy_res, surface_res, noti_level); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->mNotificationLevel == DS_TIZEN_POLICY_NOTIFICATION_LEVEL_HIGH); +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetWindowScreenMode) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + uint32_t screen_mode = TIZEN_POLICY_MODE_ALWAYS_ON; + + tizen_policy_set_window_screen_mode(policy_res, surface_res, screen_mode); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->mWindowScreenMode == DS_TIZEN_POLICY_WINDOW_SCREEN_MODE_ALWAYS_ON); +} + +TEST_F(PolicyTest, Req_PolicySurfaceGetSubsurface) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + struct wl_subsurface *subsurface_res; + uint32_t parent_universal_id = 100; + + subsurface_res = tizen_policy_get_subsurface(policy_res, surface_res, parent_universal_id); + EXPECT_TRUE(subsurface_res != NULL); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->mParentUniversalId == parent_universal_id); +} + +TEST_F(PolicyTest, Req_PolicySurfaceIconify) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_iconify(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bIconify == true); +} + +TEST_F(PolicyTest, Req_PolicySurfaceUniconify) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_uniconify(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bIconify == false); +} + +TEST_F(PolicyTest, Req_PolicySurfaceAddAuxHint) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + int32_t auxhint_id = 100; + std::string auxhint_name("AUX_HINT_NAME"); + std::string auxhint_value("AUX_HINT_VALUE"); + char* c_auxhint_name = const_cast(auxhint_name.c_str()); + char* c_auxhint_value = const_cast(auxhint_value.c_str()); + + tizen_policy_add_aux_hint(policy_res, surface_res, auxhint_id, + c_auxhint_name, c_auxhint_value); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->mAuxHintId == auxhint_id); + EXPECT_TRUE(policy_surface->mAuxHintName.compare(auxhint_name) == false) + << policy_surface->mAuxHintName << ", " << auxhint_name; + EXPECT_TRUE(policy_surface->mAuxHintValue.compare(auxhint_value) == false) + << policy_surface->mAuxHintValue << ", " << auxhint_value; +} + +TEST_F(PolicyTest, Req_PolicySurfaceChangeAuxHint) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + int32_t auxhint_id = 100; + std::string auxhint_value("AUX_HINT_VALUE"); + char* c_auxhint_value = const_cast(auxhint_value.c_str()); + + tizen_policy_change_aux_hint(policy_res, surface_res, auxhint_id, + c_auxhint_value); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->mAuxHintId == auxhint_id); + EXPECT_TRUE(policy_surface->mAuxHintValue.compare(auxhint_value) == false) + << policy_surface->mAuxHintValue << ", " << auxhint_value; +} + +TEST_F(PolicyTest, Req_PolicySurfaceDeleteAuxHint) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + int32_t auxhint_id = 100; + + tizen_policy_del_aux_hint(policy_res, surface_res, auxhint_id); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->mAuxHintId == auxhint_id); +} + +TEST_F(PolicyTest, Req_PolicySurfaceGetSupportAuxHints) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_get_supported_aux_hints(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bGetSupportedAuxHints); +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetBackgroundState) +{ + int32_t pid = getpid(); + + tizen_policy_set_background_state(policy_res, pid); + client->RoundTrip(); + + EXPECT_TRUE(comp->mPid == pid); +} + +TEST_F(PolicyTest, Req_PolicySurfaceUnsetBackgroundState) +{ + int32_t pid = getpid(); + + tizen_policy_unset_background_state(policy_res, pid); + client->RoundTrip(); + + EXPECT_TRUE(comp->mPid == pid); +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetFloatingMode) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_set_floating_mode(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bSetFloatingMode == true); +} + +TEST_F(PolicyTest, Req_PolicySurfaceUnsetFloatingMode) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_unset_floating_mode(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bSetFloatingMode == false); +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetStackMode) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_set_floating_mode(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bSetFloatingMode == true); +} + +TEST_F(PolicyTest, Req_PolicySurfaceGetSubsurfaceWatcher) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + struct tizen_subsurface_watcher *subsuface_watcher_res; + + subsuface_watcher_res = tizen_policy_get_subsurface_watcher(policy_res, surface_res); + EXPECT_TRUE(subsuface_watcher_res != NULL); + + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bGetSubsurfaceWatcher == true); + + tizen_subsurface_watcher_destroy(subsuface_watcher_res); +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetParent) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + struct wl_surface *parent_surface_res; + + parent_surface_res = wl_compositor_create_surface(compositor_res); + if (!parent_surface_res) + return; + + tizen_policy_set_parent(policy_res, surface_res, parent_surface_res); + + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->mParentSurface); +} + +TEST_F(PolicyTest, Req_PolicySurfaceAckConformantRegion) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + uint32_t serial = 100; + + tizen_policy_ack_conformant_region(policy_res, surface_res, serial); + + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->mSerial == serial); +} + +TEST_F(PolicyTest, Req_PolicySurfaceHasVideo) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + bool has_video = true; + + tizen_policy_has_video(policy_res, surface_res, (uint32_t)has_video); + + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bVideo == has_video); +} + +TEST_F(PolicyTest, Req_PolicySurfaceShow) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_show(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + + EXPECT_TRUE(policy_surface->bShow == true); +} + +TEST_F(PolicyTest, Req_PolicySurfaceHide) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + + tizen_policy_hide(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bHide == true); +} + +TEST_F(PolicyTest, Req_PolicySurfaceSetParentWithBelow) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + struct wl_surface *parent_surface_res; + + parent_surface_res = wl_compositor_create_surface(compositor_res); + if (!parent_surface_res) + return; + + tizen_policy_set_parent_with_below(policy_res, surface_res, + parent_surface_res); + + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->mParentSurface); +} + +TEST_F(PolicyTest, Ev_PolicySurfaceConformant) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + bool is_conformant = true; + + tizen_policy_get_conformant(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bGetConformant); + + policy_surface->SendConformant(is_conformant); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->mSurfaceRes == surface_res); + EXPECT_TRUE(client->mIsConformant == is_conformant); +} + +TEST_F(PolicyTest, Ev_PolicySurfaceConformant_Area) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + enum ds_tizen_policy_conformant_part part = + DS_TIZEN_POLICY_CONFORMANT_PART_INDICATOR; + bool visible = 1; + int32_t x = 100, y = 200, w = 300, h = 400; + + tizen_policy_get_conformant(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bGetConformant); + + policy_surface->SendConformantArea(part, visible, x, y, w, h); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->mSurfaceRes == surface_res); + EXPECT_TRUE(client->mConformantPart == TIZEN_POLICY_CONFORMANT_PART_INDICATOR); + EXPECT_TRUE(client->mState == (uint32_t)visible); + EXPECT_TRUE(client->mX == x); + EXPECT_TRUE(client->mY == y); + EXPECT_TRUE(client->mW == w); + EXPECT_TRUE(client->mH == h); +} + +TEST_F(PolicyTest, Ev_PolicySurfaceNotificationDone) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + int32_t noti_level = TIZEN_POLICY_LEVEL_HIGH; + enum ds_tizen_policy_notification_level notification_level = + DS_TIZEN_POLICY_NOTIFICATION_LEVEL_HIGH; + + tizen_policy_set_notification_level(policy_res, surface_res, noti_level); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->mNotificationLevel == notification_level); + + policy_surface->SendNotificationDone(notification_level, + DS_TIZEN_POLICY_ERROR_STATE_NONE); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->mSurfaceRes == surface_res); + EXPECT_TRUE(client->mLevel == noti_level); + EXPECT_TRUE(client->mErrorState == TIZEN_POLICY_ERROR_STATE_NONE); +} + +TEST_F(PolicyTest, Ev_PolicySurfaceWindowScreenModeDone) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + uint32_t screen_mode = TIZEN_POLICY_MODE_ALWAYS_ON; + enum ds_tizen_policy_window_screen_mode window_screen_mode = + DS_TIZEN_POLICY_WINDOW_SCREEN_MODE_ALWAYS_ON; + + tizen_policy_set_window_screen_mode(policy_res, surface_res, screen_mode); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->mWindowScreenMode == window_screen_mode); + + policy_surface->SendWindowScreenModeDone(window_screen_mode, + DS_TIZEN_POLICY_ERROR_STATE_NONE); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->mSurfaceRes == surface_res); + EXPECT_TRUE(client->mWindowScreenMode == window_screen_mode); + EXPECT_TRUE(client->mErrorState == TIZEN_POLICY_ERROR_STATE_NONE); +} + +TEST_F(PolicyTest, Ev_PolicySurfaceIconifyStateChanged) +{ + MockPolicySurface *policy_surface; + uint32_t surface_res_id; + bool iconified = true; + bool force = true; + + tizen_policy_iconify(policy_res, surface_res); + client->RoundTrip(); + + surface_res_id = wl_proxy_get_id((struct wl_proxy *)surface_res); + policy_surface = comp->FindPolicySurfaceWidthResId(surface_res_id); + EXPECT_TRUE(policy_surface->bIconify == true); + + policy_surface->SendIconifyStateChanged(iconified, force); + comp->Process(); + + client->RoundTrip(); + EXPECT_TRUE(client->mSurfaceRes == surface_res); + EXPECT_TRUE(client->mIconified == iconified); + EXPECT_TRUE(client->mForce == force); +} + +TEST_F(PolicyTest, Ev_PolicySurfaceSupportedAuxHits) +{ + // TODO: +} + +TEST_F(PolicyTest, Ev_PolicySurfaceAllowedAuxHint) +{ + // TODO: +} + +TEST_F(PolicyTest, Ev_PolicySurfaceAuxMessage) +{ + // TODO: +} + +TEST_F(PolicyTest, Ev_PolicySurfaceConformantRegion) +{ +} + +TEST_F(PolicyTest, Ev_PolicySurfaceInteractiveModeDone) +{ + // TODO: +} + +TEST_F(PolicyTest, Ev_PolicySurfaceInteractiveResizeDone) +{ + // TODO: +} -- 2.7.4 From 6a86b7c2db782d8dfea4b696c29482fb518606c0 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Sat, 3 Sep 2022 10:12:39 +0900 Subject: [PATCH 16/16] tinyds-tdm: create ds_tizen_policy resource ds_tizen_policy provide the wayland server implementation of tizen_policy_interface. Change-Id: I056fae55b3dcd1b8b9d3a493a6f525cd4704a7f4 --- examples/meson.build | 1 + examples/tinyds-tdm.c | 965 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 965 insertions(+), 1 deletion(-) diff --git a/examples/meson.build b/examples/meson.build index 2d5c09c..6a81cbf 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -33,6 +33,7 @@ executable('tinyds-tdm', deps_libds_tizen_launch, deps_libds_tizen_input_method, deps_libds_tizen_text_input, + deps_libds_tizen_policy, dependency('pixman-1', required: true), dependency('threads', required: true), ], diff --git a/examples/tinyds-tdm.c b/examples/tinyds-tdm.c index 26ff72c..0c9c968 100644 --- a/examples/tinyds-tdm.c +++ b/examples/tinyds-tdm.c @@ -30,6 +30,7 @@ #include #include #include +#include #define USE_TDM_BUFFER_QUEUE @@ -84,6 +85,99 @@ struct tinyds_dpms struct wl_listener get_dpms; }; +struct tinyds_policy +{ + struct ds_tizen_policy *policy; + + struct wl_listener destroy; + struct wl_listener get_surface; + struct wl_listener activate_below_by_univeral_id; + struct wl_listener lower_by_universal_id; + struct wl_listener set_transient_for; + struct wl_listener unset_transient_for; + struct wl_listener place_subsurface_below_parent; + struct wl_listener set_subsurface_stand_alone; + struct wl_listener set_background_state; + struct wl_listener unset_background_state; + struct wl_listener add_activate_above_by_universal_id; + struct wl_listener set_appid; + struct wl_listener set_transient_for_below; + + struct wl_list policy_surfaces; +}; + +struct tinyds_policy_surface +{ + struct ds_tizen_policy_surface *policy_surface; + + struct wl_listener destroy; + struct wl_listener get_visibility; + struct wl_listener get_position; + struct wl_listener activate; + struct wl_listener raise; + struct wl_listener lower; + struct wl_listener set_focus_skip; + struct wl_listener unset_focus_skip; + struct wl_listener set_role; + struct wl_listener set_window_type; + struct wl_listener set_conformant; + struct wl_listener unset_conformant; + struct wl_listener get_conformant; + struct wl_listener set_notification_level; + struct wl_listener set_window_screen_mode; + struct wl_listener get_subsurface; + struct wl_listener iconify; + struct wl_listener uniconify; + struct wl_listener add_aux_hint; + struct wl_listener change_aux_hint; + struct wl_listener delete_aux_hint; + struct wl_listener get_supported_aux_hints; + struct wl_listener set_floating_mode; + struct wl_listener unset_floating_mode; + struct wl_listener set_stack_mode; + struct wl_listener get_subsurface_watcher; + struct wl_listener set_parent; + struct wl_listener ack_conformant_region; + struct wl_listener set_video; + struct wl_listener show; + struct wl_listener hide; + struct wl_listener set_parent_with_below; + + struct wl_list visibilities; + struct wl_list positions; + struct wl_list subsurface_watchers; + + struct wl_list link; //tinyds_policy::policy_surfaces +}; + +struct tinyds_policy_visibility +{ + struct ds_tizen_policy_visibility *visibility; + + struct wl_listener destroy; + + struct wl_list link; //tinyds_policy::visibilities +}; + +struct tinyds_policy_position +{ + struct ds_tizen_policy_position *position; + + struct wl_listener destroy; + struct wl_listener set; + + struct wl_list link; //tinyds_policy::positions +}; + +struct tinyds_policy_subsurface_watcher +{ + struct ds_tizen_policy_subsurface_watcher *subsurface_watcher; + + struct wl_listener destroy; + + struct wl_list link; //tinyds_policy::subsurface_watchers +}; + struct tinyds_server { struct ds_tbm_server *tbm_server; @@ -103,6 +197,8 @@ struct tinyds_server struct tinyds_output *output; struct tinyds_dpms *dpms; + struct tinyds_policy *policy; + struct wl_event_source *stdin_source; struct wl_list views; @@ -276,7 +372,7 @@ static void server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev); static void server_add_touch(struct tinyds_server *server, struct ds_input_device *dev); - +static bool new_policy(struct tinyds_server *server); static struct tinyds_view * server_view_at(struct tinyds_server *server, double lx, double ly, double *sx, double *sy); @@ -862,6 +958,9 @@ init_server(struct tinyds_server *server, struct wl_display *display) if (!add_new_dpms(server)) goto err; + if (!new_policy(server)) + goto err; + server->seat = ds_seat_create(display, "seat0" /* arbitrary name */); if (!server->seat) goto err; @@ -2473,3 +2572,867 @@ add_new_input_method_context(struct tinyds_input_method *input_method, return true; } + +static void +visibility_handle_destroy(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_visibility *visibility; + + visibility = wl_container_of(listener, visibility, destroy); + + ds_inf("Policy Visibility(%p) destroy", visibility); + + wl_list_remove(&visibility->link); + free(visibility); +} + +static void +position_handle_destroy(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_position *position; + + position = wl_container_of(listener, position, destroy); + + ds_inf("Policy Position(%p) destroy", position); + + wl_list_remove(&position->link); + free(position); +} + +static void +position_handle_set(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_position *position; + + position = wl_container_of(listener, position, set); + + ds_inf("Policy Position(%p) set", position); + + // TODO: +} + +static void +subsurface_watcher_handle_destroy(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_subsurface_watcher *subsurface_watcher; + + subsurface_watcher = wl_container_of(listener, subsurface_watcher, destroy); + + ds_inf("Policy Subsurface_Watcher(%p) destroy", subsurface_watcher); + + wl_list_remove(&subsurface_watcher->link); + free(subsurface_watcher); +} + +static void +policy_surface_handle_destroy(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, destroy); + + ds_inf("Policy Info(%p) destroy", policy_surface); + + wl_list_remove(&policy_surface->link); + free(policy_surface); +} + +static void +policy_surface_handle_get_visibility(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + struct tinyds_policy_visibility *visibility; + struct ds_tizen_event_policy_surface_get_visibility *event; + + policy_surface = wl_container_of(listener, policy_surface, get_visibility); + event = (struct ds_tizen_event_policy_surface_get_visibility *)data; + + ds_inf("Policy Info(%p) get_visibility", policy_surface); + + visibility = calloc(1, sizeof *visibility); + if (!visibility) + return; + + visibility->visibility = event->visibility; + + visibility->destroy.notify = visibility_handle_destroy; + ds_tizen_policy_visibility_add_destroy_listener(visibility->visibility, + &visibility->destroy); + + wl_list_insert(&policy_surface->visibilities, &visibility->link); +} + +static void +policy_surface_handle_get_position(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + struct tinyds_policy_position *position; + struct ds_tizen_event_policy_surface_get_position *event; + + policy_surface = wl_container_of(listener, policy_surface, get_position); + event = (struct ds_tizen_event_policy_surface_get_position *)data; + + ds_inf("Policy Info(%p) get_position", policy_surface); + + position = calloc(1, sizeof *position); + if (!position) + return; + + position->position = event->position; + + position->destroy.notify = position_handle_destroy; + ds_tizen_policy_position_add_destroy_listener(position->position, + &position->destroy); + + position->set.notify = position_handle_set; + ds_tizen_policy_position_add_set_listener(position->position, + &position->set); + + wl_list_insert(&policy_surface->positions, &position->link); +} + +static void +policy_surface_handle_activate(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, activate); + + ds_inf("Policy Info(%p) activate", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_raise(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, raise); + + ds_inf("Policy Info(%p) raise", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_lower(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, raise); + + ds_inf("Policy Info(%p) lower", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_set_focus_skip(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_focus_skip); + + ds_inf("Policy Info(%p) set_focus_skip", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_unset_focus_skip(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, unset_focus_skip); + + ds_inf("Policy Info(%p) unset_focus_skip", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_set_role(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_role); + + ds_inf("Policy Info(%p) set_role", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_set_window_type(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_window_type); + + ds_inf("Policy Info(%p) set_window_type", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_set_conformant(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_conformant); + + ds_inf("Policy Info(%p) set_conformant", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_unset_conformant(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, unset_conformant); + + ds_inf("Policy Info(%p) unset_conformant", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_get_conformant(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, get_conformant); + + ds_inf("Policy Info(%p) get_conformant", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_set_notification_level(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_notification_level); + + ds_inf("Policy Info(%p) set_notification_level", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_set_window_screen_mode(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_window_screen_mode); + + ds_inf("Policy Info(%p) set_window_screen_mode", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_get_subsurface(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, get_subsurface); + + ds_inf("Policy Info(%p) get_subsurface", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_iconify(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, iconify); + + ds_inf("Policy Info(%p) iconify", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_uniconify(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, uniconify); + + ds_inf("Policy Info(%p) uniconify", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_add_aux_hint(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, add_aux_hint); + + ds_inf("Policy Info(%p) add_aux_hint", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_change_aux_hint(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, change_aux_hint); + + ds_inf("Policy Info(%p) change_aux_hint", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_delete_aux_hint(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, delete_aux_hint); + + ds_inf("Policy Info(%p) delete_aux_hint", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_get_supported_aux_hints(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, get_supported_aux_hints); + + ds_inf("Policy Info(%p) get_supported_aux_hints", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_set_floating_mode(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_floating_mode); + + ds_inf("Policy Info(%p) set_floating_mode", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_unset_floating_mode(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, unset_floating_mode); + + ds_inf("Policy Info(%p) unset_floating_mode", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_set_stack_mode(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_stack_mode); + + ds_inf("Policy Info(%p) set_stack_mode", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_get_subsurface_watcher(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + struct tinyds_policy_subsurface_watcher*subsurface_watcher; + struct ds_tizen_event_policy_surface_get_subsurface_watcher *event; + + policy_surface = wl_container_of(listener, policy_surface, get_subsurface_watcher); + event = (struct ds_tizen_event_policy_surface_get_subsurface_watcher *)data; + + ds_inf("Policy Info(%p) get_subsurface_watcher", policy_surface); + + subsurface_watcher = calloc(1, sizeof *subsurface_watcher); + if (!subsurface_watcher) + return; + + subsurface_watcher->subsurface_watcher = event->subsurface_watcher; + + subsurface_watcher->destroy.notify = subsurface_watcher_handle_destroy; + ds_tizen_policy_subsurface_watcher_add_destroy_listener(subsurface_watcher->subsurface_watcher, + &subsurface_watcher->destroy); + + wl_list_insert(&policy_surface->subsurface_watchers, &subsurface_watcher->link); +} + +static void +policy_surface_handle_set_parent(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_parent); + + ds_inf("Policy Info(%p) set_parent", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_ack_conformant_region(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, ack_conformant_region); + + ds_inf("Policy Info(%p) ack_conformant_region", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_set_video(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_video); + + ds_inf("Policy Info(%p) set_video", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_show(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, show); + + ds_inf("Policy Info(%p) show", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_hide(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, hide); + + ds_inf("Policy Info(%p) hide", policy_surface); + + // TODO: +} + +static void +policy_surface_handle_set_parent_with_below(struct wl_listener *listener, void *data) +{ + struct tinyds_policy_surface *policy_surface; + + policy_surface = wl_container_of(listener, policy_surface, set_parent_with_below); + + ds_inf("Policy Info(%p) set_parent_with_below", policy_surface); + + // TODO: +} + +static void +policy_handle_destroy(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, destroy); + + ds_inf("Policy(%p) destroy", policy); + + free(policy); +} + +static void +policy_handle_get_surface(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + struct tinyds_policy_surface *policy_surface; + struct ds_tizen_event_policy_get_surface *event; + + policy = wl_container_of(listener, policy, get_surface); + event = (struct ds_tizen_event_policy_get_surface *)data; + + ds_inf("Policy(%p) get_surface", policy); + + policy_surface = calloc(1, sizeof *policy_surface); + if (!policy_surface) + return; + + policy_surface->policy_surface = event->policy_surface; + + policy_surface->destroy.notify = policy_surface_handle_destroy; + ds_tizen_policy_surface_add_destroy_listener(policy_surface->policy_surface, + &policy_surface->destroy); + + policy_surface->get_visibility.notify = policy_surface_handle_get_visibility; + ds_tizen_policy_surface_add_get_visibility_listener(policy_surface->policy_surface, + &policy_surface->get_visibility); + + policy_surface->get_position.notify = policy_surface_handle_get_position; + ds_tizen_policy_surface_add_get_position_listener(policy_surface->policy_surface, + &policy_surface->get_position); + + policy_surface->activate.notify = policy_surface_handle_activate; + ds_tizen_policy_surface_add_activate_listener(policy_surface->policy_surface, + &policy_surface->activate); + + policy_surface->raise.notify = policy_surface_handle_raise; + ds_tizen_policy_surface_add_raise_listener(policy_surface->policy_surface, + &policy_surface->raise); + + policy_surface->lower.notify = policy_surface_handle_lower; + ds_tizen_policy_surface_add_lower_listener(policy_surface->policy_surface, + &policy_surface->lower); + + policy_surface->set_focus_skip.notify = policy_surface_handle_set_focus_skip; + ds_tizen_policy_surface_add_set_focus_skip_listener(policy_surface->policy_surface, + &policy_surface->set_focus_skip); + + policy_surface->unset_focus_skip.notify = policy_surface_handle_unset_focus_skip; + ds_tizen_policy_surface_add_unset_focus_skip_listener(policy_surface->policy_surface, + &policy_surface->unset_focus_skip); + + policy_surface->set_role.notify = policy_surface_handle_set_role; + ds_tizen_policy_surface_add_set_role_listener(policy_surface->policy_surface, + &policy_surface->set_role); + + policy_surface->set_window_type.notify = policy_surface_handle_set_window_type; + ds_tizen_policy_surface_add_set_window_type_listener(policy_surface->policy_surface, + &policy_surface->set_window_type); + + policy_surface->set_conformant.notify = policy_surface_handle_set_conformant; + ds_tizen_policy_surface_add_set_conformant_listener(policy_surface->policy_surface, + &policy_surface->set_conformant); + + policy_surface->unset_conformant.notify = policy_surface_handle_unset_conformant; + ds_tizen_policy_surface_add_unset_conformant_listener(policy_surface->policy_surface, + &policy_surface->unset_conformant); + + policy_surface->get_conformant.notify = policy_surface_handle_get_conformant; + ds_tizen_policy_surface_add_get_conformant_listener(policy_surface->policy_surface, + &policy_surface->get_conformant); + + policy_surface->set_notification_level.notify = + policy_surface_handle_set_notification_level; + ds_tizen_policy_surface_add_set_notification_level_listener( + policy_surface->policy_surface, &policy_surface->set_notification_level); + + policy_surface->set_window_screen_mode.notify = + policy_surface_handle_set_window_screen_mode; + ds_tizen_policy_surface_add_set_window_screen_mode_listener( + policy_surface->policy_surface, &policy_surface->set_window_screen_mode); + + policy_surface->get_subsurface.notify = policy_surface_handle_get_subsurface; + ds_tizen_policy_surface_add_get_subsurface_listener(policy_surface->policy_surface, + &policy_surface->get_subsurface); + + policy_surface->iconify.notify = policy_surface_handle_iconify; + ds_tizen_policy_surface_add_iconify_listener(policy_surface->policy_surface, + &policy_surface->iconify); + + policy_surface->uniconify.notify = policy_surface_handle_uniconify; + ds_tizen_policy_surface_add_uniconify_listener(policy_surface->policy_surface, + &policy_surface->uniconify); + + policy_surface->add_aux_hint.notify = policy_surface_handle_add_aux_hint; + ds_tizen_policy_surface_add_add_aux_hint_listener(policy_surface->policy_surface, + &policy_surface->add_aux_hint); + + policy_surface->change_aux_hint.notify = policy_surface_handle_change_aux_hint; + ds_tizen_policy_surface_add_change_aux_hint_listener(policy_surface->policy_surface, + &policy_surface->change_aux_hint); + + policy_surface->delete_aux_hint.notify = policy_surface_handle_delete_aux_hint; + ds_tizen_policy_surface_add_delete_aux_hint_listener(policy_surface->policy_surface, + &policy_surface->delete_aux_hint); + + policy_surface->get_supported_aux_hints.notify = + policy_surface_handle_get_supported_aux_hints; + ds_tizen_policy_surface_add_get_supported_aux_hints_listener( + policy_surface->policy_surface, &policy_surface->get_supported_aux_hints); + + policy_surface->set_floating_mode.notify = + policy_surface_handle_set_floating_mode; + ds_tizen_policy_surface_add_set_floating_mode_listener( + policy_surface->policy_surface, &policy_surface->set_floating_mode); + + policy_surface->unset_floating_mode.notify = + policy_surface_handle_unset_floating_mode; + ds_tizen_policy_surface_add_unset_floating_mode_listener( + policy_surface->policy_surface, &policy_surface->unset_floating_mode); + + policy_surface->set_stack_mode.notify = policy_surface_handle_set_stack_mode; + ds_tizen_policy_surface_add_set_stack_mode_listener(policy_surface->policy_surface, + &policy_surface->set_stack_mode); + + policy_surface->get_subsurface_watcher.notify = + policy_surface_handle_get_subsurface_watcher; + ds_tizen_policy_surface_add_get_subsurface_watcher_listener( + policy_surface->policy_surface, &policy_surface->get_subsurface_watcher); + + policy_surface->set_parent.notify = policy_surface_handle_set_parent; + ds_tizen_policy_surface_add_set_parent_listener(policy_surface->policy_surface, + &policy_surface->set_parent); + + policy_surface->ack_conformant_region.notify = + policy_surface_handle_ack_conformant_region; + ds_tizen_policy_surface_add_ack_conformant_region_listener( + policy_surface->policy_surface, &policy_surface->ack_conformant_region); + + policy_surface->set_video.notify = policy_surface_handle_set_video; + ds_tizen_policy_surface_add_set_video_listener(policy_surface->policy_surface, + &policy_surface->set_video); + + policy_surface->show.notify = policy_surface_handle_show; + ds_tizen_policy_surface_add_show_listener(policy_surface->policy_surface, + &policy_surface->show); + + policy_surface->hide.notify = policy_surface_handle_hide; + ds_tizen_policy_surface_add_hide_listener(policy_surface->policy_surface, + &policy_surface->hide); + + policy_surface->set_parent_with_below.notify = + policy_surface_handle_set_parent_with_below; + ds_tizen_policy_surface_add_set_parent_with_below_listener( + policy_surface->policy_surface, &policy_surface->set_parent_with_below); + + + wl_list_init(&policy_surface->visibilities); + wl_list_init(&policy_surface->positions); + wl_list_init(&policy_surface->subsurface_watchers); + + wl_list_insert(&policy->policy_surfaces, &policy_surface->link); +} + +static void +policy_handle_activate_below_by_univeral_id(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, activate_below_by_univeral_id); + + ds_inf("Policy(%p) activate_below_by_univeral_id", policy); + + // TODO: +} + +static void +policy_handle_lower_by_universal_id(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, lower_by_universal_id); + + ds_inf("Policy(%p) lower_by_universal_id", policy); + + // TODO: +} + +static void +policy_handle_set_transient_for(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, set_transient_for); + + ds_inf("Policy(%p) set_transient_for", policy); + + // TODO: +} + +static void +policy_handle_unset_transient_for(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, unset_transient_for); + + ds_inf("Policy(%p) unset_transient_for", policy); + + // TODO: +} + +static void +policy_handle_place_subsurface_below_parent(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, place_subsurface_below_parent); + + ds_inf("Policy(%p) place_subsurface_below_parent", policy); + + // TODO: +} + +static void +policy_handle_set_subsurface_stand_alone(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, set_subsurface_stand_alone); + + ds_inf("Policy(%p) set_subsurface_stand_alone", policy); + + // TODO: +} + +static void +policy_handle_set_background_state(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, set_background_state); + + ds_inf("Policy(%p) set_background_state", policy); + + // TODO: +} + +static void +policy_handle_unset_background_state(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, unset_background_state); + + ds_inf("Policy(%p) unset_background_state", policy); + + // TODO: +} + +static void +policy_handle_add_activate_above_by_universal_id(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, add_activate_above_by_universal_id); + + ds_inf("Policy(%p) add_activate_above_by_universal_id", policy); + + // TODO: +} + +static void +policy_handle_set_appid(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, set_appid); + + ds_inf("Policy(%p) set_appid", policy); + + // TODO: +} + +static void +policy_handle_set_transient_for_below(struct wl_listener *listener, void *data) +{ + struct tinyds_policy *policy; + + policy = wl_container_of(listener, policy, set_transient_for_below); + + ds_inf("Policy(%p) set_transient_for_below", policy); + + // TODO: +} + +static bool +new_policy(struct tinyds_server *server) +{ + struct tinyds_policy *policy; + + policy = calloc(1, sizeof *policy); + if (!policy) + return false; + + policy->policy = ds_tizen_policy_create(server->display); + if (!policy->policy) { + free(policy); + ds_err("Could not create ds_tizen_policy"); + return false; + } + + policy->destroy.notify = policy_handle_destroy; + ds_tizen_policy_add_destroy_listener(policy->policy, &policy->destroy); + + policy->get_surface.notify = policy_handle_get_surface; + ds_tizen_policy_add_get_surface_listener(policy->policy, &policy->get_surface); + + policy->activate_below_by_univeral_id.notify = + policy_handle_activate_below_by_univeral_id; + ds_tizen_policy_add_activate_below_by_univeral_id_listener(policy->policy, + &policy->activate_below_by_univeral_id); + + policy->lower_by_universal_id.notify = policy_handle_lower_by_universal_id; + ds_tizen_policy_add_lower_by_universal_id_listener(policy->policy, + &policy->lower_by_universal_id); + + policy->set_transient_for.notify = policy_handle_set_transient_for; + ds_tizen_policy_add_set_transient_for_listener(policy->policy, + &policy->set_transient_for); + + policy->unset_transient_for.notify = policy_handle_unset_transient_for; + ds_tizen_policy_add_unset_transient_for_listener(policy->policy, + &policy->unset_transient_for); + + policy->place_subsurface_below_parent.notify = + policy_handle_place_subsurface_below_parent; + ds_tizen_policy_add_place_subsurface_below_parent_listener(policy->policy, + &policy->place_subsurface_below_parent); + + policy->set_subsurface_stand_alone.notify = + policy_handle_set_subsurface_stand_alone; + ds_tizen_policy_add_set_subsurface_stand_alone_listener(policy->policy, + &policy->set_subsurface_stand_alone); + + policy->set_background_state.notify = policy_handle_set_background_state; + ds_tizen_policy_add_set_background_state_listener(policy->policy, + &policy->destroy); + + policy->unset_background_state.notify = policy_handle_unset_background_state; + ds_tizen_policy_add_unset_background_state_listener(policy->policy, + &policy->unset_background_state); + + policy->add_activate_above_by_universal_id.notify = + policy_handle_add_activate_above_by_universal_id; + ds_tizen_policy_add_activate_above_by_universal_id_listener(policy->policy, + &policy->add_activate_above_by_universal_id); + + policy->set_appid.notify = policy_handle_set_appid; + ds_tizen_policy_add_set_appid_listener(policy->policy, &policy->set_appid); + + policy->set_transient_for_below.notify = + policy_handle_set_transient_for_below; + ds_tizen_policy_add_set_transient_for_below_listener(policy->policy, + &policy->set_transient_for_below); + + wl_list_init(&policy->policy_surfaces); + + server->policy = policy; + + ds_inf("Policy (%p) created", policy); + + return true; +} -- 2.7.4