Fix issue content hint was not delivered when the focus_in is called without show...
[platform/core/uifw/isf.git] / ism / extras / wayland_immodule / wayland_imcontext.c
index a0ab805..f31f036 100644 (file)
 #include <Ecore.h>
 #include <Ecore_Evas.h>
 #include <Ecore_Input.h>
-#include <Ecore_Wayland.h>
+#define EFL_BETA_API_SUPPORT
+#include <Ecore_Wl2.h>
 #include <dlog.h>
 #include <wctype.h>
+#include <app_common.h>
 #ifdef HAVE_VCONF
 #include <vconf.h>
 #endif
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
 #include "isf_debug.h"
 #include "wayland_imcontext.h"
 #include "tizen_profile.h"
+#include "isf_device_event.h"
 
 #ifdef LOG_TAG
 # undef LOG_TAG
@@ -55,6 +66,7 @@
 
 #define VCONFKEY_AUTOPERIOD_ALLOW_BOOL  "file/private/isf/autoperiod_allow"
 #define VCONFKEY_AUTOCAPITAL_ALLOW_BOOL "file/private/isf/autocapital_allow"
+#define SOCK_PATH "/run/.isf/scim-panel-socket"
 
 typedef enum {
     INPUT_LANG_URDU,
@@ -74,7 +86,16 @@ typedef enum {
     INPUT_LANG_KHMER,
     INPUT_LANG_KOREAN,
     INPUT_LANG_BURMESE,
-    INPUT_LANG_OTHER
+    INPUT_LANG_OTHER,
+    INPUT_LANG_ASSAMESE_BN,
+    INPUT_LANG_BENGALI_AS,
+    INPUT_LANG_BODO,
+    INPUT_LANG_DOGRI,
+    INPUT_LANG_MANIPURI,
+    INPUT_LANG_MANIPURI_AS,
+    INPUT_LANG_MANIPURI_BN,
+    INPUT_LANG_KONKANI,
+    INPUT_LANG_SINDHI
 } Input_Language;
 
 const double DOUBLE_SPACE_INTERVAL = 1.0;
@@ -97,6 +118,7 @@ static Ecore_IMF_Context    *_show_req_ctx               = NULL;
 static Ecore_IMF_Context    *_hide_req_ctx               = NULL;
 static Ecore_IMF_Context    *_focus_req_ctx              = NULL;
 static Ecore_IMF_Context    *_input_panel_ctx            = NULL;
+static Eina_Bool             _focus_req_only             = EINA_TRUE;
 
 static Eina_Rectangle        _keyboard_geometry = {0, 0, 0, 0};
 
@@ -117,35 +139,49 @@ static double                space_key_time               = 0.0;
 static Eina_Bool             autoperiod_allow             = EINA_FALSE;
 static Eina_Bool             autocap_allow                = EINA_FALSE;
 static Eina_Bool             hw_keyboard_mode             = EINA_FALSE;
+static Eina_Bool             _preedit_cursor_changed      = EINA_FALSE;
 
 static Input_Language        input_lang                   = INPUT_LANG_OTHER;
 static Evas_Coord            g_scr_w = 0, g_scr_h = 0;
+
+static void set_autocapital (Ecore_IMF_Context *ctx);
+
+static Eina_Bool g_key_rate_checked = EINA_FALSE, g_focused = EINA_FALSE;
+static double g_original_key_rate = 0.0, g_original_key_delay = 0.0, g_desired_key_rate = 0.0;
 //
 
 typedef struct __LanguageInfo {
     const char *code;
     Input_Language lang;
     Eina_Unicode punc_code;
-    Eina_Bool auto_capital_valid;
 } LanguageInfo;
 
 static LanguageInfo __language_infos [] = {
-    { "ur_PK",  INPUT_LANG_URDU,        0x06D4, EINA_TRUE },
-    { "hi_IN",  INPUT_LANG_HINDI,       0x0964, EINA_FALSE },
-    { "bn_IN",  INPUT_LANG_BENGALI_IN,  0x0964, EINA_TRUE },
-    { "bn_BD",  INPUT_LANG_BENGALI_BD,  0x0964, EINA_TRUE },
-    { "as_IN",  INPUT_LANG_ASSAMESE,    0x0964, EINA_TRUE },
-    { "pa_IN",  INPUT_LANG_PUNJABI,     0x0964, EINA_TRUE },
-    { "ne_NP",  INPUT_LANG_NEPALI,      0x0964, EINA_TRUE },
-    { "or_IN",  INPUT_LANG_ORIYA,       0x0964, EINA_TRUE },
-    { "mai_IN", INPUT_LANG_MAITHILI,    0x0964, EINA_TRUE },
-    { "hy_AM",  INPUT_LANG_ARMENIAN,    0x0589, EINA_TRUE },
-    { "zh_CN",  INPUT_LANG_CN,          0x3002, EINA_FALSE },
-    { "zh_HK",  INPUT_LANG_CN_HK,       0x3002, EINA_FALSE },
-    { "zh_TW",  INPUT_LANG_CN_TW,       0x3002, EINA_FALSE },
-    { "ja_JP",  INPUT_LANG_JAPANESE,    0x3002, EINA_FALSE },
-    { "km_KH",  INPUT_LANG_KHMER,       0x17D4, EINA_TRUE },
-    { "ko_KR",  INPUT_LANG_KOREAN,      0x002E, EINA_FALSE },
+    { "ur_PK",  INPUT_LANG_URDU,        0x06D4 },
+    { "hi_IN",  INPUT_LANG_HINDI,       0x0964 },
+    { "bn_IN",  INPUT_LANG_BENGALI_IN,  0x0964 },
+    { "bn_BD",  INPUT_LANG_BENGALI_BD,  0x0964 },
+    { "as_IN",  INPUT_LANG_ASSAMESE,    0x0964 },
+    { "pa_IN",  INPUT_LANG_PUNJABI,     0x0964 },
+    { "ne_NP",  INPUT_LANG_NEPALI,      0x0964 },
+    { "or_IN",  INPUT_LANG_ORIYA,       0x0964 },
+    { "mai_IN", INPUT_LANG_MAITHILI,    0x0964 },
+    { "hy_AM",  INPUT_LANG_ARMENIAN,    0x0589 },
+    { "zh_CN",  INPUT_LANG_CN,          0x3002 },
+    { "zh_HK",  INPUT_LANG_CN_HK,       0x3002 },
+    { "zh_TW",  INPUT_LANG_CN_TW,       0x3002 },
+    { "ja_JP",  INPUT_LANG_JAPANESE,    0x3002 },
+    { "km_KH",  INPUT_LANG_KHMER,       0x17D4 },
+    { "ko_KR",  INPUT_LANG_KOREAN,      0x002E },
+    { "asb_IN", INPUT_LANG_ASSAMESE_BN, 0x0964 },
+    { "bna_IN", INPUT_LANG_BENGALI_AS,  0x0964 },
+    { "brx_IN", INPUT_LANG_BODO,        0x0964 },
+    { "doi_IN", INPUT_LANG_DOGRI,       0x0964 },
+    { "mni_IN", INPUT_LANG_MANIPURI,    0xabeb },
+    { "mnia_IN",INPUT_LANG_MANIPURI_AS, 0x0964 },
+    { "mnib_IN",INPUT_LANG_MANIPURI_BN, 0x0964 },
+    { "kok_IN", INPUT_LANG_KONKANI,     0x0964 },
+    { "sd_IN",  INPUT_LANG_SINDHI,      0x0964 },
 };
 
 struct _WaylandIMContext
@@ -155,8 +191,8 @@ struct _WaylandIMContext
     struct wl_text_input_manager *text_input_manager;
     struct wl_text_input *text_input;
 
-    Ecore_Wl_Window *window;
-    Ecore_Wl_Input  *input;
+    Ecore_Wl2_Window *window;
+    Ecore_Wl2_Input  *input;
     Evas            *canvas;
 
     char *preedit_text;
@@ -217,9 +253,88 @@ struct _WaylandIMContext
     Eina_Bool has_conformant;
     char *prediction_hint;
     char *mime_type;
+
+    struct
+    {
+        int x;
+        int y;
+    } input_panel_position;
     //
 };
 
+typedef struct {
+    Ecore_IMF_Context *ctx;
+    WaylandIMContext *imcontext;
+} Ecore_Imf_Wayland_Imcontext_Pair;
+Eina_List *_ecore_imf_wayland_imcontext_pair_list = NULL;
+
+static void _ecore_imf_wayland_imcontext_pair_add (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
+{
+    Ecore_Imf_Wayland_Imcontext_Pair *pair = malloc (sizeof (Ecore_Imf_Wayland_Imcontext_Pair));
+    if (pair) {
+        pair->ctx = ctx;
+        pair->imcontext = imcontext;
+
+        _ecore_imf_wayland_imcontext_pair_list = eina_list_append (_ecore_imf_wayland_imcontext_pair_list, pair);
+    }
+}
+
+static Ecore_Imf_Wayland_Imcontext_Pair* _ecore_imf_wayland_imcontext_pair_find (Ecore_IMF_Context *ctx)
+{
+    Eina_List *l;
+    Ecore_Imf_Wayland_Imcontext_Pair *pair;
+    EINA_LIST_FOREACH (_ecore_imf_wayland_imcontext_pair_list, l, pair)
+        if (pair->ctx == ctx) {
+            return pair;
+        }
+    LOGE("The Ecore_Imf %p if not found in Ecore_IMF-WaylandIMContext pair list!!", ctx);
+    return NULL;
+}
+
+static void _ecore_imf_wayland_imcontext_pair_del (Ecore_IMF_Context *ctx)
+{
+    Eina_List *l;
+    Eina_List *l_next;
+    Ecore_Imf_Wayland_Imcontext_Pair *pair;
+
+    EINA_LIST_FOREACH_SAFE (_ecore_imf_wayland_imcontext_pair_list, l, l_next, pair)
+        if (ctx == pair->ctx) {
+            free (pair);
+            _ecore_imf_wayland_imcontext_pair_list = eina_list_remove_list (_ecore_imf_wayland_imcontext_pair_list, l);
+        }
+}
+
+static void _ecore_imf_wayland_imcontext_pair_destroy ()
+{
+    if (_ecore_imf_wayland_imcontext_pair_list) {
+        Ecore_Imf_Wayland_Imcontext_Pair *pair;
+        EINA_LIST_FREE (_ecore_imf_wayland_imcontext_pair_list, pair)
+            free (pair);
+        _ecore_imf_wayland_imcontext_pair_list = NULL;
+    }
+}
+
+static int _ecore_imf_wayland_imcontext_pair_log ()
+{
+    char buffer[255] = { '\0' };
+    int count = 0;
+    Eina_List *l;
+    Ecore_Imf_Wayland_Imcontext_Pair *pair;
+    EINA_LIST_FOREACH(_ecore_imf_wayland_imcontext_pair_list, l, pair) {
+        if (pair) {
+            snprintf(buffer + strlen(buffer), 255 - strlen(buffer), "%s[%p/%p]", (count ? "," : ""), pair->ctx, pair->imcontext);
+        }
+        count++;
+    }
+    if (count == 0) {
+        LOGD("No Ecore_Imf / Wayland_Imcontext pair found");
+    } else {
+        LOGD("%d Pair(s) : %s", count, buffer);
+    }
+
+    return count;
+}
+
 // TIZEN_ONLY(20150708): Support back key
 static void _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant);
 static Eina_Bool show_input_panel(Ecore_IMF_Context *ctx);
@@ -227,9 +342,10 @@ static Eina_Bool show_input_panel(Ecore_IMF_Context *ctx);
 static void
 reset_keyboard_geometry ()
 {
-    if (g_scr_w == 0 || g_scr_h == 0) {
-        ecore_wl_sync();
-        ecore_wl_screen_size_get(&g_scr_w, &g_scr_h);
+    Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
+    if (wl2_display && (g_scr_w == 0 || g_scr_h == 0)) {
+        ecore_wl2_sync();
+        ecore_wl2_display_screen_size_get(wl2_display, &g_scr_w, &g_scr_h);
     }
     _keyboard_geometry.x = 0;
     _keyboard_geometry.y = g_scr_h;
@@ -261,6 +377,7 @@ _device_info_send (unsigned int window, Eina_Bool flag)
     e->identifier = eina_stringshare_ref (IME_DEVICE_NAME);
     e->seatname = eina_stringshare_ref (IME_DEVICE_NAME);
     e->clas = ECORE_DEVICE_CLASS_KEYBOARD;
+    e->subclas = ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD;
     e->window = window;
 
     if (flag)
@@ -270,12 +387,9 @@ _device_info_send (unsigned int window, Eina_Bool flag)
 }
 
 static void
-get_input_language ()
+set_input_language (const char *input_lang_str)
 {
     unsigned int i;
-    char *input_lang_str = vconf_get_str (VCONFKEY_ISF_INPUT_LANGUAGE);
-    if (!input_lang_str) return;
-    LOGD ("language %s", input_lang_str);
     input_lang = INPUT_LANG_OTHER;
 
     for (i = 0; i < (sizeof (__language_infos) / sizeof (__language_infos[0])); i++) {
@@ -284,8 +398,6 @@ get_input_language ()
             break;
         }
     }
-
-    free (input_lang_str);
 }
 
 static void autoperiod_allow_changed_cb (keynode_t *key, void* data)
@@ -300,7 +412,11 @@ static void autocapital_allow_changed_cb (keynode_t *key, void* data)
 
 static void input_language_changed_cb (keynode_t *key, void* data)
 {
-    get_input_language ();
+    char *input_lang = vconf_keynode_get_str (key);
+    if (input_lang) {
+        set_input_language (input_lang);
+        LOGD("input lang : %s", input_lang);
+    }
 }
 
 static Eina_Bool
@@ -364,7 +480,7 @@ autoperiod_insert (Ecore_IMF_Context *ctx)
     ulen = eina_unicode_strlen (ustr);
 
     if (cursor_pos < 2 || cursor_pos > (int)ulen) {
-        LOGD ("invalid range. cursor pos : %d, length : %d\n", cursor_pos, ulen);
+        LOGD ("invalid range. cursor pos : %d, length : %d", cursor_pos, ulen);
         goto done;
     }
 
@@ -543,9 +659,6 @@ set_autocapital (Ecore_IMF_Context *ctx)
 
     if (hw_keyboard_mode) return;
 
-    if (input_lang != INPUT_LANG_OTHER && (!__language_infos[input_lang].auto_capital_valid))
-        return;
-
     if (ecore_imf_context_input_panel_layout_get (ctx) != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
         return;
 
@@ -559,7 +672,7 @@ set_autocapital (Ecore_IMF_Context *ctx)
         uppercase = analyze_surrounding_text (ctx);
     }
 
-    SECURE_LOGD ("ctx : %p, auto capital : %d\n", ctx, uppercase);
+    LOGD ("ctx : %p, auto capital : %d", ctx, uppercase);
     wl_text_input_set_capital_mode (imcontext->text_input, uppercase);
 }
 
@@ -695,7 +808,7 @@ key_down_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
         _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW) &&
         check_hide_key(ev->keyname)) {
 
-        LOGD ("%s key is pressed.\n", ev->keyname);
+        SECURE_LOGD ("%s key is pressed.", ev->keyname);
 
         Ecore_IMF_Event_Key_Down imf_event;
         Eina_Bool filter_ret = EINA_FALSE;
@@ -705,17 +818,10 @@ key_down_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
         if (_focused_ctx)
             filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_DOWN, (Ecore_IMF_Event *)&imf_event);
         else
-            LOGD("no focus\n");
-
-        LOGD ("%s key is pressed. ret : %d\n", ev->keyname, filter_ret);
-        if (filter_ret) {
-            return EINA_FALSE; /* the event is removed from the queue */
-        }
+            LOGD("no focus");
 
-        if (_TV)
-            return EINA_TRUE; /* the event is kept */
-        else
-            return EINA_FALSE; /* the event is removed from the queue */
+        SECURE_LOGD ("%s key is pressed. ret : %d", ev->keyname, filter_ret);
+        return EINA_FALSE; /* the event is removed from the queue */
     }
     return EINA_TRUE; /* the event is kept */
 }
@@ -734,7 +840,7 @@ key_up_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
         !check_hide_key(ev->keyname))
         return EINA_TRUE; /* the event is kept */
 
-    LOGD ("%s key is released.\n", ev->keyname);
+    SECURE_LOGD ("%s key is released.", ev->keyname);
 
     Ecore_IMF_Event_Key_Up imf_event;
     Eina_Bool filter_ret = EINA_FALSE;
@@ -744,22 +850,16 @@ key_up_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
     if (_focused_ctx)
         filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_UP, (Ecore_IMF_Event *)&imf_event);
     else
-        LOGD("no focus\n");
+        LOGD("no focus");
 
-    LOGD ("%s key is released. ret : %d\n", ev->keyname, filter_ret);
+    SECURE_LOGD ("%s key is released. ret : %d", ev->keyname, filter_ret);
     if (filter_ret) {
         return EINA_FALSE; /* the event is removed from the queue */
     }
     else {
         ecore_imf_context_reset(active_ctx);
-
-        if (_TV)
-            return EINA_TRUE; /* the event is kept */
-        else {
-            _input_panel_hide(active_ctx, EINA_TRUE);
-
-            return EINA_FALSE; /* the event is removed from the queue */
-        }
+        _input_panel_hide(active_ctx, EINA_TRUE);
+        return EINA_FALSE; /* the event is removed from the queue */
     }
 }
 
@@ -780,10 +880,19 @@ rotary_event_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
     if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE)
         return EINA_TRUE;
 
+    ecore_imf_context_reset(active_ctx);
     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(active_ctx);
     if (imcontext && imcontext->input && imcontext->text_input) {
-        wl_text_input_process_input_device_event(imcontext->text_input,
-            (unsigned int)ECORE_EVENT_DETENT_ROTATE, (char*)event, sizeof(Ecore_Event_Detent_Rotate));
+        isf_device_type_e device_type = find_device_type_from_ecore_event(ECORE_EVENT_DETENT_ROTATE);
+        char *buffer = NULL;
+        size_t buflen = 0;
+
+        if (device_buffer_encode((const char*)(event), sizeof(Ecore_Event_Detent_Rotate), &buffer, &buflen) &&
+            buffer && buflen > 0) {
+            wl_text_input_process_input_device_event(imcontext->text_input,
+                (unsigned int)device_type, buffer, buflen);
+        }
+        if (buffer) free(buffer);
     }
 
     return EINA_FALSE;
@@ -856,7 +965,6 @@ static void _conformant_change_handler_del()
 static void
 _send_input_panel_hide_request(Ecore_IMF_Context *ctx)
 {
-    LOGD ("");
     if (!ctx) return;
 
     // TIZEN_ONLY(20150708): Support back key
@@ -869,7 +977,7 @@ _send_input_panel_hide_request(Ecore_IMF_Context *ctx)
     if (imcontext && imcontext->text_input) {
         wl_text_input_hide_input_panel(imcontext->text_input);
     } else {
-        LOGD("creating temporary context for sending hide request\n");
+        LOGD("creating temporary context for sending hide request");
         const char *ctx_id = ecore_imf_context_default_id_get();
         Ecore_IMF_Context *temp_context = ecore_imf_context_add(ctx_id);
         if (temp_context) {
@@ -884,20 +992,20 @@ _send_input_panel_hide_request(Ecore_IMF_Context *ctx)
 
 static void _conformant_area_free (void *data EINA_UNUSED, void *ev)
 {
-    Ecore_Wl_Event_Conformant_Change *e = ev;
+    Ecore_Wl2_Event_Conformant_Change *e = ev;
     free(e);
     e = NULL;
 }
 
-static void add_conformant_change_event(Ecore_Wl_Window *window)
+static void add_conformant_change_event(Ecore_Wl2_Window *window)
 {
-    Ecore_Wl_Event_Conformant_Change *ev;
-    ev = calloc(1, sizeof(Ecore_Wl_Event_Conformant_Change));
+    Ecore_Wl2_Event_Conformant_Change *ev;
+    ev = calloc(1, sizeof(Ecore_Wl2_Event_Conformant_Change));
     if (ev) {
-        ev->win = ecore_wl_window_id_get(window);
+        ev->win = ecore_wl2_window_id_get(window);
         ev->part_type = 1;
         ev->state = 0;
-        ecore_event_add(ECORE_WL_EVENT_CONFORMANT_CHANGE, ev, _conformant_area_free, NULL);
+        ecore_event_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, ev, _conformant_area_free, NULL);
     }
 }
 
@@ -906,7 +1014,7 @@ static Eina_Bool reset_conformant_area(Ecore_IMF_Context *ctx)
 {
     Eina_Bool reset = EINA_FALSE;
     Eina_Bool has_conformant = EINA_FALSE;
-    Ecore_Wl_Window *window = NULL;
+    Ecore_Wl2_Window *window = NULL;
 
     if (!ctx) return EINA_FALSE;
 
@@ -918,7 +1026,7 @@ static Eina_Bool reset_conformant_area(Ecore_IMF_Context *ctx)
 
     if (window) {
         int x = 0, y = 0, w = 0, h = 0;
-        Eina_Bool result = ecore_wl_window_keyboard_geometry_get(window, &x, &y, &w, &h);
+        Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
 
         if (result) {
             if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w != 0 || h != 0)) {
@@ -932,7 +1040,7 @@ static Eina_Bool reset_conformant_area(Ecore_IMF_Context *ctx)
     }
     LOGD("reset %d", reset);
     if (reset) {
-        ecore_wl_window_keyboard_geometry_set(window, 0, 0, 0, 0);
+        ecore_wl2_window_keyboard_geometry_set(window, 0, 0, 0, 0);
 
         add_conformant_change_event(window);
 
@@ -946,7 +1054,7 @@ static void restore_conformant_area(Ecore_IMF_Context *ctx)
 {
     Eina_Bool restore = EINA_FALSE;
     Eina_Bool has_conformant = EINA_FALSE;
-    Ecore_Wl_Window *window = NULL;
+    Ecore_Wl2_Window *window = NULL;
 
     if (!ctx) return;
 
@@ -958,7 +1066,7 @@ static void restore_conformant_area(Ecore_IMF_Context *ctx)
 
     if (window) {
         int x = 0, y = 0, w = 0, h = 0;
-        Eina_Bool result = ecore_wl_window_keyboard_geometry_get(window, &x, &y, &w, &h);
+        Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
 
         if (result) {
             if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w == 0 || h == 0)) {
@@ -968,7 +1076,7 @@ static void restore_conformant_area(Ecore_IMF_Context *ctx)
     }
     LOGD("restore %d", restore);
     if (restore) {
-        ecore_wl_window_keyboard_geometry_set(window,
+        ecore_wl2_window_keyboard_geometry_set(window,
             _conformant_area_backup.x, _conformant_area_backup.y,
             _conformant_area_backup.w, _conformant_area_backup.h);
 
@@ -984,7 +1092,6 @@ _send_will_hide_ack(WaylandIMContext *imcontext)
     if (!imcontext) return;
     if (!(imcontext->text_input)) return;
 
-    LOGD("");
     const char *szWillHideAck = "WILL_HIDE_ACK";
     wl_text_input_set_input_panel_data(imcontext->text_input, szWillHideAck, strlen(szWillHideAck));
     _received_will_hide_event = EINA_FALSE;
@@ -1152,19 +1259,6 @@ clear_preedit(WaylandIMContext *imcontext)
     }
 }
 
-static Eina_Bool
-check_preedit_empty(WaylandIMContext *imcontext)
-{
-    if (!imcontext) return EINA_TRUE;
-
-    if (imcontext->preedit_text) return EINA_FALSE;
-    if (imcontext->preedit_attrs) return EINA_FALSE;
-    if (imcontext->preedit_cursor != 0) return EINA_FALSE;
-    if (imcontext->preedit_commit) return EINA_FALSE;
-
-    return EINA_TRUE;
-}
-
 static void
 text_input_commit_string(void                 *data,
                          struct wl_text_input *text_input EINA_UNUSED,
@@ -1217,34 +1311,43 @@ text_input_commit_string(void                 *data,
 static void
 commit_preedit(WaylandIMContext *imcontext)
 {
-    LOGD("");
     if (!imcontext->preedit_commit)
         return;
 
     if (!imcontext->ctx)
         return;
 
+    imcontext->pending_preedit.cursor = 0;
     clear_preedit_text(imcontext);
 
     size_t commit_len = strlen(imcontext->preedit_commit);
 
     if (commit_len == 0) {
+        ecore_imf_context_preedit_start_event_add(imcontext->ctx);
+        ecore_imf_context_event_callback_call(imcontext->ctx,
+                ECORE_IMF_CALLBACK_PREEDIT_START,
+                NULL);
+
         ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
         ecore_imf_context_event_callback_call(imcontext->ctx,
                 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
                 NULL);
-    }
 
-    ecore_imf_context_preedit_end_event_add(imcontext->ctx);
-    ecore_imf_context_event_callback_call(imcontext->ctx,
-            ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
+        ecore_imf_context_preedit_end_event_add(imcontext->ctx);
+        ecore_imf_context_event_callback_call(imcontext->ctx,
+                ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
+    }
 
     if (commit_len > 0) {
+        char *commit_str = NULL;
+        commit_str = strdup(imcontext->preedit_commit);
+        clear_preedit(imcontext);
         ecore_imf_context_commit_event_add(imcontext->ctx,
-                imcontext->preedit_commit);
+                commit_str);
         ecore_imf_context_event_callback_call(imcontext->ctx,
                 ECORE_IMF_CALLBACK_COMMIT,
-                (void *)imcontext->preedit_commit);
+                (void *)commit_str);
+        free(commit_str);
     }
 }
 
@@ -1256,19 +1359,19 @@ set_focus(Ecore_IMF_Context *ctx)
     if (!imcontext) return EINA_FALSE;
 
     if (!imcontext->window) {
-        LOGW("window is not given\n");
+        LOGW("window is not given");
         return EINA_FALSE;
     }
 
-    Ecore_Wl_Input *input = ecore_wl_window_keyboard_get(imcontext->window);
+    Ecore_Wl2_Input *input = ecore_wl2_window_input_get(imcontext->window);
     if (!input) {
-        LOGW("ctx : %p, Can't get Wl_Input\n", ctx);
+        LOGW("ctx : %p, Can't get Wl_Input", ctx);
         return EINA_FALSE;
     }
 
-    struct wl_seat *seat = ecore_wl_input_seat_get(input);
+    struct wl_seat *seat = ecore_wl2_input_seat_get(input);
     if (!seat) {
-        LOGW("ctx : %p, Can't get Wl_seat\n", ctx);
+        LOGW("ctx : %p, Can't get Wl_seat", ctx);
         return EINA_FALSE;
     }
 
@@ -1276,7 +1379,34 @@ set_focus(Ecore_IMF_Context *ctx)
     _focused_ctx = ctx;
 
     wl_text_input_activate(imcontext->text_input, seat,
-            ecore_wl_window_surface_get(imcontext->window));
+            ecore_wl2_window_surface_get(imcontext->window));
+
+    if (g_key_rate_checked == EINA_FALSE && g_desired_key_rate == 0.0) {
+        char *key_rate = getenv ("ISF_KEY_REPEAT_RATE");
+        if (key_rate) {
+            g_desired_key_rate = atof (key_rate);
+            if (g_desired_key_rate > 0.0) {
+                if (!ecore_wl2_input_keyboard_repeat_get (input, &g_original_key_rate, &g_original_key_delay)) {
+                    LOGE ("ecore_wl2_input_keyboard_repeat_get failed");
+                }
+                else {
+                    LOGD ("ecore_wl2_input_keyboard_repeat_get original rate=%f, delay=%f. Desired rate=%f",
+                        g_original_key_rate, g_original_key_delay, g_desired_key_rate);
+                }
+            }
+        }
+        g_key_rate_checked = EINA_TRUE;
+    }
+
+    if (g_desired_key_rate > 0.0 && g_original_key_delay > 0.0 && !g_focused) {
+        g_focused = EINA_TRUE;
+        if (!ecore_wl2_input_keyboard_repeat_set (input, g_desired_key_rate, g_original_key_delay)) {
+            LOGE ("ecore_wl2_input_keyboard_repeat_set failed");
+        }
+        else {
+            LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_desired_key_rate, g_original_key_delay);
+        }
+    }
 
     return EINA_TRUE;
 }
@@ -1284,18 +1414,46 @@ set_focus(Ecore_IMF_Context *ctx)
 static void
 set_focus_out(Ecore_IMF_Context *ctx)
 {
+    char *surrounding = NULL;
+    int cursor_pos = 0;
+
     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
     if (!imcontext || !imcontext->input) return;
 
+    if (ecore_imf_context_surrounding_get(ctx, &surrounding, &cursor_pos)) {
+        if (surrounding) {
+            wl_text_input_finalize_content(imcontext->text_input, surrounding, cursor_pos);
+            free(surrounding);
+        }
+    }
+
     // deactivate
     if (imcontext->text_input)
         wl_text_input_deactivate(imcontext->text_input,
-                                 ecore_wl_input_seat_get(imcontext->input));
+                                 ecore_wl2_input_seat_get(imcontext->input));
 
     if (ctx == _focused_ctx)
         _focused_ctx = NULL;
 
     imcontext->input = NULL;
+    _preedit_cursor_changed = EINA_FALSE;
+
+    if (g_desired_key_rate > 0.0 && g_focused) {
+        g_focused = EINA_FALSE;
+
+        Ecore_Wl2_Input *input = ecore_wl2_window_input_get(imcontext->window);
+        if (input) {
+            if (!ecore_wl2_input_keyboard_repeat_set (input, g_original_key_rate, g_original_key_delay)) {
+                LOGE ("ecore_wl2_input_keyboard_repeat_set failed.");
+            }
+            else {
+                LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_original_key_rate, g_original_key_delay);
+            }
+        }
+        else {
+            LOGW("ctx : %p, Can't get Wl_Input", ctx);
+        }
+    }
 }
 
 // TIZEN_ONLY(20160217): ignore the duplicate show request
@@ -1326,20 +1484,20 @@ static void send_get_hide_permission(WaylandIMContext *imcontext)
 
 static Eina_Bool _client_window_focus_out_cb(void *data, int ev_type, void *ev)
 {
-    Ecore_Wl_Event_Focus_Out *e = (Ecore_Wl_Event_Focus_Out *)ev;
+    Ecore_Wl2_Event_Focus_Out *e = (Ecore_Wl2_Event_Focus_Out *)ev;
     Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
     if (!ctx || !e) return ECORE_CALLBACK_PASS_ON;
 
     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
     if (!imcontext || !imcontext->window) return ECORE_CALLBACK_PASS_ON;
 
-    unsigned int client_win_id = ecore_wl_window_id_get (imcontext->window);
+    unsigned int client_win_id = ecore_wl2_window_id_get (imcontext->window);
 
-    LOGD ("ctx : %p, client_window id : %#x, focus-out win : %#x\n", ctx, client_win_id, e->win);
+    LOGD ("ctx : %p, client_window id : %#x, focus-out win : %#x", ctx, client_win_id, e->window);
 
     if (client_win_id > 0) {
-        if (e->win == client_win_id) {
-            LOGD ("window focus out\n");
+        if (e->window == client_win_id) {
+            LOGD ("window focus out");
 
             if (_focused_ctx == ctx) {
                 wayland_im_context_focus_out (ctx);
@@ -1364,12 +1522,12 @@ static void send_will_hide_ack(Ecore_IMF_Context *ctx)
     WaylandIMContext *imcontext = NULL;
 
     if (!ctx) {
-        LOGD("ctx is NULL\n");
+        LOGD("ctx is NULL");
         need_temporary_context = EINA_TRUE;
     } else {
         imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
         if (!imcontext) {
-            LOGD("imcontext is NULL :%p\n", ctx);
+            LOGD("imcontext is NULL :%p", ctx);
             need_temporary_context = EINA_TRUE;
         } else {
             has_conformant = imcontext->has_conformant;
@@ -1380,7 +1538,7 @@ static void send_will_hide_ack(Ecore_IMF_Context *ctx)
        meaning that there is no connection available for communicating with the window manager.
        So we are creating a temporary context for sending WILL_HIDE_ACK message */
     if (need_temporary_context) {
-        LOGD("creating temporary context for sending WILL_HIDE_ACK\n");
+        LOGD("creating temporary context for sending WILL_HIDE_ACK");
         const char *ctx_id = ecore_imf_context_default_id_get();
         ctx = ecore_imf_context_add(ctx_id);
         if (ctx) {
@@ -1391,16 +1549,16 @@ static void send_will_hide_ack(Ecore_IMF_Context *ctx)
     if (ctx && imcontext) {
         if (ecore_imf_context_client_canvas_get(ctx) && has_conformant) {
             if (_conformant_reset_done && _received_will_hide_event) {
-                LOGD("Send will hide ack, _conformant_reset_done = 1, received_will_hide_event = 1\n");
+                LOGD("Send will hide ack, _conformant_reset_done = 1, received_will_hide_event = 1");
                 _send_will_hide_ack(imcontext);
                 _conformant_reset_done = EINA_FALSE;
                 _received_will_hide_event = EINA_FALSE;
             } else {
-                LOGD ("_conformant_reset_done=%d, received_will_hide_event=%d\n",
+                LOGD ("_conformant_reset_done=%d, received_will_hide_event=%d",
                     _conformant_reset_done, _received_will_hide_event);
             }
         } else {
-            LOGD("Send will hide ack right away, since there is no conformant available : %p %d\n",
+            LOGD("Send will hide ack right away, since there is no conformant available : %p %d",
                 ecore_imf_context_client_canvas_get(ctx), has_conformant);
             _send_will_hide_ack (imcontext);
         }
@@ -1418,13 +1576,13 @@ static void _render_post_cb(void *data, Evas *e, void *event_info)
     void *callback = evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
     _conformant_reset_done = EINA_TRUE;
     _conformant_reset_started = EINA_FALSE;
-    LOGD("[_render_post_cb], _conformant_reset_done = 1 , %p\n", callback);
+    LOGD("[_render_post_cb], _conformant_reset_done = 1 , %p", callback);
     send_will_hide_ack(NULL);
 }
 
 static Eina_Bool _conformant_change_cb(void *data, int ev_type, void *ev)
 {
-    Ecore_Wl_Event_Conformant_Change *e = (Ecore_Wl_Event_Conformant_Change *)ev;
+    Ecore_Wl2_Event_Conformant_Change *e = (Ecore_Wl2_Event_Conformant_Change *)ev;
     Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
     if (!e || !ctx) return ECORE_CALLBACK_PASS_ON;
 
@@ -1433,13 +1591,16 @@ static Eina_Bool _conformant_change_cb(void *data, int ev_type, void *ev)
     if (_active_context_window_id != e->win)
         return ECORE_CALLBACK_PASS_ON;
 
-    Ecore_Wl_Window *window = ecore_wl_window_find(e->win);
+    Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
+    if (!wl2_display) return ECORE_CALLBACK_PASS_ON;
+
+    Ecore_Wl2_Window *window = ecore_wl2_display_window_find(wl2_display, e->win);
     if (!window) return ECORE_CALLBACK_PASS_ON;
 
     if (!(e->state)) {
-        LOGD("_conformant_reset_done = 0, registering _render_post_cb : %p %p\n", _active_context_canvas, window);
+        LOGD("_conformant_reset_done = 0, registering _render_post_cb : %p %p", _active_context_canvas, window);
         _conformant_reset_done = EINA_FALSE;
-        if (_active_context_canvas && ecore_wl_window_conformant_get(window) && !_custom_conformant_event) {
+        if (_active_context_canvas && ecore_wl2_window_conformant_get(window) && !_custom_conformant_event) {
             evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
             evas_event_callback_add(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb, ctx);
         }
@@ -1453,22 +1614,24 @@ static Eina_Bool _conformant_change_cb(void *data, int ev_type, void *ev)
         int x = 0, y = 0, w = 0, h = 0;
 
         if (_TV) {
-            /* TV IME consists of two or three windows, so ecore_wl_window_keyboard_geometry_get() may return wrong size. */
+            /* TV IME consists of two or three windows, so ecore_wl2_window_keyboard_geometry_get() may return wrong size. */
             x = _keyboard_geometry.x, y = _keyboard_geometry.y, w = _keyboard_geometry.w, h = _keyboard_geometry.h;
             if (_keyboard_geometry.w == 0 || _keyboard_geometry.h == 0) {
-                result = ecore_wl_window_keyboard_geometry_get(window, &x, &y, &w, &h);
+                result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
             }
         } else {
             /* Since the input_panel_geometry is not delivered right at the moment, we use conformant geometry instead */
             x = 0, y = 0, w = 0, h = 0;
-            result = ecore_wl_window_keyboard_geometry_get(window, &x, &y, &w, &h);
+            result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
         }
 
         if (result) {
             Evas_Coord scr_w = 0, scr_h = 0;
-            ecore_wl_sync();
-            ecore_wl_screen_size_get(&scr_w, &scr_h);
-            int rot = ecore_wl_window_rotation_get(window);
+            ecore_wl2_sync();
+            Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
+            if (wl2_display)
+                ecore_wl2_display_screen_size_get(wl2_display ,&scr_w, &scr_h);
+            int rot = ecore_wl2_window_rotation_get(window);
             /* Assume we are using keyboard that has the same width to the screen width*/
             switch (rot) {
             case 90:
@@ -1496,7 +1659,7 @@ static Eina_Bool _conformant_change_cb(void *data, int ev_type, void *ev)
                 _keyboard_geometry.h = h;
             }
             LOGD("[KEYPAD]: scr %dx%d, rot %d, orig (%d,%d, %dx%d)", scr_w, scr_h, rot, x, y, w, h);
-            LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d\n", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
+            LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
             ecore_imf_context_input_panel_event_callback_call(ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
         }
     }
@@ -1549,23 +1712,25 @@ get_purpose(Ecore_IMF_Context *ctx)
 
 static void _canvas_focus_in_cb(void *data, Evas *e, void *event_info)
 {
-    LOGD("ctx : %p", _focus_req_ctx);
+    LOGD("ctx : %p %d", _focus_req_ctx, _focus_req_only);
 
     if (_focus_req_ctx) {
         set_focus(_focus_req_ctx);
-        show_input_panel(_focus_req_ctx);
+        if (ecore_imf_context_input_panel_enabled_get (_focus_req_ctx) || !_focus_req_only)
+            if (!ecore_imf_context_input_panel_show_on_demand_get (_focus_req_ctx) || !_focus_req_only)
+                show_input_panel (_focus_req_ctx);
 
         WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(_focus_req_ctx);
         if (imcontext && imcontext->canvas)
             evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
         _focus_req_ctx = NULL;
+        _focus_req_only = EINA_TRUE;
     }
 }
 
 static Eina_Bool
 show_input_panel(Ecore_IMF_Context *ctx)
 {
-    LOGD("ctx : %p", ctx);
     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
 
     char *surrounding = NULL;
@@ -1578,6 +1743,7 @@ show_input_panel(Ecore_IMF_Context *ctx)
         set_focus(ctx);
         if (!imcontext->input) {
             _focus_req_ctx = ctx;
+            _focus_req_only = EINA_FALSE;
             if (imcontext->canvas) {
                 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
                 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
@@ -1594,9 +1760,9 @@ show_input_panel(Ecore_IMF_Context *ctx)
 
     ignore_hide = EINA_TRUE;
 
-    _win_focus_out_handler = ecore_event_handler_add (ECORE_WL_EVENT_FOCUS_OUT, _client_window_focus_out_cb, ctx);
+    _win_focus_out_handler = ecore_event_handler_add (ECORE_WL2_EVENT_FOCUS_OUT, _client_window_focus_out_cb, ctx);
     _conformant_change_handler_del ();
-    _conformant_change_handler = ecore_event_handler_add(ECORE_WL_EVENT_CONFORMANT_CHANGE, _conformant_change_cb, ctx);
+    _conformant_change_handler = ecore_event_handler_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, _conformant_change_cb, ctx);
 
     // TIZEN_ONLY(20160217): ignore the duplicate show request
     if ((_show_req_ctx == ctx) && _compare_context(_show_req_ctx, ctx) && (!will_hide)) {
@@ -1613,12 +1779,6 @@ show_input_panel(Ecore_IMF_Context *ctx)
     _input_panel_ctx = ctx;
     _active_context_canvas = ecore_imf_context_client_canvas_get(ctx);
 
-    if (imcontext->window) {
-        _active_context_window_id = ecore_wl_window_id_get(imcontext->window);
-        imcontext->has_conformant = ecore_wl_window_conformant_get(imcontext->window);
-    } else {
-        imcontext->has_conformant = EINA_FALSE;
-    }
     //
 
     // TIZEN_ONLY(20150715): Support input_panel_state_get
@@ -1634,7 +1794,7 @@ show_input_panel(Ecore_IMF_Context *ctx)
             get_purpose(ctx));
 
     if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos)) {
-        SECURE_LOGD ("surrounding text : %s\n", surrounding);
+        SECURE_LOGD ("surrounding text : %s", surrounding);
         if (surrounding)
             free (surrounding);
 
@@ -1655,26 +1815,33 @@ show_input_panel(Ecore_IMF_Context *ctx)
 
     set_autocapital (ctx);
 
-    if (strlen(imcontext->mime_type) > 0)
+    if (imcontext->mime_type)
         wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
 
-    SECURE_LOGD ("ctx : %p, layout : %d, layout variation : %d\n", ctx,
-            layout, layout_variation);
-    SECURE_LOGD ("language : %d, cursor position : %d\n",
-            ecore_imf_context_input_panel_language_get (ctx),
-            cursor_pos);
-    SECURE_LOGD ("return key type : %d, return key disabled : %d, autocapital type : %d\n",
-            ecore_imf_context_input_panel_return_key_type_get (ctx),
-            ecore_imf_context_input_panel_return_key_disabled_get (ctx),
-            ecore_imf_context_autocapital_type_get (ctx));
-    SECURE_LOGD ("client_window : %#x, password mode : %d, prediction_allow : %d\n",
-            ecore_imf_context_client_window_get (ctx),
-            (imcontext->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA) ? 1 : 0,
-            ecore_imf_context_prediction_allow_get (ctx));
-    SECURE_LOGD ("input hint : %#x, bidi direction : %d\n", ecore_imf_context_input_hint_get (ctx), imcontext->bidi_direction);
+    if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
+            wl_text_input_set_input_panel_position(imcontext->text_input,
+                imcontext->input_panel_position.x, imcontext->input_panel_position.y);
+
+    LOGD ("ctx : %p, layout : %d, layout variation : %d, language : %d, cursor position : %d",
+           ctx, layout, layout_variation,
+           ecore_imf_context_input_panel_language_get (ctx),
+           cursor_pos);
+    LOGD ("input hint : %#x, bidi direction : %d, return key type : %d, return key disabled : %d, autocapital type : %d",
+           ecore_imf_context_input_hint_get (ctx),
+           imcontext->bidi_direction,
+           ecore_imf_context_input_panel_return_key_type_get (ctx),
+           ecore_imf_context_input_panel_return_key_disabled_get (ctx),
+           ecore_imf_context_autocapital_type_get (ctx));
+    LOGD ("client_window : %#lx, password mode : %d, prediction_allow : %d, mime_type : %s, input panel position x : %d, y : %d",
+           (unsigned long int)ecore_imf_context_client_window_get (ctx),
+           (imcontext->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA) ? 1 : 0,
+           ecore_imf_context_prediction_allow_get (ctx),
+           imcontext->mime_type,
+           imcontext->input_panel_position.x,
+           imcontext->input_panel_position.y);
 
     if (_active_context_canvas && !evas_focus_state_get (_active_context_canvas)) {
-        LOGW ("Canvas does not have focus!\n");
+        LOGW ("Canvas does not have focus!");
     }
     //
 
@@ -1687,6 +1854,13 @@ show_input_panel(Ecore_IMF_Context *ctx)
 
     wl_text_input_show_input_panel(imcontext->text_input);
 
+    if (imcontext->window) {
+        _active_context_window_id = ecore_wl2_window_id_get(imcontext->window);
+        imcontext->has_conformant = ecore_wl2_window_conformant_get(imcontext->window);
+    } else {
+        imcontext->has_conformant = EINA_FALSE;
+    }
+
     return EINA_TRUE;
 }
 
@@ -1730,6 +1904,14 @@ text_input_preedit_string(void                 *data,
     else
         preedit_changed = (strlen(text) != 0);
 
+    if (_preedit_cursor_changed) {
+        preedit_changed = EINA_TRUE;
+        _preedit_cursor_changed = EINA_FALSE;
+    }
+
+    if (imcontext->pending_preedit.attrs)
+        preedit_changed = EINA_TRUE;
+
     clear_preedit(imcontext);
 
     imcontext->preedit_text = strdup(text);
@@ -1791,6 +1973,7 @@ text_input_preedit_styling(void                 *data,
 {
     WaylandIMContext *imcontext = (WaylandIMContext *)data;
     Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
+    if (!attr) return;
 
     switch (style)
     {
@@ -1800,17 +1983,23 @@ text_input_preedit_styling(void                 *data,
         case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
             attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
             break;
-        case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT:
+        case WL_TEXT_INPUT_PREEDIT_STYLE_REVERSE:
+            attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
             break;
         case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
             attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
             break;
-        case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE:
+        case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR1:
+            attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
             break;
-        case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE:
+        case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR2:
+            attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
             break;
-        case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION:
-            attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
+        case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR3:
+            attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
+            break;
+        case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR4:
+            attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
             break;
         default:
             attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
@@ -1831,7 +2020,10 @@ text_input_preedit_cursor(void                 *data,
 {
     WaylandIMContext *imcontext = (WaylandIMContext *)data;
 
-    imcontext->pending_preedit.cursor = index;
+    if (imcontext->pending_preedit.cursor != index) {
+        imcontext->pending_preedit.cursor = index;
+        _preedit_cursor_changed = EINA_TRUE;
+    }
 }
 
 static xkb_mod_index_t
@@ -1870,18 +2062,18 @@ text_input_modifiers_map(void                 *data,
                          struct wl_array      *map)
 {
     WaylandIMContext *imcontext = (WaylandIMContext *)data;
-    LOGD ("");
-    imcontext->shift_mask = modifiers_get_mask(map, "Shift");
-    imcontext->control_mask = modifiers_get_mask(map, "Control");
-    imcontext->alt_mask = modifiers_get_mask(map, "Mod1");
-    imcontext->caps_mask = modifiers_get_mask(map, "Lock");
-    imcontext->num_mask = modifiers_get_mask(map, "Mod2");
+    imcontext->shift_mask = modifiers_get_mask(map, XKB_MOD_NAME_SHIFT);
+    imcontext->control_mask = modifiers_get_mask(map, XKB_MOD_NAME_CTRL);
+    imcontext->alt_mask = modifiers_get_mask(map, XKB_MOD_NAME_ALT);
+    imcontext->caps_mask = modifiers_get_mask(map, XKB_MOD_NAME_CAPS);
+    imcontext->num_mask = modifiers_get_mask(map, XKB_MOD_NAME_NUM);
 }
 
 static void
 _ecore_keyevent_free (void *data EINA_UNUSED, void *ev)
 {
     Ecore_Event_Key *e = ev;
+    if (e->dev) ecore_device_unref(e->dev);
     free(e);
     e = NULL;
 }
@@ -1925,9 +2117,9 @@ text_input_keysym(void                 *data,
     strncpy((char *)e->key, key, strlen(key));
     strncpy((char *)e->string, string, strlen(string));
 
-    e->window = (Ecore_Window)ecore_wl_window_id_get(imcontext->window);
-    e->event_window = (Ecore_Window)ecore_wl_window_id_get(imcontext->window);
-    e->dev = _ime_device;
+    e->window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
+    e->event_window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
+    e->dev = ecore_device_ref(_ime_device);
     e->timestamp = 0; /* For distinguishing S/W keyboard event */
 
     e->modifiers = 0;
@@ -2004,7 +2196,7 @@ text_input_input_panel_state(void                 *data EINA_UNUSED,
             will_hide = EINA_FALSE;
 
             _received_will_hide_event = EINA_TRUE;
-            LOGD("_received_will_hide_event = 1\n");
+            LOGD("_received_will_hide_event = 1");
             send_will_hide_ack(imcontext->ctx);
             break;
         case WL_TEXT_INPUT_INPUT_PANEL_STATE_SHOW:
@@ -2012,7 +2204,7 @@ text_input_input_panel_state(void                 *data EINA_UNUSED,
             _received_will_hide_event = EINA_FALSE;
             if (!_show_req_ctx)
                 _show_req_ctx = imcontext->ctx;
-            LOGD("_received_will_hide_event = 0\n");
+            LOGD("_received_will_hide_event = 0");
             break;
         default:
             _input_panel_state = (Ecore_IMF_Input_Panel_State)state;
@@ -2025,7 +2217,7 @@ text_input_input_panel_state(void                 *data EINA_UNUSED,
 
     if (state == WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE) {
         reset_keyboard_geometry();
-        LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d\n", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
+        LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
         ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
     }
     //
@@ -2049,7 +2241,7 @@ text_input_input_panel_geometry(void                 *data EINA_UNUSED,
         _keyboard_geometry.y = y;
         _keyboard_geometry.w = w;
         _keyboard_geometry.h = h;
-        LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d\n", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
+        LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
         ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
     }
 }
@@ -2124,7 +2316,7 @@ text_input_private_command(void                 *data,
     LOGD("Checking command : %s", command);
 
     if (strncmp(command, szConformantReset, strlen(szConformantReset)) == 0) {
-        Ecore_Wl_Window *window = imcontext->window;
+        Ecore_Wl2_Window *window = imcontext->window;
         if (!window) return;
 
         if (!reset_conformant_area(imcontext->ctx) && !_conformant_reset_started) {
@@ -2135,7 +2327,7 @@ text_input_private_command(void                 *data,
             _send_will_hide_ack(imcontext);
         }
     } else if (strncmp(command, szConformantRestore, strlen(szConformantRestore)) == 0) {
-        Ecore_Wl_Window *window = imcontext->window;
+        Ecore_Wl2_Window *window = imcontext->window;
         if (!window) return;
 
         restore_conformant_area(imcontext->ctx);
@@ -2160,7 +2352,7 @@ text_input_commit_content(void                 *data,
     ev.mime_types = mime_types;
     ev.description = description;
 
-    SECURE_LOGD("commit content : %s, description : %s, mime types : %s\n", content, description, mime_types);
+    SECURE_LOGD("commit content : %s, description : %s, mime types : %s", content, description, mime_types);
 
     ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT_CONTENT, (void *)&ev);
 }
@@ -2179,7 +2371,9 @@ text_input_input_panel_data(void                 *data,
         free (imcontext->input_panel_data);
 
     imcontext->input_panel_data = calloc (1, length);
-    memcpy (imcontext->input_panel_data, input_panel_data, length);
+    if (imcontext->input_panel_data)
+        memcpy (imcontext->input_panel_data, input_panel_data, length);
+
     imcontext->input_panel_data_length = length;
 }
 
@@ -2192,7 +2386,7 @@ text_input_get_selection_text (void                 *data,
     LOGD ("%d", fd);
     WaylandIMContext *imcontext = (WaylandIMContext *)data;
     if (!imcontext || !imcontext->ctx) {
-        LOGD ("");
+        LOGD ("No context!");
         close (fd);
         return;
     }
@@ -2233,7 +2427,7 @@ text_input_get_surrounding_text (void                 *data,
     LOGD("fd: %d maxlen_before: %d maxlen_after: %d", fd, maxlen_before, maxlen_after);
     WaylandIMContext *imcontext = (WaylandIMContext *)data;
     if (!imcontext || !imcontext->ctx) {
-        LOGD("");
+        LOGD ("No context!");
         close(fd);
         return;
     }
@@ -2254,7 +2448,7 @@ text_input_get_surrounding_text (void                 *data,
                 maxlen_before = cursor_pos - maxlen_before;
 
             if (maxlen_after > wlen - cursor_pos)
-                maxlen_after = wlen;
+                maxlen_after = (uint32_t)wlen;
             else
                 maxlen_after = cursor_pos + maxlen_after;
 
@@ -2334,8 +2528,10 @@ text_input_recapture_string(void                 *data,
     Eina_Bool old_preedit = EINA_FALSE;
     Eina_Bool preedit_changed = EINA_FALSE;
 
-    SECURE_LOGD("ctx : %p, preedit event (preedit: '%s', current pre-edit: '%s')",
+    SECURE_LOGD("ctx : %p, index : %d, length : %d, preedit event (preedit: '%s', current pre-edit: '%s')",
                 imcontext->ctx,
+                index,
+                length,
                 preedit,
                 imcontext->preedit_text ? imcontext->preedit_text : "");
 
@@ -2350,10 +2546,12 @@ text_input_recapture_string(void                 *data,
     else
         preedit_changed = (strlen(preedit) != 0);
 
-    clear_preedit(imcontext);
-
     // send transaction start
     ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_START");
+    ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_START, NULL);
+
+    commit_preedit(imcontext);
+    clear_preedit(imcontext);
 
     // delete surrounding text
     delete_surrounding_text(imcontext, index, length);
@@ -2396,6 +2594,22 @@ text_input_recapture_string(void                 *data,
 
     // send transaction end
     ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_END");
+    ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_END, NULL);
+}
+
+static void
+text_input_input_panel_event(void                 *data,
+                             struct wl_text_input *text_input EINA_UNUSED,
+                             uint32_t              serial EINA_UNUSED,
+                             uint32_t              event_type,
+                             uint32_t              value)
+{
+    WaylandIMContext *imcontext = (WaylandIMContext *)data;
+    if (!imcontext || !imcontext->ctx) return;
+
+    LOGD("event type : %d, value : %d", event_type, value);
+
+    ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, event_type, value);
 }
 //
 
@@ -2424,6 +2638,7 @@ static const struct wl_text_input_listener text_input_listener =
     text_input_filter_key_event_done,
     text_input_hide_permission,
     text_input_recapture_string,
+    text_input_input_panel_event,
     text_input_commit_content
     //
 };
@@ -2435,11 +2650,14 @@ keyboard_mode_changed_cb (keynode_t *key, void* data)
     hw_keyboard_mode = vconf_keynode_get_bool (key);
     Ecore_IMF_Context *active_ctx = get_using_ctx ();
     if (active_ctx) {
-        LOGD ("ctx : %p, input detect : %d\n", active_ctx, hw_keyboard_mode);
+        LOGD ("ctx : %p, input detect : %d", active_ctx, hw_keyboard_mode);
 
         Ecore_IMF_Input_Panel_Keyboard_Mode input_mode = hw_keyboard_mode ? ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE : ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE;
         ecore_imf_context_input_panel_event_callback_call (active_ctx, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, input_mode);
 
+        if (input_mode == ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE && _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW)
+            _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
+
         if ((input_mode == ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE) && _focused_ctx && (active_ctx == _focused_ctx)) {
             if (ecore_imf_context_input_panel_enabled_get (active_ctx)) {
                 ecore_imf_context_input_panel_show (active_ctx);
@@ -2447,38 +2665,55 @@ keyboard_mode_changed_cb (keynode_t *key, void* data)
         }
     }
 }
+#endif
 
-static Eina_Bool read_devices = EINA_FALSE;
-char ** device_names = NULL;
+#ifdef SOCKET_ACTIVATION
+static int activate_socket () {
+    int s;
+    struct sockaddr_un svr;
+    int len;
+    int r;
+    int cnt = 5;
+    int flag;
 
-static Eina_Bool
-filter_devices (const char *dev_name)
-{
-    int i;
-    LOGD("");
+    LOGD("socket_activate start");
+    s = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (s == -1) {
+        LOGW("socket error");
+        return -1;
+    }
 
-    if (!dev_name)
-        return EINA_FALSE;
+    flag = fcntl(s, F_GETFL, NULL);
+    flag |= O_NONBLOCK;
+    fcntl(s, F_SETFL, flag);
 
-    if (read_devices == EINA_FALSE) {
-        char *devices = getenv("ISF_REMOTE_CONTROL_DEVICES");
-        if (devices) {
-            device_names = eina_str_split(devices, ",", 0);
-        }
-        read_devices = EINA_TRUE;
-    }
+    svr.sun_family = AF_UNIX;
+    strcpy(svr.sun_path, SOCK_PATH);
+    len = sizeof(svr);
 
-     if (device_names == NULL) {
-        return EINA_FALSE;
+    r = connect(s, (struct sockaddr *)&svr, len);
+    if (r == -1) {
+        LOGD("connect error");
+        close(s);
+        return -1;
     }
 
-    for (i = 0; device_names[i]; i++) {
-        if (!strcmp (dev_name, device_names[i])) {
-            return EINA_TRUE;
+    while (cnt > 0) {
+        struct timeval s1;
+
+        gettimeofday(&s1, NULL);
+        LOGD("%d %06d\n", (int)s1.tv_sec, (int)s1.tv_usec);
+
+        r = send(s, (const void *)&s1, sizeof(s1), 0);
+        if (r == -1) {
+            LOGW("send error");
+            break;
         }
+        cnt--;
     }
 
-    return EINA_FALSE;
+    close(s);
+    return 0;
 }
 #endif
 
@@ -2487,7 +2722,11 @@ void wayland_im_initialize ()
     register_key_handler ();
 
     /* get input language vconf value */
-    get_input_language ();
+    char *input_lang_str = vconf_get_str (VCONFKEY_ISF_INPUT_LANGUAGE);
+    if (input_lang_str) {
+        set_input_language (input_lang_str);
+        free (input_lang_str);
+    }
 
 #ifdef HAVE_VCONF
     /* get autoperiod allow vconf value */
@@ -2521,11 +2760,14 @@ void wayland_im_initialize ()
         ecore_device_description_set (_ime_device, IME_DEVICE_NAME);
         ecore_device_identifier_set (_ime_device, IME_DEVICE_NAME);
         ecore_device_class_set (_ime_device, ECORE_DEVICE_CLASS_KEYBOARD);
+        ecore_device_subclass_set (_ime_device, ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD);
     }
 }
 
 void wayland_im_uninitialize ()
 {
+    _ecore_imf_wayland_imcontext_pair_destroy ();
+
     unregister_key_handler ();
 
     _win_focus_out_handler_del ();
@@ -2536,27 +2778,21 @@ void wayland_im_uninitialize ()
     vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
     vconf_ignore_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb);
     vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
-
-    if (_TV) {
-        if (device_names) {
-            if (device_names[0])
-                free (device_names[0]);
-            free (device_names);
-            device_names = NULL;
-        }
-    }
 #endif
 
     if (_ime_device) {
         ecore_device_del (_ime_device);
         _ime_device = NULL;
     }
+
+    ecore_event_type_flush(ECORE_EVENT_DEVICE_ADD, ECORE_EVENT_DEVICE_DEL);
 }
 
 void
 wayland_im_context_add(Ecore_IMF_Context *ctx)
 {
     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
+    char *appid = NULL;
 
     LOGD("ctx : %p", ctx);
 
@@ -2572,12 +2808,23 @@ wayland_im_context_add(Ecore_IMF_Context *ctx)
     imcontext->caps_mask = MOD_CAPS_MASK;
     imcontext->num_mask = MOD_NUM_MASK;
 
+    imcontext->input_panel_position.x = -1;
+    imcontext->input_panel_position.y = -1;
+
     imcontext->text_input =
         wl_text_input_manager_create_text_input(imcontext->text_input_manager);
 
     if (imcontext->text_input)
         wl_text_input_add_listener(imcontext->text_input,
                                    &text_input_listener, imcontext);
+
+    app_get_id(&appid);
+    LOGD("app id : %s\n", appid);
+
+    ecore_imf_context_prediction_hint_hash_set(ctx, "appid", appid ? appid : "");
+
+    if (appid)
+        free (appid);
 }
 
 void
@@ -2585,14 +2832,23 @@ wayland_im_context_del (Ecore_IMF_Context *ctx)
 {
     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
 
+    Eina_Bool valid = EINA_FALSE;
+    Ecore_Imf_Wayland_Imcontext_Pair *pair = _ecore_imf_wayland_imcontext_pair_find(ctx);
+    if (pair && pair->imcontext == imcontext) {
+        _ecore_imf_wayland_imcontext_pair_del(ctx);
+        valid = EINA_TRUE;
+    }
+    else {
+        LOGE("The Ecore_Imf %p and WaylandIMContext %p pair not found!! pair : %p, pair->imcontext %p",
+            ctx, imcontext, pair, pair ? pair->imcontext : NULL);
+        _ecore_imf_wayland_imcontext_pair_log();
+    }
+
     Ecore_Event_Key *ev;
-    LOGD ("ctx : %p, focused_ctx : %p, show_req_ctx : %p", ctx, _focused_ctx, _show_req_ctx);
+    LOGD ("ctx : %p [%d], focused_ctx : %p, show_req_ctx : %p", ctx, valid, _focused_ctx, _show_req_ctx);
 
     if (!imcontext) return;
 
-    if (_ime_device && imcontext->window)
-        _device_info_send (ecore_wl_window_id_get (imcontext->window), EINA_FALSE);
-
     // TIZEN_ONLY(20150708): Support back key
     if (_input_panel_ctx == ctx) {
         _clear_hide_timer();
@@ -2612,6 +2868,7 @@ wayland_im_context_del (Ecore_IMF_Context *ctx)
             evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
 
         _focus_req_ctx = NULL;
+        _focus_req_only = EINA_TRUE;
     }
     //
 
@@ -2665,14 +2922,11 @@ wayland_im_context_reset(Ecore_IMF_Context *ctx)
 
     if (!imcontext) return;
 
-    Eina_Bool preedit_empty = check_preedit_empty(imcontext);
-
     commit_preedit (imcontext);
-    clear_preedit(imcontext);
 
     if (!imcontext->input) return;
 
-    if (imcontext->text_input && !preedit_empty) {
+    if (imcontext->text_input) {
         wl_text_input_reset(imcontext->text_input);
     }
     update_state(imcontext);
@@ -2680,15 +2934,45 @@ wayland_im_context_reset(Ecore_IMF_Context *ctx)
     imcontext->reset_serial = imcontext->serial;
 }
 
+static Eina_Bool
+_prediction_hint_data_foreach_cb(const Eina_Hash *hash, const void *key,
+                                 void *data, void *fdata)
+{
+    const char *key_str = key;
+    const char *value = data;
+    Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)fdata;
+    WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
+
+    SECURE_LOGD("key : %s, value : %s\n", key_str, value);
+
+    if (imcontext && imcontext->text_input)
+        wl_text_input_prediction_hint_data(imcontext->text_input, key_str, value);
+
+    return EINA_TRUE;
+}
+
 void
 wayland_im_context_focus_in(Ecore_IMF_Context *ctx)
 {
-
-    LOGD ("ctx : %p. enable : %d, on demand : %d\n", ctx,
+    LOGD ("ctx : %p. enable : %d, on demand : %d", ctx,
           ecore_imf_context_input_panel_enabled_get(ctx),
           ecore_imf_context_input_panel_show_on_demand_get (ctx));
 
+#ifdef SOCKET_ACTIVATION
+    activate_socket ();
+#endif
+
     if (!set_focus(ctx)) {
+        WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
+        if (imcontext && !imcontext->input) {
+            if (_focus_req_ctx != ctx)
+                _focus_req_only = EINA_TRUE;
+            _focus_req_ctx = ctx;
+            if (imcontext->canvas) {
+                evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
+                evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
+            }
+        }
         LOGW("ctx : %p. Fail to set focus!", ctx);
         return;
     }
@@ -2701,17 +2985,27 @@ wayland_im_context_focus_in(Ecore_IMF_Context *ctx)
         if (imcontext->prediction_hint)
             wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
 
-        if (strlen(imcontext->mime_type) > 0)
+        if (imcontext->mime_type)
             wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
+
+        if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
+            wl_text_input_set_input_panel_position(imcontext->text_input,
+                imcontext->input_panel_position.x, imcontext->input_panel_position.y);
+
+        const Eina_Hash *hash = ecore_imf_context_prediction_hint_hash_get(ctx);
+        if (hash)
+            eina_hash_foreach(hash, _prediction_hint_data_foreach_cb, ctx);
+
+        wl_text_input_set_content_type(imcontext->text_input, imcontext->content_hint, get_purpose(ctx));
     }
 
     if (ecore_imf_context_input_panel_enabled_get(ctx))
         if (!ecore_imf_context_input_panel_show_on_demand_get (ctx))
             show_input_panel(ctx);
         else
-            LOGD ("ctx : %p input panel on demand mode : TRUE\n", ctx);
+            LOGD ("ctx : %p input panel on demand mode : TRUE", ctx);
     else
-        LOGD ("ctx : %p input panel enable : FALSE\n", ctx);
+        LOGD ("ctx : %p input panel enable : FALSE", ctx);
 }
 
 void
@@ -2721,11 +3015,20 @@ wayland_im_context_focus_out(Ecore_IMF_Context *ctx)
 
     LOGD("ctx : %p", ctx);
 
-    if (_focus_req_ctx == ctx)
+    if (_focus_req_ctx == ctx) {
         _focus_req_ctx = NULL;
+        _focus_req_only = EINA_TRUE;
+    }
 
     if (!imcontext || !imcontext->input) return;
 
+    if (_TV) {
+        if (hw_keyboard_mode == EINA_TRUE) {
+            vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
+            hw_keyboard_mode = EINA_FALSE;
+        }
+    }
+
     if (ecore_imf_context_input_panel_enabled_get(ctx)) {
         ecore_imf_context_input_panel_hide(ctx);
     }
@@ -2773,18 +3076,22 @@ wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context  *ctx,
         if (imcontext->preedit_attrs) {
             EINA_LIST_FOREACH(imcontext->preedit_attrs, l, a) {
                 attr = malloc(sizeof(*attr));
-                attr = memcpy(attr, a, sizeof(*attr));
-                *attrs = eina_list_append(*attrs, attr);
+                if (attr) {
+                    attr = memcpy(attr, a, sizeof(*attr));
+                    *attrs = eina_list_append(*attrs, attr);
+                }
             }
         }
         else {
             if (imcontext->preedit_text) {
                 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
-                // use REVERSE style as default
-                attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
-                attr->start_index = 0;
-                attr->end_index = strlen(imcontext->preedit_text);
-                *attrs = eina_list_append(*attrs, attr);
+                if (attr) {
+                    // use REVERSE style as default
+                    attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
+                    attr->start_index = 0;
+                    attr->end_index = strlen(imcontext->preedit_text);
+                    *attrs = eina_list_append(*attrs, attr);
+                }
             }
         }
     }
@@ -2804,7 +3111,7 @@ wayland_im_context_cursor_position_set (Ecore_IMF_Context *ctx,
         imcontext->cursor_position = cursor_pos;
 
         if (imcontext->input && imcontext->text_input) {
-            LOGD ("ctx : %p, cursor pos : %d\n", ctx, cursor_pos);
+            LOGD ("ctx : %p, cursor pos : %d", ctx, cursor_pos);
 
             set_autocapital (ctx);
 
@@ -2829,10 +3136,13 @@ wayland_im_context_client_window_set(Ecore_IMF_Context *ctx,
     LOGD("client window set (window: %p)", window);
 
     if (imcontext && window) {
-        imcontext->window = ecore_wl_window_find((Ecore_Window)window);
+        Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
+
+        if (wl2_display)
+            imcontext->window = ecore_wl2_display_window_find(wl2_display, (Ecore_Window)window);
 
         if (_ime_device && imcontext->window)
-            _device_info_send (ecore_wl_window_id_get (imcontext->window), EINA_TRUE);
+            _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
     }
 }
 
@@ -2845,13 +3155,14 @@ wayland_im_context_client_canvas_set(Ecore_IMF_Context *ctx,
     LOGD("client canvas set (canvas: %p)", canvas);
 
     if (imcontext && canvas) {
+        Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
         imcontext->canvas = canvas;
 
-        if (!imcontext->window)
-            imcontext->window = ecore_wl_window_find(ecore_evas_window_get(ecore_evas_ecore_evas_get(canvas)));
+        if (wl2_display && !imcontext->window)
+            imcontext->window = ecore_wl2_display_window_find(wl2_display, ecore_evas_window_get(ecore_evas_ecore_evas_get(canvas)));
 
         if (_ime_device && imcontext->window)
-            _device_info_send (ecore_wl_window_id_get (imcontext->window), EINA_TRUE);
+            _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
     }
 }
 
@@ -2938,12 +3249,12 @@ wayland_im_context_filter_event(Ecore_IMF_Context    *ctx,
 #endif
     if (type == ECORE_IMF_EVENT_MOUSE_UP) {
         if (ecore_imf_context_input_panel_enabled_get(ctx)) {
-            LOGD ("[Mouse-up event] ctx : %p\n", ctx);
+            LOGD ("[Mouse-up event] ctx : %p", ctx);
             if (ctx == _focused_ctx) {
                 ecore_imf_context_input_panel_show(ctx);
             }
             else
-                LOGE ("Can't show IME because there is no focus. ctx : %p\n", ctx);
+                LOGE ("Can't show IME because there is no focus. ctx : %p", ctx);
         }
     }
 #if !(ENABLE_GRAB_KEYBOARD)
@@ -2980,31 +3291,19 @@ wayland_im_context_filter_event(Ecore_IMF_Context    *ctx,
             return EINA_FALSE;
 
         if (!_focused_ctx) {
-            LOGW ("no focus\n");
+            LOGW ("no focus");
             return EINA_FALSE;
         }
 
         if (_focused_ctx != ctx) {
-            LOGW ("focused context is different from the context used in ecore_imf_context_filter_event.\n");
-            LOGW ("focus context : %p, context : %p\n", _focused_ctx, ctx);
+            LOGW ("focused context is different from the context used in ecore_imf_context_filter_event.");
+            LOGW ("focus context : %p, context : %p", _focused_ctx, ctx);
             return EINA_FALSE;
         }
 
-        if (_TV) {
-            if (strcmp (ecore_key_ev.keyname, "Return") == 0 && type == ECORE_IMF_EVENT_KEY_DOWN && filter_devices (key_dev_name) && hw_keyboard_mode == EINA_TRUE) {
-                LOGD ("Changed keyboard mode from H/W to S/W ");
-                hw_keyboard_mode = EINA_FALSE;
-                vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
-
-                if (ecore_imf_context_input_panel_enabled_get (ctx)) {
-                    ecore_imf_context_input_panel_show (ctx);
-                }
-                return EINA_TRUE;
-            }
-        }
-
         do {
-            if (!ecore_key_ev.timestamp && (ecore_key_ev.modifiers & MOD_Mod5_MASK)) {
+            if (!ecore_key_ev.timestamp && (ecore_key_ev.modifiers & MOD_Mod5_MASK)
+                && key_dev_subclass == ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD) {
                 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
                     if (strcmp (ecore_key_ev.key, "space") == 0 ||
                         strcmp (ecore_key_ev.key, "KP_Space") == 0 ) {
@@ -3039,9 +3338,15 @@ wayland_im_context_filter_event(Ecore_IMF_Context    *ctx,
                                            modifiers, (key_dev_name ? key_dev_name : ""), key_dev_class, key_dev_subclass);
             //Waiting for filter_key_event_done from IME.
             //This function should return IME filtering result with boolean type.
-            struct wl_display *display = ecore_wl_display_get();
-            if (display) {
-                while (ecore_time_get() - start_time < WAIT_FOR_FILTER_DONE_SECOND && wl_display_roundtrip(display) != -1) {
+            Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
+            struct wl_display *display = NULL;
+            if (wl2_display)
+                display = ecore_wl2_display_get(wl2_display);
+            struct wl_event_queue *queue = wl_display_create_queue(display);
+
+            if (display && queue) {
+                while (ecore_time_get() - start_time < WAIT_FOR_FILTER_DONE_SECOND && _focused_ctx == ctx && wl_display_roundtrip_queue(display, queue) != -1) {
+                    wl_display_dispatch_pending(display);
                     if (imcontext->last_key_event_filter.serial == serial) {
                         ret = imcontext->last_key_event_filter.state;
                         break;
@@ -3049,11 +3354,30 @@ wayland_im_context_filter_event(Ecore_IMF_Context    *ctx,
                         break;
                 }
             }
+
+            if (queue)
+                wl_event_queue_destroy(queue);
             LOGD ("elapsed : %.3f ms, serial (last, require) : (%d, %d)", (ecore_time_get() - start_time)*1000, imcontext->last_key_event_filter.serial, serial);
         } while (0);
 
         if (type == ECORE_IMF_EVENT_KEY_DOWN) {
             if (ret == EINA_FALSE) {
+                if (_TV) {
+                    if (strcmp (ecore_key_ev.keyname, "Return") == 0 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_REMOCON) {
+                        int val;
+                        if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
+                            if (val) {
+                                LOGD ("Changed keyboard mode from H/W to S/W ");
+                                hw_keyboard_mode = EINA_FALSE;
+                                vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
+                                if (ecore_imf_context_input_panel_enabled_get (ctx)) {
+                                    ecore_imf_context_input_panel_show (ctx);
+                                }
+                                return EINA_TRUE;
+                            }
+                        }
+                    }
+                }
                 if (strcmp (ecore_key_ev.key, "space") == 0 ||
                     strcmp (ecore_key_ev.key, "KP_Space") == 0) {
                     autoperiod_insert (ctx);
@@ -3066,10 +3390,10 @@ wayland_im_context_filter_event(Ecore_IMF_Context    *ctx,
         if (eina_list_count (imcontext->keysym_list)) {
             Eina_List *n = eina_list_last(imcontext->keysym_list);
             ev = (Ecore_Event_Key *)eina_list_data_get(n);
-            int type = (unsigned long int)ev->data;
+            int event_type = (unsigned long int)ev->data;
 
             ev->data = NULL;
-            ecore_event_add(type, ev, NULL, NULL);
+            ecore_event_add(event_type, ev, _ecore_keyevent_free, NULL);
             imcontext->keysym_list = eina_list_remove_list(imcontext->keysym_list, n);
         }
     }
@@ -3125,7 +3449,7 @@ void wayland_im_context_autocapital_type_set(Ecore_IMF_Context *ctx,
         imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE;
 
     if (imcontext->input && imcontext->text_input) {
-        LOGD ("ctx : %p. set autocapital type : %d\n", ctx, autocapital_type);
+        LOGD ("ctx : %p. set autocapital type : %d", ctx, autocapital_type);
         wl_text_input_set_content_type(imcontext->text_input,
                 imcontext->content_hint,
                 get_purpose(ctx));
@@ -3192,7 +3516,7 @@ wayland_im_context_input_panel_layout_set(Ecore_IMF_Context *ctx,
     }
 
     if (imcontext->input && imcontext->text_input) {
-        LOGD ("ctx : %p, layout type : %d\n", ctx, layout);
+        LOGD ("ctx : %p, layout type : %d", ctx, layout);
         wl_text_input_set_content_type(imcontext->text_input,
                 imcontext->content_hint,
                 get_purpose(ctx));
@@ -3221,7 +3545,7 @@ wayland_im_context_input_mode_set(Ecore_IMF_Context *ctx,
         imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
 
     if (imcontext->input && imcontext->text_input) {
-        LOGD ("ctx : %p, input mode : %d\n", ctx, input_mode);
+        LOGD ("ctx : %p, input mode : %d", ctx, input_mode);
         wl_text_input_set_content_type(imcontext->text_input,
                 imcontext->content_hint,
                 get_purpose(ctx));
@@ -3250,8 +3574,48 @@ wayland_im_context_input_hint_set(Ecore_IMF_Context *ctx,
     else
         imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
 
+    // autofill
+    LOGD("autofill hint : %x\n", input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK);
+
+    switch(input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK)
+    {
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE;
+        break;
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY;
+        break;
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH;
+        break;
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR;
+        break;
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_NUMBER:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_NUMBER;
+        break;
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_EMAIL_ADDRESS:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_EMAIL_ADDRESS;
+        break;
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_PHONE:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_PHONE;
+        break;
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_ADDRESS:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_ADDRESS;
+        break;
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_CODE:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_CODE;
+        break;
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_ID:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_ID;
+        break;
+    case ECORE_IMF_INPUT_HINT_AUTOFILL_NAME:
+        imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_NAME;
+        break;
+    }
+
     if (imcontext->input && imcontext->text_input) {
-        LOGD("ctx : %p, input hint : %#x\n", ctx, input_hints);
+        LOGD("ctx : %p, input hint : %#x", ctx, input_hints);
         wl_text_input_set_content_type(imcontext->text_input,
                 imcontext->content_hint,
                 get_purpose(ctx));
@@ -3378,7 +3742,7 @@ wayland_im_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *da
         if (strncmp(data, custom_conformant_finished, strlen(custom_conformant_finished)) == 0) {
             if (_custom_conformant_event) {
                 _conformant_reset_done = EINA_TRUE;
-                LOGD("[conformant:custom,finished], _conformant_reset_done = 1\n");
+                LOGD("[conformant:custom,finished], _conformant_reset_done = 1");
                 send_will_hide_ack(NULL);
             }
             return;
@@ -3389,7 +3753,9 @@ wayland_im_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *da
         free(imcontext->imdata);
 
     imcontext->imdata = calloc(1, length);
-    memcpy(imcontext->imdata, data, length);
+    if (imcontext->imdata && data)
+        memcpy(imcontext->imdata, data, length);
+
     imcontext->imdata_size = length;
 
     if (imcontext->input && imcontext->text_input && (imcontext->imdata_size > 0))
@@ -3425,7 +3791,7 @@ wayland_im_context_bidi_direction_set(Ecore_IMF_Context *ctx, Ecore_IMF_BiDi_Dir
     imcontext->bidi_direction = bidi_direction;
 
     if (imcontext->input && imcontext->text_input) {
-        LOGD ("ctx : %p, bidi direction : %#x\n", ctx, bidi_direction);
+        LOGD ("ctx : %p, bidi direction : %#x", ctx, bidi_direction);
         wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
     }
 }
@@ -3443,10 +3809,10 @@ wayland_im_context_prediction_hint_set (Ecore_IMF_Context *ctx, const char *pred
     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
     if (!imcontext) return;
 
-    imcontext->prediction_hint = strdup(prediction_hint);
+    imcontext->prediction_hint = strdup(prediction_hint ? prediction_hint : "");
 
     if (imcontext->input && imcontext->text_input) {
-        LOGD ("ctx : %p, prediction_hint : %s\n", ctx, imcontext->prediction_hint);
+        SECURE_LOGD ("ctx : %p, prediction_hint : %s", ctx, imcontext->prediction_hint);
         wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
     }
 }
@@ -3460,17 +3826,41 @@ wayland_im_context_mime_type_accept_set (Ecore_IMF_Context *ctx, const char *mim
     imcontext->mime_type = strdup(mime_type);
 
     if (imcontext->input && imcontext->text_input && (strlen(mime_type) > 0)) {
-        LOGD ("ctx : %p, mime_type : %s\n", ctx, imcontext->mime_type);
+        LOGD ("ctx : %p, mime_type : %s", ctx, imcontext->mime_type);
         wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
     }
 }
 
+void
+wayland_im_context_input_panel_position_set (Ecore_IMF_Context *ctx, int x, int y)
+{
+    WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
+    if (!imcontext) return;
+
+    if ((imcontext->input_panel_position.x != x) || (imcontext->input_panel_position.y != y)) {
+        imcontext->input_panel_position.x = x;
+        imcontext->input_panel_position.y = y;
+    }
+
+    if (imcontext->input && imcontext->text_input) {
+        LOGD ("ctx : %p, x = %d, y = %d", ctx, x, y);
+        wl_text_input_set_input_panel_position(imcontext->text_input,
+            imcontext->input_panel_position.x, imcontext->input_panel_position.y);
+    }
+}
+
 WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager)
 {
     WaylandIMContext *context = calloc(1, sizeof(WaylandIMContext));
-
-    LOGD("new context created");
-    context->text_input_manager = text_input_manager;
+    if (context) {
+        LOGD("new context created");
+        context->text_input_manager = text_input_manager;
+    }
 
     return context;
 }
+
+void wayland_im_context_pair_set (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
+{
+    _ecore_imf_wayland_imcontext_pair_add (ctx, imcontext);
+}