} events;
};
+struct ds_tizen_input_method_manager {
+ struct wl_global *global;
+ struct wl_resource *resource;
+
+ struct wl_listener destroy;
+
+ struct {
+ struct wl_signal destroy;
+ struct wl_signal set_transient_for;
+ } events;
+};
+
static const struct zwp_input_method_context_v1_interface context_impl;
+static const struct zwp_input_method_manager_v1_interface input_method_mgr_impl;
+
+WL_EXPORT void
+ds_tizen_input_method_manager_add_destroy_listener(
+ struct ds_tizen_input_method_manager *im_mgr, struct wl_listener *listener)
+{
+ wl_signal_add(&im_mgr->events.destroy, listener);
+}
+
+WL_EXPORT void
+ds_tizen_input_method_manager_add_set_transient_for_listener(
+ struct ds_tizen_input_method_manager *im_mgr, struct wl_listener *listener)
+{
+ wl_signal_add(&im_mgr->events.set_transient_for, listener);
+}
+
+static void
+input_method_mgr_handle_display_destroy(struct wl_listener *listener, void *data)
+{
+ struct ds_tizen_input_method_manager *input_method_mgr;
+
+ input_method_mgr = wl_container_of(listener, input_method_mgr, destroy);
+
+ ds_inf("Global destroy: input_method_mgr(%p)", input_method_mgr);
+
+ wl_signal_emit(&input_method_mgr->events.destroy, input_method_mgr);
+ wl_list_remove(&input_method_mgr->destroy.link);
+
+ wl_global_destroy(input_method_mgr->global);
+ free(input_method_mgr);
+}
+
+static void
+input_method_mgr_handle_set_transient_for(struct wl_client *wl_client,
+ struct wl_resource *resource, uint32_t parent_pid, uint32_t child_pid)
+{
+ struct ds_tizen_input_method_manager_event_set_transient_for ds_event;
+ struct ds_tizen_input_method_manager *input_method_mgr;
+
+ input_method_mgr = wl_resource_get_user_data(resource);
+
+ ds_inf("input_method_mgr_handle_set_transient_for() parent:%u, child:%u",
+ parent_pid, child_pid);
+
+ ds_event.pid_parent = parent_pid;
+ ds_event.pid_child = child_pid;
+ wl_signal_emit(&input_method_mgr->events.set_transient_for, &ds_event);
+}
+
+static const struct zwp_input_method_manager_v1_interface input_method_mgr_impl =
+{
+ .set_transient_for = input_method_mgr_handle_set_transient_for,
+};
+
+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,
+ &zwp_input_method_manager_v1_interface,
+ version, id);
+ if (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_EXPORT struct ds_tizen_input_method_manager *
+ds_tizen_input_method_manager_create(struct wl_display *display)
+{
+ struct ds_tizen_input_method_manager *input_method_mgr;
+
+ input_method_mgr = calloc(1, sizeof *input_method_mgr);
+ if (input_method_mgr == NULL) {
+ ds_err("calloc() failed. ds_tizen_input_method_manager");
+ return NULL;
+ }
+
+ input_method_mgr->global = wl_global_create(display,
+ &zwp_input_method_manager_v1_interface, INPUT_METHOD_VERSION, input_method_mgr, input_method_mgr_bind);
+ if (!input_method_mgr->global) {
+ free(input_method_mgr);
+ return NULL;
+ }
+
+ wl_signal_init(&input_method_mgr->events.destroy);
+ wl_signal_init(&input_method_mgr->events.set_transient_for);
+
+ input_method_mgr->destroy.notify = input_method_mgr_handle_display_destroy;
+ wl_display_add_destroy_listener(display, &input_method_mgr->destroy);
+
+ ds_inf("Global create: zwp_input_method_manager_v1. input_method_mgr(%p)", input_method_mgr);
+
+ return input_method_mgr;
+}
WL_EXPORT void
ds_tizen_input_method_add_destroy_listener(
--- /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 MockInputMethodMgrCompositor : public MockCompositor
+{
+public:
+ MockInputMethodMgrCompositor()
+ : MockCompositor(&MockInputMethodMgrCompositor::TestSetup, this)
+ {
+ ds_inf("%s : this(%p)", __func__, this);
+
+ // initialize the flags to check
+ bDestroyed = false;
+
+ bSetTransientFor = false;
+ mParentPid = 0;
+ mChildPid = 0;
+ }
+
+ ~MockInputMethodMgrCompositor()
+ {
+ ds_inf("%s : this(%p)", __func__, this);
+ }
+
+ static void TestSetup(void *data)
+ {
+ MockInputMethodMgrCompositor *mockComp =
+ static_cast<MockInputMethodMgrCompositor *>(data);
+ Compositor *comp = mockComp->compositor;
+
+ ds_inf("%s: mockComp(%p)", __func__, mockComp);
+
+ mockComp->mInputMethodMgr = ds_tizen_input_method_manager_create(comp->display);
+
+ // destroy listener
+ mockComp->mDestroyListener.notify =
+ MockInputMethodMgrCompositor::DestroyCallback;
+ mockComp->mDestroyListener.parent = mockComp;
+ ds_tizen_input_method_manager_add_destroy_listener(mockComp->mInputMethodMgr,
+ &mockComp->mDestroyListener);
+
+ // set_transient_for listener
+ mockComp->mSetTransientForListener.notify =
+ MockInputMethodMgrCompositor::SetTransientForCallback;
+ mockComp->mSetTransientForListener.parent = mockComp;
+ ds_tizen_input_method_manager_add_set_transient_for_listener(mockComp->mInputMethodMgr,
+ &mockComp->mSetTransientForListener);
+ }
+
+ static void DestroyCallback(struct wl_listener *listener, void *data)
+ {
+ ds_inf("%s", __func__);
+
+ MockInputMethodMgrCompositor *mockComp =
+ reinterpret_cast<DestroyListener *>(listener)->parent;
+
+ mockComp->bDestroyed = true;
+ }
+
+ static void SetTransientForCallback(struct wl_listener *listener, void *data)
+ {
+ struct ds_tizen_input_method_manager_event_set_transient_for *event =
+ (struct ds_tizen_input_method_manager_event_set_transient_for *)data;
+
+ ds_inf("%s", __func__);
+
+ MockInputMethodMgrCompositor *mockComp =
+ reinterpret_cast<SetTransientForListener *>(listener)->parent;
+
+ mockComp->bSetTransientFor = true;
+ mockComp->mParentPid = event->pid_parent;
+ mockComp->mChildPid = event->pid_child;
+ }
+
+public:
+ bool bDestroyed;
+ bool bSetTransientFor;
+ uint32_t mParentPid;
+ uint32_t mChildPid;
+
+private:
+ struct ds_tizen_input_method_manager *mInputMethodMgr;
+ struct DestroyListener: ::wl_listener {
+ MockInputMethodMgrCompositor *parent;
+ };
+ DestroyListener mDestroyListener;
+
+ struct SetTransientForListener: ::wl_listener {
+ MockInputMethodMgrCompositor *parent;
+ };
+ SetTransientForListener mSetTransientForListener;
+};
+
+class MockInputMethodMgrClient : public MockClient
+{
+public:
+ MockInputMethodMgrClient()
+ : bActivated(false),
+ compositor_res(nullptr),
+ zwp_input_method_manager(nullptr)
+ {}
+
+ MockInputMethodMgrClient(const struct wl_registry_listener *listener)
+ : MockClient(listener, this)
+ {
+ ds_inf("%s", __func__);
+ }
+
+ ~MockInputMethodMgrClient()
+ {
+ 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 SetInputMethodMgr(struct zwp_input_method_manager_v1 *global_res)
+ {
+ ds_inf("%s", __func__);
+ zwp_input_method_manager = global_res;
+ }
+
+ struct zwp_input_method_manager_v1 *GetInputMethodMgr()
+ {
+ ds_inf("%s", __func__);
+
+ return zwp_input_method_manager;
+ }
+
+public:
+ bool bActivated;
+
+private:
+ struct wl_compositor *compositor_res;
+ struct zwp_input_method_manager_v1 *zwp_input_method_manager;
+};
+
+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__);
+
+ MockInputMethodMgrClient *client = static_cast<MockInputMethodMgrClient *>(data);
+ struct wl_compositor *compositor_res;
+ struct zwp_input_method_manager_v1 *zwp_input_method_manager;
+
+ 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_manager_v1")) {
+ zwp_input_method_manager = (struct zwp_input_method_manager_v1 *)wl_registry_bind(registry,
+ name, &zwp_input_method_manager_v1_interface, INPUT_METHOD_VERSION);
+ if (zwp_input_method_manager == nullptr) {
+ ds_err("wl_registry_bind() failed. zwp_input_method_manager_v1 resource.");
+ return;
+ }
+ client->SetInputMethodMgr(zwp_input_method_manager);
+ }
+}
+
+static void
+client_registry_cb_global_remove(void *data, struct wl_registry *registry,
+ uint32_t name)
+{
+ ds_inf("%s", __func__);
+
+ MockInputMethodMgrClient *client = static_cast<MockInputMethodMgrClient *>(data);
+ struct wl_compositor *compositor_res = client->GetWlCompositor();
+ struct zwp_input_method_manager_v1 *input_method_mgr_res = client->GetInputMethodMgr();
+
+ zwp_input_method_manager_v1_destroy(input_method_mgr_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 InputMethodMgrTest : public ::testing::Test
+{
+public:
+ void SetUp(void) override;
+ void TearDown(void) override;
+
+ MockInputMethodMgrCompositor *comp;
+ MockInputMethodMgrClient *client;
+ struct wl_compositor *compositor_res;
+ struct zwp_input_method_manager_v1 *input_method_mgr_res;
+};
+
+void
+InputMethodMgrTest::SetUp(void)
+{
+ ds_log_init(DS_INF, NULL);
+
+ ds_inf("%s", __func__);
+
+ comp = new MockInputMethodMgrCompositor();
+ client = new MockInputMethodMgrClient(®istry_listener);
+ compositor_res = client->GetWlCompositor();
+ input_method_mgr_res = client->GetInputMethodMgr();
+
+ client->RoundTrip();
+}
+
+void
+InputMethodMgrTest::TearDown(void)
+{
+ ds_inf("%s", __func__);
+
+ client->RoundTrip();
+
+ delete client;
+ delete comp;
+}
+
+TEST_F(InputMethodMgrTest, Create_P)
+{
+ EXPECT_TRUE(true);
+}
+
+TEST_F(InputMethodMgrTest, Req_SetTransientFor)
+{
+ uint32_t parent_pid = 123;
+ uint32_t child_pid = 321;
+
+ zwp_input_method_manager_v1_set_transient_for(input_method_mgr_res, parent_pid, child_pid);
+ client->RoundTrip();
+ EXPECT_TRUE(comp->mParentPid == parent_pid);
+ EXPECT_TRUE(comp->mChildPid == child_pid);
+}
\ No newline at end of file