--- /dev/null
+#define E_COMP_WL
+#include "e.h"
+#include "e_mod_main.h"
+#include "e_mod_input_method_manager.h"
+#include <Ecore.h>
+#include <input-method-server-protocol.h>
+
+const unsigned int MAX_COUNT_TRANSIENT_FOR = 6;
+
+typedef struct _E_Input_Method_Mgr E_Input_Method_Mgr;
+
+struct _E_Input_Method_Mgr
+{
+ struct wl_global *global;
+ struct wl_resource *resource;
+};
+
+static uint32_t g_parent_pid = 0;
+static uint32_t g_child_pid = 0;
+static Ecore_Timer *g_transient_timer = NULL;
+static uint32_t g_transient_timer_count = 0;
+
+static E_Client *find_visible_ec_by_pid(uint32_t pid);
+
+static Eina_Bool
+_e_input_method_manager_set_transient_for(uint32_t parent_pid, uint32_t child_pid)
+{
+ E_Client *parent_ec = find_visible_ec_by_pid(parent_pid);
+ E_Client *child_ec = find_visible_ec_by_pid(child_pid);
+
+ if (parent_ec && child_ec)
+ {
+ e_policy_stack_transient_for_set(child_ec, parent_ec);
+ LOGI("Succeeded to set transient for");
+ return EINA_TRUE;
+ }
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+_transient_for_timer_handler(void *data)
+{
+ if (g_parent_pid == 0 || g_child_pid == 0)
+ {
+ g_transient_timer = NULL;
+ g_transient_timer_count = 0;
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ if (g_transient_timer_count > MAX_COUNT_TRANSIENT_FOR)
+ {
+ g_transient_timer = NULL;
+ g_transient_timer_count = 0;
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ g_transient_timer_count++;
+
+ if (_e_input_method_manager_set_transient_for(g_parent_pid, g_child_pid))
+ {
+ g_transient_timer = NULL;
+ g_parent_pid = 0;
+ g_child_pid = 0;
+ g_transient_timer_count = 0;
+
+ return ECORE_CALLBACK_CANCEL;
+ }
+ else
+ return ECORE_CALLBACK_RENEW;
+}
+
+static E_Client *find_visible_ec_by_pid(uint32_t pid)
+{
+ E_Client *ec;
+ Eina_List *l = NULL;
+
+ EINA_LIST_FOREACH(e_comp->clients, l, ec)
+ {
+ if (!ec) continue;
+ if (e_object_is_del(E_OBJECT(ec))) continue;
+ if (ec->netwm.pid != pid) continue;
+
+ LOGI("pid(%d), name(%s), win(%x), visible(%d)", ec->netwm.pid, e_client_util_name_get(ec), e_client_util_win_get(ec), ec->visible);
+
+ if (ec->y == 0 && ec->visible && ec->vkbd.vkbd == 0)
+ return ec;
+ }
+
+ LOGW("No found ec for pid(%d)", pid);
+
+ return NULL;
+}
+
+static void
+_e_input_method_manager_cb_set_transient_for(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t parent_pid, uint32_t child_pid)
+{
+ LOGI("parent pid(%u), child pid(%u)", parent_pid, child_pid);
+
+ g_parent_pid = parent_pid;
+ g_child_pid = child_pid;
+
+ if (!_e_input_method_manager_set_transient_for(parent_pid, child_pid))
+ {
+ if (!g_transient_timer)
+ {
+ g_transient_timer_count = 0;
+ g_transient_timer = ecore_timer_add(0.3, _transient_for_timer_handler, NULL);
+ }
+ }
+}
+
+static const struct wl_input_method_manager_interface _e_input_method_manager_interface =
+{
+ _e_input_method_manager_cb_set_transient_for,
+};
+
+static void
+_e_input_method_manager_unbind(struct wl_resource *resource)
+{
+ if (g_transient_timer)
+ {
+ ecore_timer_del(g_transient_timer);
+ g_transient_timer = NULL;
+ }
+}
+
+static void
+_e_input_method_manager_cb_bind(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
+{
+ E_Input_Method_Mgr *input_method_mgr = data;
+
+ input_method_mgr->resource =
+ wl_resource_create(client,
+ &wl_input_method_manager_interface, 1, id);
+
+ if (input_method_mgr->resource)
+ wl_resource_set_implementation(input_method_mgr->resource,
+ &_e_input_method_manager_interface,
+ input_method_mgr, _e_input_method_manager_unbind);
+}
+
+Eina_Bool
+e_input_method_manager_create(void)
+{
+ E_Input_Method_Mgr *input_method_mgr;
+
+ if (!(input_method_mgr = E_NEW(E_Input_Method_Mgr, 1)))
+ {
+ ERR("Could not allocate space for Input_Method_Manager");
+ return EINA_FALSE;
+ }
+
+ input_method_mgr->global =
+ wl_global_create(e_comp_wl->wl.disp,
+ &wl_input_method_manager_interface, 1,
+ input_method_mgr, _e_input_method_manager_cb_bind);
+
+ if (!input_method_mgr->global)
+ {
+ free(input_method_mgr);
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}