--- /dev/null
+#ifndef LIBDS_TIZEN_INPUT_METHOD_H
+#define LIBDS_TIZEN_INPUT_METHOD_H
+
+#include <stdint.h>
+#include <wayland-server.h>
+#include <libds/seat.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ds_tizen_input_method_context_event_commit_string
+{
+ uint32_t serial;
+ const char *text;
+};
+
+struct ds_tizen_input_method_context_event_preedit_string
+{
+ uint32_t serial;
+ const char *text, *commit;
+};
+
+struct ds_tizen_input_method_context_event_preedit_styling
+{
+ uint32_t index, length, style;
+};
+
+struct ds_tizen_input_method_context_event_preedit_cursor
+{
+ int32_t index;
+};
+
+struct ds_tizen_input_method_context_event_delete_surrounding_text
+{
+ int32_t index;
+ uint32_t length;
+};
+
+struct ds_tizen_input_method_context_event_cursor_position
+{
+ int32_t index, anchor;
+};
+
+struct ds_tizen_input_method_context_event_modifiers_map
+{
+ struct wl_array *map;
+};
+
+struct ds_tizen_input_method_context_event_keysym
+{
+ uint32_t serial, time, sym, state, modifiers;
+};
+
+struct ds_tizen_input_method_context_event_language
+{
+ uint32_t serial;
+ const char *language;
+};
+
+struct ds_tizen_input_method_context_event_text_direction
+{
+ uint32_t serial, direction;
+};
+
+//input_method
+struct ds_tizen_input_method *
+ds_tizen_input_method_create(struct wl_display *display);
+
+struct ds_tizen_input_method_context *
+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,
+ struct ds_tizen_input_method_context *context);
+void ds_tizen_input_method_send_deactivate(struct ds_tizen_input_method *im,
+ struct ds_tizen_input_method_context *context);
+
+//input_method_context
+void
+ds_tizen_input_method_context_add_destroy_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_commit_string_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_preedit_string_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_preedit_styling_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_preedit_cursor_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_delete_surrounding_text_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_cursor_position_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_modifiers_map_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_keysym_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_grab_keyboard_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_key_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_modifiers_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_language_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+void
+ds_tizen_input_method_context_add_text_direction_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener);
+
+// events
+void
+ds_tizen_input_method_context_send_surrounding_text(struct ds_tizen_input_method_context *context,
+ const char *text, uint32_t cursor, uint32_t anchor);
+void
+ds_tizen_input_method_context_send_reset(struct ds_tizen_input_method_context *context);
+void
+ds_tizen_input_method_context_send_content_type(
+ struct ds_tizen_input_method_context *context, uint32_t hint, uint32_t purpose);
+void
+ds_tizen_input_method_context_send_invoke_action(
+ struct ds_tizen_input_method_context *context, uint32_t button, uint32_t index);
+void
+ds_tizen_input_method_context_send_commit_state(
+ struct ds_tizen_input_method_context *context, uint32_t serial);
+void
+ds_tizen_input_method_context_send_preferred_language(
+ struct ds_tizen_input_method_context *context, const char *launguage);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+#include <stdlib.h>
+#include <wayland-server.h>
+#include <input-method-server-protocol.h>
+#include <libds/log.h>
+
+#include "util.h"
+#include <libds/seat.h>
+#include <libds-tizen/input_method.h>
+
+#define INPUT_METHOD_VERSION 1
+
+struct ds_tizen_input_method;
+
+struct ds_tizen_input_method_context {
+ struct wl_resource *resource;
+ struct ds_tizen_input_method *input_method;
+
+ struct {
+ struct wl_signal destroy;
+ struct wl_signal commit_string;
+ struct wl_signal preedit_string;
+ struct wl_signal preedit_styling;
+ struct wl_signal preedit_cursor;
+ struct wl_signal delete_surrounding_text;
+ struct wl_signal cursor_position;
+ struct wl_signal modifiers_map;
+ struct wl_signal keysym;
+ struct wl_signal grab_keyboard;
+ struct wl_signal key;
+ struct wl_signal modifiers;
+ struct wl_signal language;
+ struct wl_signal text_direction;
+ } events;
+};
+
+struct ds_tizen_input_method {
+ struct wl_global *global;
+ struct wl_resource *resource;
+ struct ds_tizen_input_method_context *context;
+
+ struct wl_listener destroy;
+
+ struct {
+ struct wl_signal destroy;
+ struct wl_signal new_input_method_context;
+ } events;
+};
+
+static const struct zwp_input_method_context_v1_interface context_impl;
+
+WL_EXPORT void
+ds_tizen_input_method_add_destroy_listener(
+ struct ds_tizen_input_method *im, struct wl_listener *listener)
+{
+ wl_signal_add(&im->events.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)
+{
+ if (!im || !context) return;
+
+ ds_inf("ds_tizen_input_method_send_activate");
+ zwp_input_method_v1_send_activate(im->resource, context->resource);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_send_deactivate(struct ds_tizen_input_method *im,
+ struct ds_tizen_input_method_context *context)
+{
+ if (!im || !context) return;
+
+ ds_inf("ds_tizen_input_method_send_deactivate");
+ zwp_input_method_v1_send_deactivate(im->resource, context->resource);
+}
+
+static void
+context_destroy(struct ds_tizen_input_method_context *context)
+{
+ ds_inf("input_method_context(%p) destroy", context);
+
+ wl_signal_emit(&context->events.destroy, context);
+
+ free(context);
+}
+
+static void
+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;
+ input_method->context = NULL;
+
+ context_destroy(context);
+}
+
+WL_EXPORT struct ds_tizen_input_method_context *
+ds_tizen_input_method_create_context(struct ds_tizen_input_method *input_method)
+{
+ struct ds_tizen_input_method_context *context;
+ struct wl_resource *binding;
+
+ ds_inf("ds_tizen_input_method_create_context");
+ context = calloc(1, sizeof *context);
+ if (context == NULL)
+ return NULL;
+
+ binding = input_method->resource;
+ if (!binding) return NULL;
+ context->resource = wl_resource_create(wl_resource_get_client(binding),
+ &zwp_input_method_context_v1_interface, INPUT_METHOD_VERSION, 0);
+ wl_resource_set_implementation(context->resource, &context_impl,
+ context, input_method_context_client_handle_destroy);
+
+ wl_signal_init(&context->events.destroy);
+ wl_signal_init(&context->events.commit_string);
+ wl_signal_init(&context->events.preedit_string);
+ wl_signal_init(&context->events.preedit_styling);
+ wl_signal_init(&context->events.preedit_cursor);
+ wl_signal_init(&context->events.delete_surrounding_text);
+ wl_signal_init(&context->events.cursor_position);
+ wl_signal_init(&context->events.modifiers_map);
+ wl_signal_init(&context->events.keysym);
+ wl_signal_init(&context->events.grab_keyboard);
+ wl_signal_init(&context->events.key);
+ wl_signal_init(&context->events.modifiers);
+ 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;
+ context->input_method = input_method;
+
+ return context;
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_destroy_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.destroy, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_commit_string_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.commit_string, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_preedit_string_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.preedit_string, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_preedit_styling_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.preedit_styling, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_preedit_cursor_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.preedit_cursor, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_delete_surrounding_text_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.delete_surrounding_text, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_cursor_position_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.cursor_position, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_modifiers_map_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.modifiers_map, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_keysym_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.keysym, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_grab_keyboard_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.grab_keyboard, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_key_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.key, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_modifiers_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.modifiers, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_language_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.language, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_add_text_direction_listener(
+ struct ds_tizen_input_method_context *context, struct wl_listener *listener)
+{
+ wl_signal_add(&context->events.text_direction, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_send_surrounding_text(struct ds_tizen_input_method_context *context,
+ const char *text, uint32_t cursor, uint32_t anchor)
+{
+ if (!context || !context->resource) return;
+
+ ds_inf("ds_tizen_input_method_context_send_surrounding_text");
+ zwp_input_method_context_v1_send_surrounding_text(context->resource, text, cursor, anchor);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_send_reset(
+ struct ds_tizen_input_method_context *context)
+{
+ if (!context || !context->resource) return;
+
+ ds_inf("ds_tizen_input_method_context_send_reset");
+ zwp_input_method_context_v1_send_reset(context->resource);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_send_content_type(
+ struct ds_tizen_input_method_context *context, uint32_t hint, uint32_t purpose)
+{
+ if (!context || !context->resource) return;
+
+ ds_inf("ds_tizen_input_method_context_send_content_type");
+ zwp_input_method_context_v1_send_content_type(context->resource, hint, purpose);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_send_invoke_action(
+ struct ds_tizen_input_method_context *context, uint32_t button, uint32_t index)
+{
+ if (!context || !context->resource) return;
+
+ ds_inf("ds_tizen_input_method_context_send_invoke_action");
+ zwp_input_method_context_v1_send_invoke_action(context->resource, button, index);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_send_commit_state(
+ struct ds_tizen_input_method_context *context, uint32_t serial)
+{
+ if (!context || !context->resource) return;
+
+ ds_inf("ds_tizen_input_method_context_send_commit_state");
+ zwp_input_method_context_v1_send_commit_state(context->resource, serial);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_context_send_preferred_language(
+ struct ds_tizen_input_method_context *context, const char *language)
+{
+ if (!context || !context->resource) return;
+
+ ds_inf("ds_tizen_input_method_context_send_preferred_language");
+ zwp_input_method_context_v1_send_preferred_language(context->resource, language);
+}
+
+static void
+context_handle_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ ds_inf("context_handle_destroy");
+ wl_resource_destroy(resource);
+}
+
+static void
+context_handle_commit_string(struct wl_client *client,
+ struct wl_resource *resource, uint32_t serial, const char *text)
+{
+ struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource);
+ struct ds_tizen_input_method_context_event_commit_string ds_event;
+
+ ds_inf("context_handle_commit_string");
+ ds_event.serial = serial;
+ ds_event.text = text;
+
+ wl_signal_emit(&context->events.commit_string, &ds_event);
+}
+
+static void
+context_handle_preedit_string(struct wl_client *client,
+ struct wl_resource *resource, uint32_t serial, const char *text,
+ const char *commit)
+{
+ struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource);
+ struct ds_tizen_input_method_context_event_preedit_string ds_event;
+
+ ds_inf("context_handle_preedit_string() serial:%u, text:%s, commit:%s",
+ serial, text, commit);
+
+ ds_event.serial = serial;
+ ds_event.text = text;
+ ds_event.commit = commit;
+
+ wl_signal_emit(&context->events.preedit_string, &ds_event);
+}
+
+static void
+context_handle_preedit_styling(struct wl_client *client,
+ struct wl_resource *resource, uint32_t index, uint32_t length,
+ uint32_t style)
+{
+ struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource);
+ struct ds_tizen_input_method_context_event_preedit_styling ds_event;
+
+ ds_inf("context_handle_preedit_styling() index:%u, length:%u, style:%u",
+ index, length, style);
+
+ ds_event.index = index;
+ ds_event.length = length;
+ ds_event.style = style;
+
+ wl_signal_emit(&context->events.preedit_styling, &ds_event);
+}
+
+static void
+context_handle_preedit_cursor(struct wl_client *client,
+ struct wl_resource *resource, int32_t index)
+{
+ struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource);
+ struct ds_tizen_input_method_context_event_preedit_cursor ds_event;
+
+ ds_inf("context_handle_preedit_cursor() cursor:%d", index);
+
+ ds_event.index = index;
+ wl_signal_emit(&context->events.preedit_styling, &ds_event);
+}
+
+static void
+context_handle_delete_surrounding_text(struct wl_client *client,
+ struct wl_resource *resource, int32_t index, uint32_t length)
+{
+ struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource);
+ struct ds_tizen_input_method_context_event_delete_surrounding_text ds_event;
+
+ ds_inf("context_handle_delete_surrounding_text() index:%d, length:%u", index, length);
+
+ ds_event.index = index;
+ ds_event.length = length;
+ wl_signal_emit(&context->events.delete_surrounding_text, &ds_event);
+}
+
+static void
+context_handle_cursor_position(struct wl_client *client,
+ struct wl_resource *resource, int32_t index, int32_t anchor)
+{
+ struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource);
+ struct ds_tizen_input_method_context_event_cursor_position ds_event;
+
+ ds_inf("context_handle_cursor_position() index:%d anchor:%d", index, anchor);
+
+ ds_event.index = index;
+ ds_event.anchor = anchor;
+ wl_signal_emit(&context->events.cursor_position, &ds_event);
+}
+
+static void
+context_handle_modifiers_map(struct wl_client *client,
+ struct wl_resource *resource, struct wl_array *map)
+{
+ struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource);
+ struct ds_tizen_input_method_context_event_modifiers_map ds_event;
+
+ ds_inf("context_handle_modifiers_map() map(%p)", map);
+
+ ds_event.map = map;
+ wl_signal_emit(&context->events.modifiers_map, &ds_event);
+}
+
+static void
+context_handle_keysym(struct wl_client *client, struct wl_resource *resource,
+ uint32_t serial, uint32_t time, uint32_t sym,
+ uint32_t state, uint32_t modifiers)
+{
+ struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource);
+ struct ds_tizen_input_method_context_event_keysym ds_event;
+
+ ds_inf("context_handle_keysym() serial(%u), time(%u), sym(%u), state(%u), modifiers(%u)",
+ serial, time, sym, state, modifiers);
+
+ ds_event.serial = serial;
+ ds_event.time = time;
+ ds_event.sym = sym;
+ ds_event.state = state;
+ ds_event.modifiers = modifiers;
+ wl_signal_emit(&context->events.keysym, &ds_event);
+}
+
+static void
+context_handle_grab_keyboard(struct wl_client *client,
+ struct wl_resource *resource, uint32_t id)
+{
+ ds_inf("context_handle_grab_keyboard() nothing done");
+ //TODO
+}
+
+static void
+context_handle_key(struct wl_client *client, struct wl_resource *resource,
+ uint32_t serial, uint32_t time, uint32_t key, uint32_t state_w)
+{
+ ds_inf("context_handle_key() nothing done");
+ //TODO
+}
+
+static void
+context_handle_modifiers(struct wl_client *client,
+ struct wl_resource *resource, uint32_t serial, uint32_t mods_depressed,
+ uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
+{
+ ds_inf("context_handle_modifiers() nothing done");
+ //TODO
+}
+
+static void
+context_handle_language(struct wl_client *client,
+ struct wl_resource *resource, uint32_t serial, const char *language)
+{
+ struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource);
+ struct ds_tizen_input_method_context_event_language ds_event;
+
+ ds_inf("context_handle_language() serial(%u) language(%s)", serial, language);
+
+ ds_event.serial = serial;
+ ds_event.language = language;
+ wl_signal_emit(&context->events.language, &ds_event);
+}
+
+static void
+context_handle_text_direction(struct wl_client *client,
+ struct wl_resource *resource, uint32_t serial, uint32_t direction)
+{
+ struct ds_tizen_input_method_context *context = wl_resource_get_user_data(resource);
+ struct ds_tizen_input_method_context_event_text_direction ds_event;
+
+ ds_inf("context_handle_text_direction() serial(%u) direction(%u)", serial, direction);
+
+ ds_event.serial = serial;
+ ds_event.direction = direction;
+ wl_signal_emit(&context->events.text_direction, &ds_event);
+}
+
+static const struct zwp_input_method_context_v1_interface context_impl = {
+ .destroy = context_handle_destroy,
+ .commit_string = context_handle_commit_string,
+ .preedit_string = context_handle_preedit_string,
+ .preedit_styling = context_handle_preedit_styling,
+ .preedit_cursor = context_handle_preedit_cursor,
+ .delete_surrounding_text = context_handle_delete_surrounding_text,
+ .cursor_position = context_handle_cursor_position,
+ .modifiers_map = context_handle_modifiers_map,
+ .keysym = context_handle_keysym,
+ .grab_keyboard = context_handle_grab_keyboard,
+ .key = context_handle_key,
+ .modifiers = context_handle_modifiers,
+ .language = context_handle_language,
+ .text_direction = context_handle_text_direction,
+ //for tizen_only
+ .selection_region = NULL,
+ .private_command = NULL,
+ .update_input_panel_data = NULL,
+ .hide_input_panel = NULL,
+ .get_selection_text = NULL,
+ .get_surrounding_text = NULL,
+ .filter_key_event_done = NULL,
+ .update_ise_geometry = NULL,
+ .recapture_string = NULL,
+ .input_panel_event = NULL,
+ .commit_content = NULL,
+ .update_candidate_state = NULL,
+ .reshow_input_panel = NULL,
+ .set_floating_panel = NULL,
+ .set_floating_drag_enabled = NULL,
+};
+
+static void
+input_method_handle_display_destroy(struct wl_listener *listener, void *data)
+{
+ struct ds_tizen_input_method *input_method;
+
+ input_method = wl_container_of(listener, input_method, destroy);
+
+ ds_inf("Global destroy: input_method(%p)", input_method);
+
+ if (input_method->context)
+ context_destroy(input_method->context);
+
+ wl_signal_emit(&input_method->events.destroy, input_method);
+ wl_list_remove(&input_method->destroy.link);
+
+ wl_global_destroy(input_method->global);
+ free(input_method);
+}
+
+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)
+{
+ struct ds_tizen_input_method *input_method = data;
+
+ ds_inf("input_method. client binds. (client:%p)", wl_client);
+
+ input_method->resource = wl_resource_create(wl_client,
+ &zwp_input_method_v1_interface,
+ version, id);
+ if (input_method->resource == NULL) {
+ ds_err("input_method. wl_resource_create() failed.");
+ wl_client_post_no_memory(wl_client);
+ return;
+ }
+ wl_resource_set_implementation(input_method->resource, NULL,
+ input_method, input_method_client_handle_destroy);
+}
+
+WL_EXPORT struct ds_tizen_input_method *
+ds_tizen_input_method_create(struct wl_display *display)
+{
+ struct ds_tizen_input_method *input_method;
+
+ input_method = calloc(1, sizeof *input_method);
+ if (input_method == NULL) {
+ ds_err("calloc() failed. ds_tizen_input_method");
+ return NULL;
+ }
+
+ input_method->global = wl_global_create(display,
+ &zwp_input_method_v1_interface, INPUT_METHOD_VERSION, input_method, input_method_bind);
+ if (!input_method->global) {
+ free(input_method);
+ return NULL;
+ }
+
+ 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);
+
+ ds_inf("Global create: zwp_input_method_v1. input_method(%p)", input_method);
+
+ return input_method;
+}
--- /dev/null
+#include "tc_main.h"
+#include "mockclient.h"
+#include "mockcompositor.h"
+#include <libds-tizen/input_method.h>
+#include <input-method-server-protocol.h>
+#include <input-method-client-protocol.h>
+
+#define INPUT_METHOD_VERSION 1
+
+class MockInputMethodCompositor : public MockCompositor
+{
+public:
+ MockInputMethodCompositor()
+ : MockCompositor(&MockInputMethodCompositor::TestSetup, this)
+ {
+ ds_inf("%s : this(%p)", __func__, this);
+
+ // initialize the flags to check
+ bDestroyed = false;
+ bNewInputMethodContext = false;
+ }
+
+ ~MockInputMethodCompositor()
+ {
+ ds_inf("%s : this(%p)", __func__, this);
+ }
+
+ static void TestSetup(void *data)
+ {
+ MockInputMethodCompositor *mockComp =
+ static_cast<MockInputMethodCompositor *>(data);
+ Compositor *comp = mockComp->compositor;
+
+ ds_inf("%s: mockComp(%p)", __func__, mockComp);
+
+ mockComp->mInputMethod = ds_tizen_input_method_create(comp->display);
+
+ // destroy listener
+ mockComp->mDestroyListener.notify =
+ MockInputMethodCompositor::DestroyCallback;
+ 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)
+ {
+ ds_inf("%s", __func__);
+
+ MockInputMethodCompositor *mockComp =
+ reinterpret_cast<DestroyListener *>(listener)->parent;
+
+ mockComp->bDestroyed = true;
+ }
+
+ static void NewInputMethodContextCallback(struct wl_listener *listener, void *data)
+ {
+ ds_inf("%s", __func__);
+
+ MockInputMethodCompositor *mockComp =
+ reinterpret_cast<NewInputMethodContextListener *>(listener)->parent;
+ struct ds_tizen_input_method_context *context =
+ static_cast<struct ds_tizen_input_method_context *>(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);
+ }
+
+ void SendActivate()
+ {
+ ds_inf("%s", __func__);
+
+ ds_tizen_input_method_send_activate(mInputMethod, mInputMethodContext);
+ }
+
+ void SendDeactivate()
+ {
+ ds_inf("%s", __func__);
+
+ ds_tizen_input_method_send_deactivate(mInputMethod, mInputMethodContext);
+ }
+
+public:
+ bool bDestroyed;
+ bool bNewInputMethodContext;
+
+private:
+ struct ds_tizen_input_method_manager *mInputMethodMgr;
+ struct ds_tizen_input_method *mInputMethod;
+ struct ds_tizen_input_method_context *mInputMethodContext;
+
+ struct DestroyListener: ::wl_listener {
+ MockInputMethodCompositor *parent;
+ };
+ DestroyListener mDestroyListener;
+
+ struct NewInputMethodContextListener: ::wl_listener {
+ MockInputMethodCompositor *parent;
+ };
+ NewInputMethodContextListener mNewInputMethodContextListener;
+};
+
+class MockInputMethodClient : public MockClient
+{
+public:
+ MockInputMethodClient()
+ : bActivate(false),
+ bDeactivate(false),
+ compositor_res(nullptr),
+ zwp_input_method(nullptr)
+ {}
+
+ MockInputMethodClient(const struct wl_registry_listener *listener)
+ : MockClient(listener, this)
+ {
+ ds_inf("%s", __func__);
+ }
+
+ ~MockInputMethodClient()
+ {
+ ds_inf("%s", __func__);
+ }
+
+ void SetWlCompositor(struct wl_compositor *global_res)
+ {
+ ds_inf("%s", __func__);
+
+ compositor_res = global_res;
+ }
+
+ struct wl_compositor *GetWlCompositor()
+ {
+ ds_inf("%s", __func__);
+
+ return compositor_res;
+ }
+
+ void SetInputMethod(struct zwp_input_method_v1 *global_res)
+ {
+ ds_inf("%s", __func__);
+ zwp_input_method = global_res;
+ }
+
+ struct zwp_input_method_v1 *GetInputMethod()
+ {
+ ds_inf("%s", __func__);
+
+ return zwp_input_method;
+ }
+
+public:
+ bool bActivate;
+ bool bDeactivate;
+
+private:
+ struct wl_compositor *compositor_res;
+ struct zwp_input_method_v1 *zwp_input_method;
+};
+
+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__);
+
+ MockInputMethodClient *client = static_cast<MockInputMethodClient *>(data);
+ struct wl_compositor *compositor_res;
+ struct zwp_input_method_v1 *zwp_input_method;
+
+ 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, "zwp_input_method_v1")) {
+ zwp_input_method = (struct zwp_input_method_v1 *)wl_registry_bind(registry,
+ name, &zwp_input_method_v1_interface, INPUT_METHOD_VERSION);
+ if (zwp_input_method == nullptr) {
+ ds_err("wl_registry_bind() failed. zwp_input_method_v1 resource.");
+ return;
+ }
+ client->SetInputMethod(zwp_input_method);
+ }
+}
+
+static void
+client_registry_cb_global_remove(void *data, struct wl_registry *registry,
+ uint32_t name)
+{
+ ds_inf("%s", __func__);
+
+ MockInputMethodClient *client = static_cast<MockInputMethodClient *>(data);
+ struct wl_compositor *compositor_res = client->GetWlCompositor();
+ struct zwp_input_method_v1 *input_method_res = client->GetInputMethod();
+
+ zwp_input_method_v1_destroy(input_method_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
+};
+
+static void
+im_cb_activate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
+{
+ ds_inf("%s", __func__);
+
+ MockInputMethodClient *client = static_cast<MockInputMethodClient *>(data);
+ client->bActivate = true;
+}
+static void
+im_cb_deactivate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
+{
+ ds_inf("%s", __func__);
+
+ MockInputMethodClient *client = static_cast<MockInputMethodClient *>(data);
+ client->bDeactivate = true;
+}
+static void
+im_cb_destroy (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
+{}
+static void
+im_cb_show_input_panel (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx, uint32_t angle)
+{}
+static void
+im_cb_hide_input_panel (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
+{}
+static void
+im_cb_open_connection (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
+{}
+static void
+im_cb_close_connection (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
+{}
+static void
+im_cb_set_text_input_id (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx, uint32_t text_input_id)
+{}
+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 = im_cb_show_input_panel,
+ .hide_input_panel = im_cb_hide_input_panel,
+ .open_connection = im_cb_open_connection,
+ .close_connection = im_cb_close_connection,
+ .set_text_input_id = im_cb_set_text_input_id,
+};
+
+class InputMethodTest : public ::testing::Test
+{
+public:
+ void SetUp(void) override;
+ void TearDown(void) override;
+
+ MockInputMethodCompositor *comp;
+ MockInputMethodClient *client;
+ struct wl_compositor *compositor_res;
+ struct zwp_input_method_v1 *input_method_res;
+};
+
+void
+InputMethodTest::SetUp(void)
+{
+ ds_log_init(DS_INF, NULL);
+
+ ds_inf("%s", __func__);
+
+ comp = new MockInputMethodCompositor();
+ client = new MockInputMethodClient(®istry_listener);
+ compositor_res = client->GetWlCompositor();
+ input_method_res = client->GetInputMethod();
+
+ zwp_input_method_v1_add_listener(input_method_res,
+ &input_method_cb_listener, client);
+
+ client->RoundTrip();
+}
+
+void
+InputMethodTest::TearDown(void)
+{
+ ds_inf("%s", __func__);
+
+ client->RoundTrip();
+
+ delete client;
+ delete comp;
+}
+
+TEST_F(InputMethodTest, Create_P)
+{
+ EXPECT_TRUE(true);
+}
+
+TEST_F(InputMethodTest, CreateInputMethodContext)
+{
+ comp->CreateInputMethodContext();
+ comp->Process();
+
+ EXPECT_TRUE(comp->bNewInputMethodContext);
+}
+
+TEST_F(InputMethodTest, Ev_Activate)
+{
+ comp->CreateInputMethodContext();
+ comp->Process();
+
+ comp->SendActivate();
+ comp->Process();
+
+ client->RoundTrip();
+ EXPECT_TRUE(client->bActivate);
+}
+
+TEST_F(InputMethodTest, Ev_Deactivate)
+{
+ comp->CreateInputMethodContext();
+ comp->Process();
+
+ comp->SendDeactivate();
+ comp->Process();
+
+ client->RoundTrip();
+ EXPECT_TRUE(client->bDeactivate);
+}