Update cursor position before handling key event
authorSangYong Park <sy302.park@samsung.com>
Fri, 27 Sep 2013 07:11:59 +0000 (16:11 +0900)
committerSangYong Park <sy302.park@samsung.com>
Fri, 27 Sep 2013 07:24:48 +0000 (16:24 +0900)
[Title] Update cursor position before handling key event
[Issue#] N_SE-52622
[Problem] Multiple capital letter was inserted when autocapital was enabled.
[Cause] Cursor position updates are slow.
[Solution] Update cursor position before handling key event.

Change-Id: I2bf019f5e267250f99d65fbdbb8a08af39e607b4

Source/WebKit2/UIProcess/efl/InputMethodContextEfl.cpp
Source/WebKit2/UIProcess/efl/InputMethodContextEfl.h

index 0cbda23..879a6d4 100755 (executable)
@@ -98,6 +98,7 @@ InputMethodContextEfl::InputMethodContextEfl(EwkViewImpl* viewImpl, PassOwnPtr<E
     , m_inputPickerType(-1)
     , m_doNotHandleFakeKeyEvent(false)
     , m_fakeKeyEventTimer(this, &InputMethodContextEfl::fakeKeyEventTimerFired)
+    , m_approximateCursorPosition(0)
 #endif
 {
 #if ENABLE(TIZEN_ISF_PORT)
@@ -178,7 +179,11 @@ Eina_Bool InputMethodContextEfl::onIMFRetrieveSurrounding(void* data, Ecore_IMF_
     const EditorState& editor = inputMethodContext->m_viewImpl->page()->editorState();
 
     if (text) {
-        CString utf8Text(editor.surroundingText.utf8());
+        CString utf8Text;
+        if (!inputMethodContext->m_approximateSurroundingText.isNull())
+            utf8Text = inputMethodContext->m_approximateSurroundingText.utf8();
+        else
+            utf8Text = editor.surroundingText.utf8();
         size_t length = utf8Text.length();
 
         *text = static_cast<char*>(malloc((length + 1) * sizeof(char)));
@@ -190,8 +195,12 @@ Eina_Bool InputMethodContextEfl::onIMFRetrieveSurrounding(void* data, Ecore_IMF_
         (*text)[length] = 0;
     }
 
-    if (offset)
-        *offset = editor.cursorPosition;
+    if (offset) {
+        if (!inputMethodContext->m_approximateSurroundingText.isNull())
+            *offset = inputMethodContext->m_approximateCursorPosition;
+        else
+            *offset = editor.cursorPosition;
+    }
 
     return true;
 }
@@ -206,6 +215,8 @@ void InputMethodContextEfl::onIMFDeleteSurrounding(void* data, Ecore_IMF_Context
 
     Ecore_IMF_Event_Delete_Surrounding* event = static_cast<Ecore_IMF_Event_Delete_Surrounding*>(eventInfo);
     inputMethodContext->m_viewImpl->page()->deleteSurroundingText(event->offset, event->n_chars);
+
+    inputMethodContext->updateApproximateText(String(), event->offset, event->n_chars);
 }
 
 void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
@@ -216,7 +227,10 @@ void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Con
 
     inputMethodContext->requestFakeKeyEvent();
 
-    inputMethodContext->m_viewImpl->page()->confirmComposition(String::fromUTF8(static_cast<char*>(eventInfo)));
+    String completeString = String::fromUTF8(static_cast<char*>(eventInfo));
+    inputMethodContext->m_viewImpl->page()->confirmComposition(completeString);
+
+    inputMethodContext->updateApproximateText(completeString, 0, 0);
 }
 
 #if ENABLE(TIZEN_WEBKIT2_SUPPORT_JAPANESE_IME)
@@ -336,6 +350,8 @@ void InputMethodContextEfl::onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Co
 
     if (buffer)
         free(buffer);
+
+    inputMethodContext->updateApproximateText(preeditString, 0, 0);
 }
 #else
 void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
@@ -422,6 +438,22 @@ void InputMethodContextEfl::handleKeyDownEvent(const Evas_Event_Key_Down* downEv
 
 #if ENABLE(TIZEN_ISF_PORT)
     m_doNotHandleFakeKeyEvent = false;
+
+    const EditorState& state = m_viewImpl->page()->editorState();
+
+    if (m_approximateSurroundingText.isNull() && downEvent->compose) {
+        if (downEvent->compose[0] == 0x8) {
+            if (state.cursorPosition > 0)
+                updateApproximateText(String(), state.cursorPosition - 1, 1);
+        } else if (downEvent->compose[0] == 0x7f) {
+            if (state.cursorPosition < state.surroundingText.length())
+                updateApproximateText(String(), state.cursorPosition, 1);
+        } else
+            updateApproximateText(String::fromUTF8(downEvent->compose), 0, 0);
+    }
+
+    if (!state.hasComposition)
+        ecore_imf_context_cursor_position_set(m_context.get(), m_approximateCursorPosition);
 #endif
 }
 
@@ -439,6 +471,8 @@ void InputMethodContextEfl::updateTextInputState()
 
     if (m_context && !editor.hasComposition)
         ecore_imf_context_cursor_position_set(m_context.get(), editor.cursorPosition);
+
+    m_approximateSurroundingText = String();
 }
 
 void InputMethodContextEfl::updateTextInputStateByUserAction(bool setFocus)
@@ -814,20 +848,60 @@ void InputMethodContextEfl::requestFakeKeyEvent()
 
 void InputMethodContextEfl::fakeKeyEventTimerFired(WebCore::Timer<InputMethodContextEfl>*)
 {
-    const char* text = " ";
+    UChar ch = 0;
+    if (!m_approximateSurroundingText.isNull()) {
+        if (!m_approximateCursorPosition)
+            ch = m_approximateSurroundingText[0];
+        else if (m_approximateCursorPosition > m_approximateSurroundingText.length())
+            ch = m_approximateSurroundingText[m_approximateSurroundingText.length() - 1];
+        else
+            ch = m_approximateSurroundingText[m_approximateCursorPosition - 1];
+    }
+
+    String string;
+    if (Unicode::isSeparatorSpace(ch))
+        string = "space";
+    else if (Unicode::isPrintableChar(ch))
+        string.append(ch);
+    else
+        string = "Shift_L";
+
+    CString stringForEvent = string.utf8();
+    const char* data = stringForEvent.data();
 
     Evas_Event_Key_Down downEvent;
     memset(&downEvent, 0, sizeof(Evas_Event_Key_Down));
-    downEvent.key = text;
-    downEvent.string = text;
+    downEvent.key = data;
+    downEvent.string = data;
     m_viewImpl->page()->handleKeyboardEvent(NativeWebKeyboardEvent(&downEvent, true));
 
     Evas_Event_Key_Up upEvent;
     memset(&upEvent, 0, sizeof(Evas_Event_Key_Up));
-    upEvent.key = text;
-    upEvent.string = text;
+    upEvent.key = data;
+    upEvent.string = data;
     m_viewImpl->page()->handleKeyboardEvent(NativeWebKeyboardEvent(&upEvent));
 }
+
+void InputMethodContextEfl::updateApproximateText(const String& text, unsigned removePosition, unsigned removeLength)
+{
+    if (m_approximateSurroundingText.isNull()) {
+        const EditorState& state = m_viewImpl->page()->editorState();
+
+        m_approximateSurroundingText = state.surroundingText;
+        if (m_approximateSurroundingText.isNull())
+            m_approximateSurroundingText = emptyString();
+        m_approximateCursorPosition = state.cursorPosition;
+    }
+
+    if (!text.isNull()) {
+        m_approximateSurroundingText.insert(text, m_approximateCursorPosition);
+        m_approximateCursorPosition += text.length();
+    } else {
+        m_approximateSurroundingText.remove(removePosition, removeLength);
+        if (m_approximateCursorPosition > removePosition && m_approximateCursorPosition <= removePosition + removeLength)
+            m_approximateCursorPosition = removePosition;
+    }
+}
 #endif // #if ENABLE(TIZEN_ISF_PORT)
 
 }
index fc2f304..95bd2f5 100755 (executable)
@@ -105,6 +105,8 @@ private:
 
     void requestFakeKeyEvent();
     void fakeKeyEventTimerFired(WebCore::Timer<InputMethodContextEfl>*);
+
+    void updateApproximateText(const String&, unsigned, unsigned);
 #endif
 
     EwkViewImpl* m_viewImpl;
@@ -125,6 +127,8 @@ private:
     int m_inputPickerType;
     bool m_doNotHandleFakeKeyEvent;
     WebCore::Timer<InputMethodContextEfl> m_fakeKeyEventTimer;
+    String m_approximateSurroundingText;
+    unsigned m_approximateCursorPosition;
 #endif
 };