ContextMenu is overlapping with IME.
authorManish R Gurnaney <m.gurnaney@samsung.com>
Tue, 20 Aug 2013 20:51:03 +0000 (02:21 +0530)
committerGerrit Code Review <gerrit@gerrit.vlan144.tizendev.org>
Mon, 2 Sep 2013 01:53:37 +0000 (01:53 +0000)
[Title] ContextMenu is overlapping with IME.
[Issue#] WEB-3307
[Problem] ContextMenu is overlapping with IME.
[Cause] When IME is present and contextmenu is created for links
        it overlaps since the IME is not hidden.
[Solution] Incase IME is present hide the IME and show the
           focus ring and contextmenu at the proper position.

Change-Id: I570896b5a004758cdc5be814065b2a8cc6d052f2

Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp
Source/WebKit2/UIProcess/API/efl/ewk_view.cpp
Source/WebKit2/UIProcess/API/efl/tizen/FocusRing.cpp
Source/WebKit2/UIProcess/API/efl/tizen/FocusRing.h
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/efl/InputMethodContextEfl.cpp
Source/WebKit2/UIProcess/efl/InputMethodContextEfl.h
Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp

index 96ac408..0076d6b 100755 (executable)
@@ -941,6 +941,11 @@ void PageClientImpl::setVisibleContentRect(const IntRect& newRect, float newScal
         m_viewImpl->didChangeScrollAndScale(previousScrollPosition, previousScale);
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
+    if (m_viewImpl->focusRing && m_viewImpl->focusRing->delayContextMenuShow())
+        m_viewImpl->focusRing->showFocusRingAndContextMenu();
+#endif
+
 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
     if (!isClipboardWindowOpened())
         updateTextSelectionHandlesAndContextMenu(true);
index b46a1c8..d721796 100755 (executable)
@@ -456,22 +456,52 @@ static Eina_Bool _ewk_view_smart_gesture_start(Ewk_View_Smart_Data* smartData, c
             if (impl->pageClient->isDragMode()) {
                 impl->pageClient->setDragMode(false);
             }
+            if (!evas_object_focus_get(impl->view()))
+                evas_object_focus_set(impl->view(), true);
+            if (InputMethodContextEfl::getSystemKeypadShow()) {
+                // If status of ime is ON, we will hide the ime and won't show FocusRing and ContextMenu.
+                // Show will happen when viewport size changes.
+                // The focus ring node is saved.
+               impl->inputMethodContext()->hideIMFContext();
 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
-            if (impl->focusRing)
-                impl->focusRing->show(IntRect(), true);
+               if (impl->focusRing) {
+                   impl->focusRing->setDelayContextMenuShow(true);
+                   impl->focusRing->show(IntRect(), true);
+               }
+#endif
+            } else {
+#if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
+                if (impl->focusRing)
+                    impl->focusRing->show(IntRect(), true);
 #endif
-            impl->gestureClient->showContextMenu(scenePoint);
+                impl->gestureClient->showContextMenu(scenePoint);
+            }
             break;
         }
 #endif
         // 2. Check to show context menu.
         if ((!hitTestResultData.absoluteImageURL.isEmpty() || !hitTestResultData.absoluteLinkURL.isEmpty())
             && !hitTestResultData.isContentEditable) {
+            if (!evas_object_focus_get(impl->view()))
+                 evas_object_focus_set(impl->view(), true);
+            if (InputMethodContextEfl::getSystemKeypadShow()) {
+                // If status of ime is ON, we will hide the ime and won't show FocusRing and ContextMenu.
+                // Show will happen when viewport size changes.
+                // The focus ring node is saved.
+                impl->inputMethodContext()->hideIMFContext();
 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
-            if (impl->focusRing)
-                impl->focusRing->show(IntRect(), true);
+                if (impl->focusRing) {
+                    impl->focusRing->setDelayContextMenuShow(true);
+                    impl->focusRing->show(IntRect(), true);
+                }
+#endif
+            } else {
+#if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
+                if (impl->focusRing)
+                    impl->focusRing->show(IntRect(), true);
 #endif
-            impl->gestureClient->showContextMenu(scenePoint);
+                impl->gestureClient->showContextMenu(scenePoint);
+            }
             break;
         }
 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
index 758453b..81d9a0f 100755 (executable)
@@ -38,6 +38,7 @@ FocusRing::FocusRing(EwkViewImpl* viewImpl)
     , m_imageInnerWidth(0)
     , m_showTimer(0)
     , m_hideTimer(0)
+    , m_delayContextMenuShow(false)
 {
 }
 
@@ -116,7 +117,6 @@ void FocusRing::show(const IntRect& rect, const bool includeOnlyImage)
     EINA_SAFETY_ON_NULL_RETURN(pageClientImpl);
 
     IntRect focusRingRect(rect);
-    Color focusRingColor;
 
     if (rect.isEmpty()) {
 #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
@@ -142,14 +142,16 @@ void FocusRing::show(const IntRect& rect, const bool includeOnlyImage)
         }
 
         focusRingRect = hitTestResultData.focusedRect;
-        focusRingColor = hitTestResultData.focusedColor;
+        m_focusRingColor = hitTestResultData.focusedColor;
 #endif // #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
+        if (m_delayContextMenuShow)
+            return;
     }
 
-    internalShow(m_viewImpl->transformToScene().mapRect(focusRingRect), focusRingColor);
+    internalShow(m_viewImpl->transformToScene().mapRect(focusRingRect));
 }
 
-void FocusRing::internalShow(const IntRect& rect, const Color& color)
+void FocusRing::internalShow(const IntRect& rect)
 {
     IntRect focusRingRect(rect);
 
@@ -189,12 +191,12 @@ void FocusRing::internalShow(const IntRect& rect, const Color& color)
     }
 
     if (m_imagePath.isNull()) {
-        if (color.isValid()) {
+        if (m_focusRingColor.isValid()) {
             int r, g, b;
-            r = (color.red() * color.alpha()) / 255;
-            g = (color.green() * color.alpha()) / 255;
-            b = (color.blue() * color.alpha()) / 255;
-            evas_object_color_set(m_focusRingObject, r, g, b, color.alpha());
+            r = (m_focusRingColor.red() * m_focusRingColor.alpha()) / 255;
+            g = (m_focusRingColor.green() * m_focusRingColor.alpha()) / 255;
+            b = (m_focusRingColor.blue() * m_focusRingColor.alpha()) / 255;
+            evas_object_color_set(m_focusRingObject, r, g, b, m_focusRingColor.alpha());
         }
 
         evas_object_move(m_focusRingObject, focusRingRect.x(), focusRingRect.y());
@@ -281,7 +283,7 @@ void FocusRing::updateScrollAndScale(const IntPoint& previousScrollPosition, flo
     rect.moveBy(previousScrollPosition);
     rect.scale(1 / previousScale);
 
-    internalShow(enclosingIntRect(m_viewImpl->transformToScene().mapRect(rect)), Color());
+    internalShow(enclosingIntRect(m_viewImpl->transformToScene().mapRect(rect)));
 #else
     UNUSED_PARAM(previousScrollPosition);
     UNUSED_PARAM(previousScale);
@@ -306,4 +308,16 @@ IntPoint FocusRing::centerPointInScreen()
     return point;
 }
 
+void FocusRing::showFocusRingAndContextMenu()
+{
+    // Should be called only when flag m_delayContextMenuShow is set true.
+    IntRect focusRingRect;
+    m_viewImpl->page()->getFocusRingNodeRect(focusRingRect);
+    if (!focusRingRect.isEmpty()) {
+        show(focusRingRect, true);
+        m_viewImpl->gestureClient->showContextMenu(centerPointInScreen());
+    }
+    m_delayContextMenuShow = false;
+}
+
 #endif // #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
index 9863db5..0c209b1 100755 (executable)
@@ -39,6 +39,7 @@ public:
     ~FocusRing();
 
     void setImage(const String&, int, int);
+    void setColor(const WebCore::Color color) { m_focusRingColor = color; }
 
     void requestToShow(const WebCore::IntPoint&, bool = false);
     void requestToHide(bool immediately = false);
@@ -51,6 +52,10 @@ public:
     const WebCore::IntRect& rect() { return m_rect; }
     WebCore::IntPoint centerPointInScreen();
 
+    void setDelayContextMenuShow(bool delay){ m_delayContextMenuShow = delay; }
+    bool delayContextMenuShow() { return m_delayContextMenuShow; }
+    void showFocusRingAndContextMenu();
+
 private:
     static const int s_showTimerTime = 100;
     static Eina_Bool showTimerCallback(void*);
@@ -60,7 +65,7 @@ private:
 
 private:
     FocusRing(EwkViewImpl*);
-    void internalShow(const WebCore::IntRect&, const WebCore::Color&);
+    void internalShow(const WebCore::IntRect&);
 
     EwkViewImpl* m_viewImpl;
 
@@ -75,6 +80,8 @@ private:
     WebCore::IntPoint m_position;
 
     WebCore::IntRect m_rect;
+    WebCore::Color m_focusRingColor;
+    bool m_delayContextMenuShow;
 };
 
 #endif // #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
index 771a444..474c21b 100755 (executable)
@@ -1012,6 +1012,10 @@ public:
     bool scrollContentByLine(const WebCore::IntPoint&, WebCore::SelectionDirection direction);
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
+    void getFocusRingNodeRect(WebCore::IntRect&);
+#endif
+
 #if ENABLE(TIZEN_LINK_MAGNIFIER)
     void getLinkMagnifierRect(const WebCore::IntPoint&, const WebCore::IntSize&);
     void openLink(const WebCore::IntPoint&);
index 5eb8030..2da230c 100755 (executable)
@@ -34,6 +34,7 @@ namespace WebKit {
 const unsigned InputMethodContextEfl::maxContextSize = 10;
 Ecore_X_Atom InputMethodContextEfl::s_externalKeyboardProperty = 0;
 bool InputMethodContextEfl::s_shouldUseExternalKeyboard = false;
+bool InputMethodContextEfl::s_isSystemKeypadShow = false;
 
 void InputMethodContextEfl::initializeExternalKeyboard()
 {
@@ -95,6 +96,8 @@ InputMethodContextEfl::InputMethodContextEfl(EwkViewImpl* viewImpl, PassOwnPtr<E
 #if ENABLE(TIZEN_ISF_PORT)
     if (!s_externalKeyboardProperty)
         initializeExternalKeyboard();
+
+    m_IMEStatusChangeHandler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, IMEStatusChangeCallback, this);
 #else
     ASSERT(context);
     ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
@@ -104,6 +107,8 @@ InputMethodContextEfl::InputMethodContextEfl(EwkViewImpl* viewImpl, PassOwnPtr<E
 
 InputMethodContextEfl::~InputMethodContextEfl()
 {
+    ecore_event_handler_del(m_IMEStatusChangeHandler);
+    m_IMEStatusChangeHandler = 0;
 }
 
 #if ENABLE(TIZEN_ISF_PORT)
@@ -839,6 +844,21 @@ void InputMethodContextEfl::fakeKeyEventTimerFired(WebCore::Timer<InputMethodCon
     upEvent.string = text;
     m_viewImpl->page()->handleKeyboardEvent(NativeWebKeyboardEvent(&upEvent));
 }
+
+Eina_Bool InputMethodContextEfl::IMEStatusChangeCallback(void* data, int type, void* event)
+{
+    // Callback to get Virtual keyboard state from window manager.
+    // In case it is invoked from other than WebPage.
+    Ecore_X_Event_Window_Property* ev = static_cast<Ecore_X_Event_Window_Property*>(event);
+
+    Ecore_X_Virtual_Keyboard_State state = ecore_x_e_virtual_keyboard_state_get(ev->win);
+    if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON)
+        s_isSystemKeypadShow = true;
+    else if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
+        s_isSystemKeypadShow = false;
+
+    return ECORE_CALLBACK_PASS_ON;
+}
 #endif // #if ENABLE(TIZEN_ISF_PORT)
 
 }
index f26f4d9..4f95d60 100755 (executable)
@@ -68,7 +68,8 @@ public:
     void hideIMFContext();
     bool isIMEPostion(int, int);
     void removeIMFContext(uintptr_t);
-    int inputPickerType() { return m_inputPickerType; }
+    static Eina_Bool IMEStatusChangeCallback(void*, int, void*);
+    static bool getSystemKeypadShow() { return s_isSystemKeypadShow; }
 #endif
 
 private:
@@ -126,6 +127,8 @@ private:
     int m_inputPickerType;
     bool m_doNotHandleFakeKeyEvent;
     WebCore::Timer<InputMethodContextEfl> m_fakeKeyEventTimer;
+    Ecore_Event_Handler* m_IMEStatusChangeHandler;
+    static bool s_isSystemKeypadShow;
 #endif
 };
 
index e64439f..7f857e8 100755 (executable)
@@ -974,6 +974,15 @@ bool WebPageProxy::scrollContentByLine(const IntPoint& point, SelectionDirection
 }
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
+void WebPageProxy::getFocusRingNodeRect(WebCore::IntRect& focusRingRect)
+{
+    if (!isValid())
+        return;
+    process()->sendSync(Messages::WebPage::GetFocusRingNodeRect(), Messages::WebPage::GetFocusRingNodeRect::Reply(focusRingRect), m_pageID);
+}
+#endif
+
 #if ENABLE(TIZEN_LINK_MAGNIFIER)
 void WebPageProxy::getLinkMagnifierRect(const WebCore::IntPoint& position, const WebCore::IntSize& size)
 {
index fdd52cc..08ba167 100755 (executable)
@@ -352,6 +352,15 @@ public:
     void scrollContentByLine(const WebCore::IntPoint&, int direction, bool& result);
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
+#if ENABLE(TOUCH_ADJUSTMENT)
+    WebCore::IntRect getFocusedRect(WebCore::HitTestResult, WebCore::Page*, const WebCore::IntPoint&, const WebCore::IntSize&);
+#else
+    WebCore::IntRect getFocusedRect(WebCore::HitTestResult, WebCore::Page*);
+#endif
+    void getFocusRingNodeRect(WebCore::IntRect&);
+#endif
+
 #if ENABLE(TIZEN_OFFLINE_PAGE_SAVE)
     void startOfflinePageSave(String subresourceFolderName);
 #endif
@@ -1212,6 +1221,10 @@ private:
     EditorState m_editorState;
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
+    RefPtr<WebCore::Node> m_focusedNode;
+#endif
+
 #if ENABLE(TIZEN_ISF_PORT)
     bool m_prepareKeyDownEvent;
     Vector<OwnPtr<KeyPressCommand> > m_keyPressCommands;
index acf5324..6cdc1dd 100755 (executable)
@@ -389,6 +389,10 @@ messages -> WebPage {
     ScrollContentByLine(WebCore::IntPoint point, int direction) -> (bool result)
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
+    GetFocusRingNodeRect() -> (WebCore::IntRect focusRingRect)
+#endif
+
 #if ENABLE(TIZEN_OFFLINE_PAGE_SAVE)
     StartOfflinePageSave(WTF::String subresourceFolderName)
 #endif
index 100f34d..ae290c3 100755 (executable)
@@ -868,9 +868,9 @@ static bool isClickableOrFocusable(Node* focusableNode)
 }
 
 #if ENABLE(TOUCH_ADJUSTMENT)
-static IntRect getFocusedRect(HitTestResult hitTestResult, Page* page, const IntPoint& point, const IntSize& area)
+IntRect WebPage::getFocusedRect(HitTestResult hitTestResult, Page* page, const IntPoint& point, const IntSize& area)
 #else
-static IntRect getFocusedRect(HitTestResult hitTestResult, Page* page)
+IntRect WebPage::getFocusedRect(HitTestResult hitTestResult, Page* page)
 #endif
 {
     Node* node = hitTestResult.innerNode();
@@ -917,14 +917,30 @@ static IntRect getFocusedRect(HitTestResult hitTestResult, Page* page)
     }
 
     if (!isFocusRingDrawable) {
-        if (node->hasTagName(HTMLNames::imgTag))
+        if (node->hasTagName(HTMLNames::imgTag)) {
+            m_focusedNode = node;
             return getNodeRect(node, node, !hitTestResult.absoluteImageURL().isEmpty());
-
+        }
         return IntRect();
     }
 
+    m_focusedNode = focusableNode;
     return getNodeRect(node, focusableNode, !hitTestResult.absoluteImageURL().isEmpty());
 }
+
+void WebPage::getFocusRingNodeRect(IntRect& focusRingRect)
+{
+    // Incase IME is ON the focus ring node is saved when user does long press.
+    // This function returns the foucs ring node rect which is required when we
+    // show the focus ring and context menu after hiding the IME.
+    if (m_focusedNode) {
+        bool isImage = false;
+        Node* node = m_focusedNode.get();
+        if (node->isElementNode() && node->hasTagName(HTMLNames::imgTag))
+            isImage = true;
+        focusRingRect = getNodeRect(node, node, isImage);
+    }
+}
 #endif
 
 #if ENABLE(TOUCH_ADJUSTMENT)