Add null checking in InputMethodContextEFL
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / efl / InputMethodContextEfl.cpp
index 9cfdc63..bde3a43 100755 (executable)
@@ -30,20 +30,23 @@ using namespace WebCore;
 
 namespace WebKit {
 
+#if ENABLE(TIZEN_ISF_PORT)
+const unsigned InputMethodContextEfl::maxContextSize = 10;
+#endif
+
 InputMethodContextEfl::InputMethodContextEfl(EwkViewImpl* viewImpl, PassOwnPtr<Ecore_IMF_Context> context)
     : m_viewImpl(viewImpl)
     , m_context(context)
     , m_focused(false)
 #if ENABLE(TIZEN_ISF_PORT)
+    , m_contextID(0)
     , m_useInputMethod(false)
     , m_state(ECORE_IMF_INPUT_PANEL_STATE_HIDE)
     , m_inputPickerType(-1)
 #endif
 {
+#if !ENABLE(TIZEN_ISF_PORT)
     ASSERT(context);
-#if ENABLE(TIZEN_ISF_PORT)
-    initializeIMFContext(m_context.get(), ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL);
-#else
     ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
     ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
 #endif
@@ -70,9 +73,11 @@ void InputMethodContextEfl::onIMFInputPanelStateChanged(void* data, Ecore_IMF_Co
         evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,ime,opened", 0);
 }
 
-void InputMethodContextEfl::onIMFInputPanelGeometryChanged(void* data, Ecore_IMF_Context*, int value)
+void InputMethodContextEfl::onIMFInputPanelGeometryChanged(void* data, Ecore_IMF_Context*, int)
 {
     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
+    if (!inputMethodContext->m_context)
+        return;
 
     Eina_Rectangle rect;
     ecore_imf_context_input_panel_geometry_get(inputMethodContext->m_context.get(), &rect.x, &rect.y, &rect.w, &rect.h);
@@ -94,6 +99,8 @@ void InputMethodContextEfl::onIMFCandidatePanelStateChanged(void* data, Ecore_IM
 void InputMethodContextEfl::onIMFCandidatePanelGeometryChanged(void* data, Ecore_IMF_Context*, int)
 {
     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
+    if (!inputMethodContext->m_context)
+        return;
 
     Eina_Rectangle rect;
     ecore_imf_context_candidate_panel_geometry_get(inputMethodContext->m_context.get(), &rect.x, &rect.y, &rect.w, &rect.h);
@@ -315,6 +322,11 @@ void InputMethodContextEfl::handleMouseUpEvent(const Evas_Event_Mouse_Up*)
 
 void InputMethodContextEfl::handleKeyDownEvent(const Evas_Event_Key_Down* downEvent, bool* isFiltered)
 {
+#if ENABLE(TIZEN_ISF_PORT)
+    if (!m_context)
+        return;
+#endif
+
     Ecore_IMF_Event inputMethodEvent;
     ecore_imf_evas_event_key_down_wrap(const_cast<Evas_Event_Key_Down*>(downEvent), &inputMethodEvent.key_down);
 
@@ -366,7 +378,7 @@ void InputMethodContextEfl::updateTextInputState()
 #endif
 
 #if ENABLE(TIZEN_ISF_PORT)
-void InputMethodContextEfl::initializeIMFContext(Ecore_IMF_Context* context, Ecore_IMF_Input_Panel_Layout layout)
+void InputMethodContextEfl::initializeIMFContext(Ecore_IMF_Context* context, Ecore_IMF_Input_Panel_Layout layout, int layoutVariation, Ecore_IMF_Input_Panel_Return_Key_Type returnKeyType)
 {
     ecore_imf_context_input_panel_enabled_set(context, false);
     ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_INPUT_PANEL_STATE_EVENT, onIMFInputPanelStateChanged, this);
@@ -377,7 +389,11 @@ void InputMethodContextEfl::initializeIMFContext(Ecore_IMF_Context* context, Eco
     ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, onIMFDeleteSurrounding, this);
     ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
     ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
-    ecore_imf_context_input_panel_layout_set(m_context.get(), layout);
+
+    ecore_imf_context_input_panel_layout_set(context, layout);
+    if (layoutVariation >= 0)
+        ecore_imf_context_input_panel_layout_variation_set(context, layoutVariation);
+    ecore_imf_context_input_panel_return_key_type_set(context, returnKeyType);
 }
 
 void InputMethodContextEfl::setUseInputMethod(bool use)
@@ -386,35 +402,72 @@ void InputMethodContextEfl::setUseInputMethod(bool use)
     updateTextInputState();
 }
 
-Ecore_IMF_Input_Panel_Layout InputMethodContextEfl::layoutType(const String& type)
+PassOwnPtr<Ecore_IMF_Context> InputMethodContextEfl::takeContext(uintptr_t contextID)
 {
-    if (type == "number")
-        return ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER;
-    else if (type == "email")
-        return ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
+    size_t i = m_contextList.size();
+    while (i > 0) {
+        --i;
+        if (m_contextList[i].first == contextID) {
+            PassOwnPtr<Ecore_IMF_Context> context = m_contextList[i].second.release();
+            m_contextList.remove(i);
+            return context;
+        }
+    }
+
+    return PassOwnPtr<Ecore_IMF_Context>();
+}
+
+void InputMethodContextEfl::setIMFContext(const EditorState& editor)
+{
+    const String& type = editor.inputMethodHints;
+    Ecore_IMF_Input_Panel_Layout layout;
+    int layoutVariation = -1;
+    Ecore_IMF_Input_Panel_Return_Key_Type returnKeyType = ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
+
+    if (type == "number") {
+        layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
+        layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_NORMAL;
+    } else if (type == "signedNumber") {
+        layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
+        layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED;
+    } else if (type == "decimalNumber") {
+        layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
+        layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL;
+    } else if (type == "signedDecimalNumber") {
+        layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
+        layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL;
+    } else if (type == "email")
+        layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
     else if (type == "url")
-        return ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
+        layout = ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
     else if (type == "tel")
-        return ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
+        layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
     else if (type == "password")
-        return ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
+        layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
+    else {
+        layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
+        if (type == "search")
+            returnKeyType = ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH;
+    }
+
+    OwnPtr<Ecore_IMF_Context> context;
+    if (m_contextID == editor.inputMethodContextID)
+        context = m_context.release();
     else
-        return ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
-}
+        context = takeContext(editor.inputMethodContextID);
 
-void InputMethodContextEfl::setIMFContext(Ecore_IMF_Input_Panel_Layout layout, const String& type)
-{
-    if (m_contextList.contains(layout)) {
-        revertIMFContext();
-        m_context = m_contextList.take(layout);
-    } else if (!m_context || ecore_imf_context_input_panel_layout_get(m_context.get()) != layout) {
-        OwnPtr<Ecore_IMF_Context> context = createIMFContext(evas_object_evas_get(m_viewImpl->view()));
-        if (m_context)
-            revertIMFContext();
-        m_context = context.release();
-        initializeIMFContext(m_context.get(), layout);
+    revertIMFContext();
+
+    if (!context) {
+        context = createIMFContext(evas_object_evas_get(m_viewImpl->view()));
+        if (!context)
+            return;
+        initializeIMFContext(context.get(), layout, layoutVariation, returnKeyType);
     }
 
+    m_context = context.release();
+    m_contextID = editor.inputMethodContextID;
+
     if (type == "password" || type == "plugin")
         ecore_imf_context_prediction_allow_set(m_context.get(), false);
     else
@@ -471,9 +524,12 @@ void InputMethodContextEfl::revertIMFContext()
     if (!m_context)
         return;
 
+    if (m_contextList.size() >= maxContextSize)
+        m_contextList.remove(0);
+
     PassOwnPtr<Ecore_IMF_Context> imfContext = m_context.release();
-    int layout = ecore_imf_context_input_panel_layout_get(imfContext.get());
-    m_contextList.add(layout, imfContext);
+    m_contextList.append(std::make_pair(m_contextID, imfContext));
+    m_contextID = 0;
 }
 
 void InputMethodContextEfl::resetIMFContext()
@@ -486,9 +542,7 @@ void InputMethodContextEfl::resetIMFContext()
 
 void InputMethodContextEfl::showIMFContext(const EditorState& editor)
 {
-    Ecore_IMF_Input_Panel_Layout layout = layoutType(editor.inputMethodHints);
-
-    if (m_context && m_state != ECORE_IMF_INPUT_PANEL_STATE_HIDE && layout == ecore_imf_context_input_panel_layout_get(m_context.get()))
+    if (isShow() && m_contextID == editor.inputMethodContextID)
         return;
 
     Ewk_Settings* settings = ewk_view_settings_get(m_viewImpl->view());
@@ -537,13 +591,6 @@ void InputMethodContextEfl::showIMFContext(const EditorState& editor)
 #endif
 #endif // ENABLE(TIZEN_INPUT_TAG_EXTENSION)
 
-#if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
-    if (m_viewImpl->pageClient->isClipboardWindowOpened()) {
-        LOG(ISF, "[FAIL] Clipboard\n");
-        return;
-    }
-#endif
-
     bool hasFocus = evas_object_focus_get(m_viewImpl->view());
 
     if (!defaultKeypadEnabled) {
@@ -555,13 +602,20 @@ void InputMethodContextEfl::showIMFContext(const EditorState& editor)
         return;
     }
 
-    setIMFContext(layout, editor.inputMethodHints);
+    setIMFContext(editor);
+    if (!m_context)
+        return;
 
     if (!hasFocus) {
         m_focused = true;
         return;
     }
 
+#if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
+    if (m_viewImpl->pageClient->isClipboardWindowOpened())
+        m_viewImpl->pageClient->closeClipboardWindow();
+#endif
+
     ecore_imf_context_reset(m_context.get());
     ecore_imf_context_focus_in(m_context.get());
     ecore_imf_context_input_panel_show(m_context.get());
@@ -570,7 +624,6 @@ void InputMethodContextEfl::showIMFContext(const EditorState& editor)
     ewk_view_focused_node_adjust(m_viewImpl->view(), EINA_TRUE);
 
     m_focused = true;
-    m_state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
 }
 
 void InputMethodContextEfl::hideIMFContext()
@@ -592,7 +645,8 @@ void InputMethodContextEfl::hideIMFContext()
 
     m_focused = false;
 
-    if (ecore_imf_context_input_panel_state_get(m_context.get()) != ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
+    if (ecore_imf_context_input_panel_state_get(m_context.get()) != ECORE_IMF_INPUT_PANEL_STATE_HIDE
+        && evas_object_focus_get(m_viewImpl->view())) {
         ecore_imf_context_reset(m_context.get());
         ecore_imf_context_input_panel_hide(m_context.get());
         ecore_imf_context_focus_out(m_context.get());
@@ -625,6 +679,14 @@ bool InputMethodContextEfl::isIMEPostion(int x, int y)
     return false;
 }
 
+void InputMethodContextEfl::removeIMFContext(uintptr_t contextID)
+{
+    if (m_contextID == contextID)
+        hideIMFContext();
+
+    takeContext(contextID);
+}
+
 #endif
 
 }