Add keypad layout that has number variation
authorSangYong Park <sy302.park@samsung.com>
Thu, 9 May 2013 05:11:54 +0000 (14:11 +0900)
committerGerrit Code Review <gerrit2@kim11>
Wed, 29 May 2013 05:54:45 +0000 (14:54 +0900)
[Title] Add keypad layout that has number variation
[Issue#] P-130507-0231
[Problem] Number keypad contain non-numeric button
[Cause] Set wrong keypad layout
[Solution] Set proper keypad layout

Change-Id: I0a251f4c7403490bb7398fecf66c5f8902edb5ac

Conflicts:

Source/WebKit2/UIProcess/WebPageProxy.messages.in

12 files changed:
Source/WebCore/page/ChromeClient.h
Source/WebCore/rendering/RenderObject.cpp
Source/WebKit2/Shared/EditorState.cpp
Source/WebKit2/Shared/EditorState.h
Source/WebKit2/UIProcess/WebPageProxy.h [changed mode: 0644->0755]
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/UIProcess/efl/InputMethodContextEfl.cpp
Source/WebKit2/UIProcess/efl/InputMethodContextEfl.h
Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp [changed mode: 0644->0755]
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h
Source/WebKit2/WebProcess/WebPage/WebPage.cpp

index 55dcd35..b40de3f 100755 (executable)
@@ -398,7 +398,7 @@ namespace WebCore {
         virtual float contentsScaleFactor() const = 0;
 #endif
 
-#if ENABLE(TIZEN_SCREEN_READER)
+#if OS(TIZEN)
         virtual void rendererWillBeDestroyed(RenderObject*) { }
 #endif
 
index 37acb1d..aa20968 100755 (executable)
@@ -2307,7 +2307,7 @@ void RenderObject::willBeDestroyed()
     if (frame() && frame()->eventHandler()->autoscrollRenderer() == this)
         frame()->eventHandler()->stopAutoscrollTimer(true);
 
-#if ENABLE(TIZEN_SCREEN_READER)
+#if OS(TIZEN)
     if (frame() && frame()->page())
         frame()->page()->chrome()->client()->rendererWillBeDestroyed(this);
 #endif
index 6bf25d7..504e92e 100755 (executable)
@@ -42,6 +42,7 @@ void EditorState::encode(CoreIPC::ArgumentEncoder* encoder) const
     encoder->encode(hasComposition);
 
 #if ENABLE(TIZEN_ISF_PORT)
+    encoder->encode(inputMethodContextID);
     encoder->encode(inputMethodHints);
     encoder->encode(surroundingText);
     encoder->encode(cursorPosition);
@@ -92,6 +93,9 @@ bool EditorState::decode(CoreIPC::ArgumentDecoder* decoder, EditorState& result)
         return false;
 
 #if ENABLE(TIZEN_ISF_PORT)
+    if (!decoder->decode(result.inputMethodContextID))
+        return false;
+
     if (!decoder->decode(result.inputMethodHints))
         return false;
 
index 981a2fc..389e897 100755 (executable)
@@ -43,6 +43,7 @@ struct EditorState {
         , isInPasswordField(false)
         , hasComposition(false)
 #if ENABLE(TIZEN_ISF_PORT)
+        , inputMethodContextID(0)
         , cursorPosition(0)
 #endif
 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
@@ -65,6 +66,7 @@ struct EditorState {
     bool isInPasswordField;
     bool hasComposition;
 #if ENABLE(TIZEN_ISF_PORT)
+    uintptr_t inputMethodContextID;
     WTF::String inputMethodHints;
     WTF::String surroundingText;
     unsigned cursorPosition;
old mode 100644 (file)
new mode 100755 (executable)
index e760886..1a85048
@@ -953,6 +953,7 @@ public:
     void deleteSurroundingText(int, int);
 
     void didCancelComposition();
+    void removeInputMethodContext(uintptr_t);
 #endif
 
     void setBackgroundColor(double red, double green, double blue, double alpha);
index 607a3c7..ab713ec 100755 (executable)
@@ -476,4 +476,8 @@ messages -> WebPageProxy {
 #if ENABLE(TIZEN_FILE_SYSTEM)
     ExceededLocalFileSystemQuota(uint64_t frameID, WTF::String originIdentifier, int64_t currentUsage) -> (bool allow) Delayed
 #endif
+
+#if ENABLE(TIZEN_ISF_PORT)
+    RemoveInputMethodContext(uintptr_t id)
+#endif
 }
index 5c25dc7..8716672 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
@@ -366,7 +369,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_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 +380,10 @@ 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);
 }
 
 void InputMethodContextEfl::setUseInputMethod(bool use)
@@ -386,35 +392,65 @@ 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;
+
+    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
-        return ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
-}
+        layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
 
-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);
+    OwnPtr<Ecore_IMF_Context> context;
+    if (m_contextID == editor.inputMethodContextID)
+        context = m_context.release();
+    else
+        context = takeContext(editor.inputMethodContextID);
+
+    if (!context) {
+        context = createIMFContext(evas_object_evas_get(m_viewImpl->view()));
+        initializeIMFContext(context.get(), layout, layoutVariation);
     }
 
+    revertIMFContext();
+    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 +507,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 +525,7 @@ void InputMethodContextEfl::resetIMFContext()
 
 void InputMethodContextEfl::showIMFContext(const EditorState& editor)
 {
-    Ecore_IMF_Input_Panel_Layout layout = layoutType(editor.inputMethodHints);
-
-    if (isShow() && 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());
@@ -548,7 +585,7 @@ void InputMethodContextEfl::showIMFContext(const EditorState& editor)
         return;
     }
 
-    setIMFContext(layout, editor.inputMethodHints);
+    setIMFContext(editor);
 
     if (!hasFocus) {
         m_focused = true;
@@ -623,6 +660,14 @@ bool InputMethodContextEfl::isIMEPostion(int x, int y)
     return false;
 }
 
+void InputMethodContextEfl::removeIMFContext(uintptr_t contextID)
+{
+    if (m_contextID == contextID)
+        hideIMFContext();
+
+    takeContext(contextID);
+}
+
 #endif
 
 }
index 2da5645..a439889 100755 (executable)
@@ -36,9 +36,13 @@ class InputMethodContextEfl {
 public:
     static PassOwnPtr<InputMethodContextEfl> create(EwkViewImpl* viewImpl, Evas* canvas)
     {
+#if ENABLE(TIZEN_ISF_PORT)
+        OwnPtr<Ecore_IMF_Context> context;
+#else
         OwnPtr<Ecore_IMF_Context> context = createIMFContext(canvas);
         if (!context)
             return nullptr;
+#endif
 
         return adoptPtr(new InputMethodContextEfl(viewImpl, context.release()));
     }
@@ -57,6 +61,7 @@ public:
     void resetIMFContext();
     void hideIMFContext();
     bool isIMEPostion(int, int);
+    void removeIMFContext(uintptr_t);
 #endif
 
 private:
@@ -67,7 +72,7 @@ private:
     static void onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context*, void* eventInfo);
 
 #if ENABLE(TIZEN_ISF_PORT)
-    void initializeIMFContext(Ecore_IMF_Context*, Ecore_IMF_Input_Panel_Layout);
+    void initializeIMFContext(Ecore_IMF_Context*, Ecore_IMF_Input_Panel_Layout, int);
 
     static void onIMFInputPanelStateChanged(void*, Ecore_IMF_Context*, int);
     static void onIMFInputPanelGeometryChanged(void*, Ecore_IMF_Context*, int);
@@ -76,8 +81,8 @@ private:
     static Eina_Bool onIMFRetrieveSurrounding(void*, Ecore_IMF_Context*, char**, int*);
     static void onIMFDeleteSurrounding(void*, Ecore_IMF_Context*, void*);
 
-    Ecore_IMF_Input_Panel_Layout layoutType(const String&);
-    void setIMFContext(Ecore_IMF_Input_Panel_Layout, const String&);
+    PassOwnPtr<Ecore_IMF_Context> takeContext(uintptr_t);
+    void setIMFContext(const EditorState&);
     void revertIMFContext();
     void showIMFContext(const EditorState&);
     void destroyIMFContextList();
@@ -94,7 +99,10 @@ private:
     bool m_focused;
 
 #if ENABLE(TIZEN_ISF_PORT)
-    HashMap<int, OwnPtr<Ecore_IMF_Context> > m_contextList;
+    static const unsigned maxContextSize;
+
+    Vector<std::pair<uintptr_t, OwnPtr<Ecore_IMF_Context> > > m_contextList;
+    uintptr_t m_contextID;
     bool m_useInputMethod;
     int m_state;
     WebCore::IntRect m_imeRect;
old mode 100644 (file)
new mode 100755 (executable)
index a7758e8..306525d
@@ -288,7 +288,16 @@ void WebPageProxy::didCancelComposition()
         inputMethodContext->resetIMFContext();
     m_didCancelCompositionFromWebProcess = false;
 }
-#endif
+
+void WebPageProxy::removeInputMethodContext(uintptr_t id)
+{
+    InputMethodContextEfl* inputMethodContext = static_cast<PageClientImpl*>(m_pageClient)->viewImpl()->inputMethodContext();
+    if (!inputMethodContext)
+        return;
+
+    inputMethodContext->removeIMFContext(id);
+}
+#endif // #if ENABLE(TIZEN_ISF_PORT)
 
 void WebPageProxy::requestUpdateFormNavigation()
 {
index 8aa85ab..a0ee02f 100755 (executable)
@@ -1004,10 +1004,17 @@ float WebChromeClient::contentsScaleFactor() const
 }
 #endif
 
-#if ENABLE(TIZEN_SCREEN_READER)
+#if OS(TIZEN)
 void WebChromeClient::rendererWillBeDestroyed(RenderObject* object)
 {
+#if ENABLE(TIZEN_SCREEN_READER)
     m_page->updateScreenReaderFocus(object);
+#endif
+
+#if ENABLE(TIZEN_ISF_PORT)
+    if (object->node() && object->node()->isRootEditableElement())
+        m_page->send(Messages::WebPageProxy::RemoveInputMethodContext(reinterpret_cast<uintptr_t>(object->node())));
+#endif
 }
 #endif
 
index 876ac46..7a1b99f 100755 (executable)
@@ -260,7 +260,7 @@ private:
     virtual float contentsScaleFactor() const OVERRIDE;
 #endif
 
-#if ENABLE(TIZEN_SCREEN_READER)
+#if OS(TIZEN)
     virtual void rendererWillBeDestroyed(WebCore::RenderObject*);
 #endif
 
index d694d4a..1e35a0d 100755 (executable)
@@ -558,11 +558,11 @@ EditorState WebPage::editorState() const
     result.shouldIgnoreCompositionSelectionChange = frame->editor()->ignoreCompositionSelectionChange();
 
 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION) || ENABLE(TIZEN_ISF_PORT)
-    Element* selectionRoot = frame->selection()->rootEditableElementOrDocumentElement();
-    if (!selectionRoot)
+    Element* rootEditableElement = frame->selection()->rootEditableElement();
+    if (!rootEditableElement)
         return result;
 
-    result.editorRect = frame->view()->contentsToWindow(selectionRoot->getPixelSnappedRect());
+    result.editorRect = frame->view()->contentsToWindow(rootEditableElement->getPixelSnappedRect());
     if (result.editorRect.maxX() <= 0 || result.editorRect.maxY() <= 0)
         result.isContentEditable = false;
 
@@ -573,11 +573,33 @@ EditorState WebPage::editorState() const
 #endif
 
 #if ENABLE(TIZEN_ISF_PORT)
-    Node* hostNode = selectionRoot->shadowAncestorNode();
-    if (result.isContentEditable) {
+    if (!result.shouldIgnoreCompositionSelectionChange && result.isContentEditable) {
+        result.inputMethodContextID = reinterpret_cast<uintptr_t>(rootEditableElement);
+
+        Node* hostNode = rootEditableElement->shadowHost();
+        if (!hostNode)
+            hostNode = rootEditableElement;
+
         HTMLTextFormControlElement* formControl = toTextFormControl(hostNode);
         if (formControl) {
-            result.inputMethodHints = formControl->type();
+            const AtomicString& type = formControl->type();
+
+            if (type == "number" && formControl->hasTagName(HTMLNames::inputTag)) {
+                StepRange stepRange = static_cast<HTMLInputElement*>(formControl)->createStepRange(RejectAny);
+                bool needsSigned = stepRange.minimum().isNegative();
+                bool needsDecimal = (stepRange.step().floor() != stepRange.step());
+
+                if (needsSigned && needsDecimal)
+                    result.inputMethodHints = "signedDecimalNumber";
+                else if (needsSigned)
+                    result.inputMethodHints = "signedNumber";
+                else if (needsDecimal)
+                    result.inputMethodHints = "decimalNumber";
+                else
+                    result.inputMethodHints = "number";
+            } else
+                result.inputMethodHints = type;
+
             result.surroundingText = formControl->value();
         }