Implement that a text selection handle can be moved over another text selection handle.
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / API / efl / tizen / TextSelection.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 3788049..470da01
@@ -47,6 +47,7 @@ TextSelection::TextSelection(EwkViewImpl* viewImpl)
 #if ENABLE(TIZEN_WEBKIT2_FOR_MOVING_TEXT_SELECTION_HANDLE_FROM_OSP)
       , m_selectedHandle(0)
 #endif
+      , m_handleMovingDirection(HandleMovingDirectionNormal)
 {
     ASSERT(viewWidget);
 
@@ -99,6 +100,11 @@ void TextSelection::update()
     if (editorState.updateEditorRectOnly)
         return;
 
+#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
+    if (!editorState.shouldIgnoreCompositionSelectionChange)
+        informTextStyleState();
+#endif
+
     if (isTextSelectionMode()) {
         if (!editorState.selectionIsRange) {
             if (editorState.isContentEditable && !evas_object_focus_get(m_viewImpl->view())) {
@@ -114,30 +120,13 @@ void TextSelection::update()
 
                 setIsTextSelectionMode(false);
             }
-#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
-            m_viewImpl->page()->getTextStyleStateForSelection();
-#endif
         } else {
             if (!isTextSelectionDowned() && !isTextSelectionHandleDowned()) {
                 updateHandlers();
                 showContextMenu();
-#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
-                m_viewImpl->page()->getTextStyleStateForSelection();
-#endif
             }
         }
     }
-#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
-    else {
-        if (editorState.isContentEditable && !editorState.selectionIsRange) {
-            WebCore::IntRect caretRect;
-            m_viewImpl->page()->getCaretPosition(caretRect);
-            if (!caretRect.isEmpty()) {
-                m_viewImpl->page()->getTextStyleStateForSelection();
-            }
-        }
-    }
-#endif
 }
 
 void TextSelection::setIsTextSelectionMode(bool isTextSelectionMode)
@@ -148,8 +137,8 @@ void TextSelection::setIsTextSelectionMode(bool isTextSelectionMode)
     if (!isTextSelectionMode) {
         hide();
         clear();
-        m_leftHandle->setIsMouseDowned(false);
-        m_rightHandle->setIsMouseDowned(false);
+        initHandlesMouseDownedStatus();
+        setIsTextSelectionDowned(false);
     }
 
     m_isTextSelectionMode = isTextSelectionMode;
@@ -184,10 +173,18 @@ void TextSelection::updateHandlers()
     WebCore::IntPoint leftEvasPoint = toEvasTransform.mapPoint(leftRect.minXMaxYCorner());
     WebCore::IntPoint rightEvasPoint = toEvasTransform.mapPoint(rightRect.maxXMaxYCorner());
 
+    TextSelectionHandle* shownLeftHandle = m_leftHandle;
+    TextSelectionHandle* shownRightHandle = m_rightHandle;
+
+    if (m_handleMovingDirection == HandleMovingDirectionReverse) {
+        shownLeftHandle = m_rightHandle;
+        shownRightHandle = m_leftHandle;
+    }
+
     EditorState editorState = m_viewImpl->page()->editorState();
     if (editorState.isContentEditable) {
-        m_leftHandle->hide();
-        m_rightHandle->hide();
+        shownLeftHandle->hide();
+        shownRightHandle->hide();
 
         WebCore::IntRect editorRect = editorState.editorRect;
         WebCore::IntPoint editorLeftEvasPoint = toEvasTransform.mapPoint(editorRect.location());
@@ -197,21 +194,21 @@ void TextSelection::updateHandlers()
         evas_object_geometry_get(m_viewImpl->view(), &webViewX, &webViewY, &webViewWidth, &webViewHeight);
         if ((editorLeftEvasPoint.x() <= leftEvasPoint.x() && editorLeftEvasPoint.y() <= leftEvasPoint.y())
             && (webViewX <= leftEvasPoint.x() && webViewY <= leftEvasPoint.y())) {
-                m_leftHandle->move(leftEvasPoint);
-                m_leftHandle->show();
+            shownLeftHandle->move(leftEvasPoint, m_viewImpl->transformToScene().mapRect(leftRect));
+            shownLeftHandle->show();
         }
 
         if ((editorRightEvasPoint.x() >= rightEvasPoint.x() && editorRightEvasPoint.y() >= rightEvasPoint.y())
             && ((webViewX + webViewWidth) >= rightEvasPoint.x() && (webViewY <= rightEvasPoint.y() && (webViewY + webViewHeight) >= rightEvasPoint.y()))) {
-            m_rightHandle->move(rightEvasPoint);
-            m_rightHandle->show();
+            shownRightHandle->move(rightEvasPoint, m_viewImpl->transformToScene().mapRect(rightRect));
+            shownRightHandle->show();
         }
     } else {
-        m_leftHandle->move(leftEvasPoint);
-        m_leftHandle->show();
+        shownLeftHandle->move(leftEvasPoint, m_viewImpl->transformToScene().mapRect(leftRect));
+        shownLeftHandle->show();
 
-        m_rightHandle->move(rightEvasPoint);
-        m_rightHandle->show();
+        shownRightHandle->move(rightEvasPoint, m_viewImpl->transformToScene().mapRect(rightRect));
+        shownRightHandle->show();
     }
 }
 
@@ -279,6 +276,21 @@ void TextSelection::showContextMenu()
             point = rightRect.maxXMinYCorner();
             isPresentInViewPort = true;
         }
+
+        if (isPresentInViewPort && editorState.isContentEditable) {
+            // In case of single line editor box.
+            if (leftRect == rightRect) {
+                // draw context menu at center point of visible selection range in the editor box
+                IntRect editorRect = editorState.editorRect;
+                leftRect.intersect(editorRect);
+                if (!leftRect.isEmpty())
+                    point = leftRect.center();
+                else {
+                    // not draw context menu if there is no visible selection range in the editor box
+                    isPresentInViewPort = false;
+                }
+            }
+        }
 #else
         point = leftRect.center();
 #endif
@@ -347,13 +359,17 @@ void TextSelection::hideContextMenu()
 
 void TextSelection::setLeftSelectionToEvasPoint(const IntPoint& evasPoint)
 {
-    m_viewImpl->page()->setLeftSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
+    int result = m_viewImpl->page()->setLeftSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint), m_handleMovingDirection);
+    if (result)
+        m_handleMovingDirection = result;
     updateHandlers();
 }
 
 void TextSelection::setRightSelectionToEvasPoint(const IntPoint& evasPoint)
 {
-    m_viewImpl->page()->setRightSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
+    int result = m_viewImpl->page()->setRightSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint), m_handleMovingDirection);
+    if (result)
+        m_handleMovingDirection = result;
     updateHandlers();
 }
 
@@ -399,11 +415,11 @@ void TextSelection::handleMouseMove(TextSelectionHandle* handle, const IntPoint&
 
 void TextSelection::handleMouseUp(TextSelectionHandle* /* handle */, const IntPoint& /* position */)
 {
+    m_handleMovingDirection = HandleMovingDirectionNormal;
+
     hideMagnifier();
+    updateHandlers();
     showContextMenu();
-#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
-    m_viewImpl->page()->getTextStyleStateForSelection();
-#endif
 }
 
 bool TextSelection::isMagnifierVisible()
@@ -418,7 +434,15 @@ void TextSelection::updateHandlesAndContextMenu(bool isShow, bool isScrolling)
         return;
     }
 
+    EditorState editorState = m_viewImpl->page()->editorState();
+    if (!editorState.selectionIsRange && editorState.isContentEditable)
+        setIsTextSelectionMode(false);
+
     if (isShow) {
+#if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
+        if (m_viewImpl->pageClient->isClipboardWindowOpened())
+            return;
+#endif
         if (m_viewImpl->gestureClient->isGestureWorking())
             return;
 
@@ -468,7 +492,7 @@ Eina_Bool TextSelection::moveAnimatorCallback(void* data)
 
 // 'return false' means text selection is not possible for point.
 // 'return true' means text selection is possible.
-bool TextSelection::textSelectionDown(const IntPoint& point, bool isStartedTextSelectionFromOutside)
+bool TextSelection::textSelectionDown(const IntPoint& point)
 {
     // text selection should be ignored when longtap on handle from osp
     if (!isEnabled() && isTextSelectionHandleDowned())
@@ -480,7 +504,7 @@ bool TextSelection::textSelectionDown(const IntPoint& point, bool isStartedTextS
     setIsTextSelectionMode(false);
 
     IntPoint contentsPoint = m_viewImpl->transformFromScene().mapPoint(point);
-    bool result = m_viewImpl->page()->selectClosestWord(contentsPoint, isStartedTextSelectionFromOutside);
+    bool result = m_viewImpl->page()->selectClosestWord(contentsPoint);
     if (!result)
         return false;
 
@@ -499,7 +523,9 @@ bool TextSelection::textSelectionDown(const IntPoint& point, bool isStartedTextS
     return true;
 }
 
-void TextSelection::textSelectionMove(const IntPoint& point, bool isStartedTextSelectionFromOutside)
+static int s_textSelectionMargin = 5;
+
+void TextSelection::textSelectionMove(const IntPoint& point)
 {
     // text selection should be ignored when longtap on handle from osp
     if (!isEnabled() && isTextSelectionHandleDowned())
@@ -512,28 +538,61 @@ void TextSelection::textSelectionMove(const IntPoint& point, bool isStartedTextS
 
     WebCore::IntPoint viewPoint;
     EditorState editorState = m_viewImpl->page()->editorState();
+    bool isInEditablePicker = false;
+
+#if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
     if (editorState.isContentEditable) {
+        if (editorState.inputMethodHints == "date"
+            || editorState.inputMethodHints == "datetime"
+            || editorState.inputMethodHints == "datetime-local"
+            || editorState.inputMethodHints == "month"
+            || editorState.inputMethodHints == "time"
+            || editorState.inputMethodHints == "week")
+            isInEditablePicker = true;
+    }
+#endif
+
+    if (editorState.isContentEditable && !isInEditablePicker) {
         IntRect mapRect = m_viewImpl->transformToScene().mapRect(editorState.editorRect);
         IntPoint updatedPoint = point;
-        if ((point.y() < mapRect.y()) || (point.y() > ((mapRect.y()) + (mapRect.height()))))
-            updatedPoint.setY((mapRect.y()) + ((mapRect.height())/2) );
+        bool scrolledY = false;
+        if (point.y() < mapRect.y()) {
+            updatedPoint.setY(mapRect.y() + s_textSelectionMargin);
+            if (m_viewImpl->page()->scrollContentByLine(point,WebCore::DirectionBackward)) {
+                scrolledY = true;
+                updateMagnifier(updatedPoint);
+            }
+        } else if (point.y() > mapRect.maxY()) {
+            updatedPoint.setY(mapRect.maxY() - s_textSelectionMargin);
+            if (m_viewImpl->page()->scrollContentByLine(point,WebCore::DirectionForward)) {
+                scrolledY = true;
+                updateMagnifier(updatedPoint);
+            }
+        }
 
+        bool scrolledX = false;
         if (point.x() < mapRect.x()) {
-            updatedPoint.setX(mapRect.x());
-            if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionBackward))
+            updatedPoint.setX(mapRect.x() + s_textSelectionMargin);
+            if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionBackward)) {
+                scrolledX = true;
                 updateMagnifier(updatedPoint);
-        } else if (point.x() > ((mapRect.x()) + (mapRect.width()))) {
-            updatedPoint.setX((mapRect.x()) + (mapRect.width()));
-            if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionForward))
+            }
+        } else if (point.x() > mapRect.maxX()) {
+            updatedPoint.setX(mapRect.maxX() - s_textSelectionMargin);
+            if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionForward)) {
+                scrolledX = true;
                 updateMagnifier(updatedPoint);
-        } else {
+            }
+        }
+
+        if (!scrolledX && !scrolledY) {
             viewPoint = m_viewImpl->transformFromScene().mapPoint(updatedPoint);
-            m_viewImpl->page()->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
+            m_viewImpl->page()->selectClosestWord(viewPoint);
             updateMagnifier(updatedPoint);
         }
     } else {
         viewPoint = m_viewImpl->transformFromScene().mapPoint(point);
-        m_viewImpl->page()->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
+        m_viewImpl->page()->selectClosestWord(viewPoint);
         updateMagnifier(point);
     }
     showMagnifier();
@@ -561,21 +620,17 @@ void TextSelection::textSelectionUp(const IntPoint& point, bool isStartedTextSel
         showContextMenu();
     } else if (!isStartedTextSelectionFromOutside)
         setIsTextSelectionMode(false);
-
-#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
-    m_viewImpl->page()->getTextStyleStateForSelection();
-#endif
 }
 
 #if ENABLE(TIZEN_WEBKIT2_FOR_MOVING_TEXT_SELECTION_HANDLE_FROM_OSP)
 TextSelectionHandle* TextSelection::getSelectedHandle(const IntPoint& position)
 {
     WebCore::IntRect leftHandleRect = m_leftHandle->getHandleRect();
-    if (leftHandleRect.contains(position))
+    if (!leftHandleRect.isEmpty() && leftHandleRect.contains(position))
         return m_leftHandle;
 
     WebCore::IntRect rightHandleRect = m_rightHandle->getHandleRect();
-    if (rightHandleRect.contains(position))
+    if (!rightHandleRect.isEmpty() && rightHandleRect.contains(position))
         return m_rightHandle;
 
     return 0;
@@ -586,10 +641,8 @@ void TextSelection::textSelectionHandleDown(const IntPoint& position)
     m_selectedHandle = getSelectedHandle(position);
     if (m_selectedHandle)
         m_selectedHandle->mouseDown(position);
-    else {
-        m_leftHandle->setIsMouseDowned(false);
-        m_rightHandle->setIsMouseDowned(false);
-    }
+    else
+        initHandlesMouseDownedStatus();
 }
 
 void TextSelection::textSelectionHandleMove(const IntPoint& position)
@@ -650,6 +703,50 @@ void TextSelection::showHandlesAndContextMenu()
     }
 }
 
+void TextSelection::initHandlesMouseDownedStatus()
+{
+    m_leftHandle->setIsMouseDowned(false);
+    m_rightHandle->setIsMouseDowned(false);
+}
+
+void TextSelection::changeContextMenuPosition(WebCore::IntPoint& position)
+{
+    if (m_leftHandle->isTop()) {
+        IntRect handleRect = m_leftHandle->getHandleRect();
+        position.setY(position.y() - handleRect.height());
+    }
+}
+
+#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
+void TextSelection::informTextStyleState()
+{
+    WebCore::IntPoint startPoint, endPoint;
+    WebCore::IntRect leftRect, rightRect;
+
+    WebCore::IntRect caretRect;
+    m_viewImpl->page()->getCaretPosition(caretRect);
+    if (!caretRect.isEmpty()) {
+        startPoint.setX(caretRect.x());
+        startPoint.setY(caretRect.y() + caretRect.height());
+
+        endPoint.setX(caretRect.x() + caretRect.width());
+        endPoint.setY(caretRect.y() + caretRect.height());
+    }
+    else if (m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect)) {
+        startPoint.setX(leftRect.x());
+        startPoint.setY(leftRect.y() + leftRect.height());
+
+        endPoint.setX(rightRect.x() + rightRect.width());
+        endPoint.setY(rightRect.y() + rightRect.height());
+    }
+
+    AffineTransform toEvasTransform = m_viewImpl->transformToScene();
+    WebCore::IntPoint startEvasPoint = toEvasTransform.mapPoint(startPoint);
+    WebCore::IntPoint endEvasPoint = toEvasTransform.mapPoint(endPoint);
+
+    ewkViewTextStyleState(m_viewImpl->view(), startEvasPoint, endEvasPoint);
+}
+#endif
 } // namespace WebKit
 
 #endif // TIZEN_WEBKIT2_TEXT_SELECTION