Implemented scrolling of text when the magnifier is on
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / API / efl / tizen / TextSelection.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 2b542c8..75039b6
@@ -29,6 +29,7 @@
 #include "TextSelection.h"
 
 #include "EditorState.h"
+#include "EwkViewImpl.h"
 #include "NativeWebMouseEvent.h"
 #include "ewk_view.h"
 #include <Elementary.h>
@@ -37,18 +38,15 @@ using namespace WebCore;
 
 namespace WebKit {
 
-TextSelection::TextSelection(Evas_Object* viewWidget, WebPageProxy* page, PageClientImpl* pageClient)
-      : m_object(viewWidget)
-      , m_page(page)
-      , m_pageClient(pageClient)
+TextSelection::TextSelection(EwkViewImpl* viewImpl)
+      : m_viewImpl(viewImpl)
       , m_isTextSelectionDowned(false)
       , m_isTextSelectionMode(false)
       , m_moveAnimator(0)
+      , m_showTimer(0)
 {
     ASSERT(viewWidget);
 
-    m_viewImpl = EwkViewImpl::fromEvasObject(m_object);
-
     const Eina_List* defaultThemeList = elm_theme_list_get(0);
 
     const Eina_List* l;
@@ -57,17 +55,17 @@ TextSelection::TextSelection(Evas_Object* viewWidget, WebPageProxy* page, PageCl
         char* themePath = elm_theme_list_item_path_get((const char*)theme, 0);
 
         if (themePath) {
-            m_leftHandle = new TextSelectionHandle(m_object, themePath, "elm/entry/selection/block_handle_left", true, this);
-            m_rightHandle = new TextSelectionHandle(m_object, themePath, "elm/entry/selection/block_handle_right", false, this);
+            m_leftHandle = new TextSelectionHandle(m_viewImpl->view(), themePath, "elm/entry/selection/block_handle_left", true, this);
+            m_rightHandle = new TextSelectionHandle(m_viewImpl->view(), themePath, "elm/entry/selection/block_handle_right", false, this);
 
             free(themePath);
             break;
         }
     }
 
-    m_magnifier = new TextSelectionMagnifier(m_object, page, pageClient);
+    m_magnifier = new TextSelectionMagnifier(m_viewImpl);
 
-    evas_object_event_callback_add(m_object, EVAS_CALLBACK_MOUSE_UP, onMouseUp, this);
+    evas_object_event_callback_add(m_viewImpl->view(), EVAS_CALLBACK_MOUSE_UP, onMouseUp, this);
 }
 
 TextSelection::~TextSelection()
@@ -80,48 +78,50 @@ TextSelection::~TextSelection()
 
     delete m_magnifier;
 
-    evas_object_event_callback_del(m_object, EVAS_CALLBACK_MOUSE_UP, onMouseUp);
+    evas_object_event_callback_del(m_viewImpl->view(), EVAS_CALLBACK_MOUSE_UP, onMouseUp);
 }
 
 void TextSelection::update()
 {
-    if (isTextSelectionMode() ) {
-        EditorState editorState = m_page->editorState();
+    EditorState editorState = m_viewImpl->page()->editorState();
+    if (editorState.updateEditorRectOnly)
+        return;
+
+    if (isTextSelectionMode()) {
         if (!editorState.selectionIsRange) {
-            if (editorState.isContentEditable && !evas_object_focus_get(m_object)) {
+            if (editorState.isContentEditable && !evas_object_focus_get(m_viewImpl->view())) {
                 WebCore::IntRect caretRect;
-                m_page->getCaretPosition(caretRect);
+                m_viewImpl->page()->getCaretPosition(caretRect);
                 if (!caretRect.isEmpty())
                     return;
             } else {
                 WebCore::IntRect leftRect;
                 WebCore::IntRect rightRect;
-                if (isTextSelectionDowned() || m_page->getSelectionHandlers(leftRect, rightRect))
+                if (isTextSelectionDowned() || m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect))
                     return;
 
                 setIsTextSelectionMode(false);
             }
 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
-            m_page->getTextStyleStateForSelection();
+            m_viewImpl->page()->getTextStyleStateForSelection();
 #endif
         } else {
             if (!isTextSelectionDowned() && !isTextSelectionHandleDowned()) {
                 updateHandlers();
                 showContextMenu();
 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
-                m_page->getTextStyleStateForSelection();
+                m_viewImpl->page()->getTextStyleStateForSelection();
 #endif
             }
         }
     }
 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
     else {
-        EditorState editorState = m_page->editorState();
         if (editorState.isContentEditable && !editorState.selectionIsRange) {
             WebCore::IntRect caretRect;
-            m_page->getCaretPosition(caretRect);
+            m_viewImpl->page()->getCaretPosition(caretRect);
             if (!caretRect.isEmpty()) {
-                m_page->getTextStyleStateForSelection();
+                m_viewImpl->page()->getTextStyleStateForSelection();
             }
         }
     }
@@ -143,11 +143,11 @@ void TextSelection::setIsTextSelectionMode(bool isTextSelectionMode)
 
 void TextSelection::clear()
 {
-    EditorState editorState = m_page->editorState();
+    EditorState editorState = m_viewImpl->page()->editorState();
     if (!editorState.selectionIsRange)
         return;
 
-    m_page->selectionRangeClear();
+    m_viewImpl->page()->selectionRangeClear();
 }
 
 void TextSelection::hide()
@@ -160,16 +160,17 @@ void TextSelection::hide()
 void TextSelection::updateHandlers()
 {
     WebCore::IntRect leftRect, rightRect;
-    if (!m_page->getSelectionHandlers(leftRect, rightRect)) {
-        clear();
+    if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect))
         return;
-    }
+
+    m_lastLeftHandleRect = leftRect;
+    m_lastRightHandleRect = rightRect;
 
     AffineTransform toEvasTransform = m_viewImpl->transformToScene();
     WebCore::IntPoint leftEvasPoint = toEvasTransform.mapPoint(leftRect.minXMaxYCorner());
     WebCore::IntPoint rightEvasPoint = toEvasTransform.mapPoint(rightRect.maxXMaxYCorner());
 
-    EditorState editorState = m_page->editorState();
+    EditorState editorState = m_viewImpl->page()->editorState();
     if (editorState.isContentEditable) {
         m_leftHandle->hide();
         m_rightHandle->hide();
@@ -179,7 +180,7 @@ void TextSelection::updateHandlers()
         WebCore::IntPoint editorRightEvasPoint = toEvasTransform.mapPoint(editorRect.maxXMaxYCorner());
         int webViewX, webViewY, webViewWidth, webViewHeight;
 
-        evas_object_geometry_get(m_object, &webViewX, &webViewY, &webViewWidth, &webViewHeight);
+        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);
@@ -227,7 +228,7 @@ void TextSelection::showContextMenu()
     if (!isEnabled())
         return;
 
-    EditorState editorState = m_page->editorState();
+    EditorState editorState = m_viewImpl->page()->editorState();
     if (!editorState.selectionIsRange && !editorState.isContentEditable)
         return;
 
@@ -237,16 +238,15 @@ void TextSelection::showContextMenu()
 #endif
     if (editorState.selectionIsRange) {
         WebCore::IntRect leftRect, rightRect;
-        if (!m_page->getSelectionHandlers(leftRect, rightRect)) {
-            clear();
+        if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect))
             return;
-        }
+
 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
         // Checking if this point is in viewport area. If the calcualated
         // point/Left/Right point are in view port then draw else do not draw the
         // context menu. Only draw the selection points.
-        FloatRect unscaledRect = FloatRect(m_pageClient->visibleContentRect());
-        unscaledRect.scale(1 / m_pageClient->scaleFactor());
+        FloatRect unscaledRect = FloatRect(m_viewImpl->pageClient->visibleContentRect());
+        unscaledRect.scale(1 / m_viewImpl->pageClient->scaleFactor());
         IntRect viewportRect = enclosingIntRect(unscaledRect);
 
         WebCore::IntPoint visiblePoint = leftRect.center();
@@ -270,7 +270,7 @@ void TextSelection::showContextMenu()
 #endif
     } else if (editorState.isContentEditable) {
         WebCore::IntRect caretRect;
-        m_page->getCaretPosition(caretRect);
+        m_viewImpl->page()->getCaretPosition(caretRect);
 
         if (caretRect.isEmpty())
             return;
@@ -287,12 +287,12 @@ void TextSelection::showContextMenu()
 
     // show context menu if its in viewport else do not show the contextmenu
 
-    Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_object));
+    Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_viewImpl->view()));
     if (!smartData || !smartData->api || !smartData->api->mouse_down || !smartData->api->mouse_up)
         return;
 
     point = m_viewImpl->transformToScene().mapPoint(point);
-    Evas* evas = evas_object_evas_get(m_object);
+    Evas* evas = evas_object_evas_get(m_viewImpl->view());
 
     // send mouse down.
     Evas_Event_Mouse_Down mouseDown;
@@ -328,18 +328,18 @@ void TextSelection::hideContextMenu()
     if (!isEnabled())
         return;
 
-    m_page->hideContextMenu();
+    m_viewImpl->page()->hideContextMenu();
 }
 
 void TextSelection::setLeftSelectionToEvasPoint(const IntPoint& evasPoint)
 {
-    m_page->setLeftSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
+    m_viewImpl->page()->setLeftSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
     updateHandlers();
 }
 
 void TextSelection::setRightSelectionToEvasPoint(const IntPoint& evasPoint)
 {
-    m_page->setRightSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
+    m_viewImpl->page()->setRightSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
     updateHandlers();
 }
 
@@ -347,11 +347,11 @@ void TextSelection::setRightSelectionToEvasPoint(const IntPoint& evasPoint)
 void TextSelection::handleMouseDown(TextSelectionHandle* handle, const IntPoint& /*position*/)
 {
     WebCore::IntPoint basePosition;
-    EditorState editorState = m_page->editorState();
+    EditorState editorState = m_viewImpl->page()->editorState();
 
     if (editorState.selectionIsRange) {
         WebCore::IntRect leftRect, rightRect;
-        if (!m_page->getSelectionHandlers(leftRect, rightRect)) {
+        if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect)) {
             clear();
             return;
         }
@@ -388,7 +388,7 @@ void TextSelection::handleMouseUp(TextSelectionHandle* /* handle */, const IntPo
     hideMagnifier();
     showContextMenu();
 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
-    m_page->getTextStyleStateForSelection();
+    m_viewImpl->page()->getTextStyleStateForSelection();
 #endif
 }
 
@@ -443,7 +443,7 @@ Eina_Bool TextSelection::moveAnimatorCallback(void* data)
     TextSelection* textSelection = static_cast<TextSelection*>(data);
 
     Evas_Coord_Point point;
-    evas_pointer_canvas_xy_get(evas_object_evas_get(textSelection->m_object), &point.x, &point.y);
+    evas_pointer_canvas_xy_get(evas_object_evas_get(textSelection->m_viewImpl->view()), &point.x, &point.y);
     textSelection->textSelectionMove(IntPoint(point.x, point.y));
 
     return ECORE_CALLBACK_RENEW;
@@ -453,10 +453,14 @@ Eina_Bool TextSelection::moveAnimatorCallback(void* data)
 // 'return true' means text selection is possible.
 bool TextSelection::textSelectionDown(const IntPoint& point, bool isStartedTextSelectionFromOutside)
 {
+    // text selection should be ignored when longtap on handle from osp
+    if (!isEnabled() && isTextSelectionHandleDowned())
+        return false;
+
     setIsTextSelectionMode(false);
 
     IntPoint contentsPoint = m_viewImpl->transformFromScene().mapPoint(point);
-    bool result = m_page->selectClosestWord(contentsPoint, isStartedTextSelectionFromOutside);
+    bool result = m_viewImpl->page()->selectClosestWord(contentsPoint, isStartedTextSelectionFromOutside);
     if (!result)
         return false;
 
@@ -477,21 +481,39 @@ bool TextSelection::textSelectionDown(const IntPoint& point, bool isStartedTextS
 
 void TextSelection::textSelectionMove(const IntPoint& point, bool isStartedTextSelectionFromOutside)
 {
+    // text selection should be ignored when longtap on handle from osp
+    if (!isEnabled() && isTextSelectionHandleDowned())
+        return;
+
     if (!isTextSelectionMode()) {
         stopMoveAnimator();
         return;
     }
 
-    WebCore::IntPoint viewPoint = m_viewImpl->transformFromScene().mapPoint(point);
-    EditorState editorState = m_page->editorState();
+    WebCore::IntPoint viewPoint;
+    EditorState editorState = m_viewImpl->page()->editorState();
     if (editorState.isContentEditable) {
         IntRect mapRect = m_viewImpl->transformToScene().mapRect(editorState.editorRect);
-        if(mapRect.contains(point)) {
-            m_page->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
-            updateMagnifier(point);
+        IntPoint updatedPoint = point;
+        if ((point.y() < mapRect.y()) || (point.y() > ((mapRect.y()) + (mapRect.height()))))
+            updatedPoint.setY((mapRect.y()) + ((mapRect.height())/2) );
+
+        if (point.x() < mapRect.x()) {
+            updatedPoint.setX(mapRect.x());
+            if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionBackward))
+                updateMagnifier(updatedPoint);
+        } else if (point.x() > ((mapRect.x()) + (mapRect.width()))) {
+            updatedPoint.setX((mapRect.x()) + (mapRect.width()));
+            if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionForward))
+                updateMagnifier(updatedPoint);
+        } else {
+            viewPoint = m_viewImpl->transformFromScene().mapPoint(updatedPoint);
+            m_viewImpl->page()->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
+            updateMagnifier(updatedPoint);
         }
     } else {
-        m_page->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
+        viewPoint = m_viewImpl->transformFromScene().mapPoint(point);
+        m_viewImpl->page()->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
         updateMagnifier(point);
     }
     showMagnifier();
@@ -499,6 +521,10 @@ void TextSelection::textSelectionMove(const IntPoint& point, bool isStartedTextS
 
 void TextSelection::textSelectionUp(const IntPoint& point, bool isStartedTextSelectionFromOutside)
 {
+    // text selection should be ignored when longtap on handle from osp
+    if (!isEnabled() && isTextSelectionHandleDowned())
+        return;
+
     stopMoveAnimator();
 
     if (!isTextSelectionMode() || !isTextSelectionDowned())
@@ -507,7 +533,7 @@ void TextSelection::textSelectionUp(const IntPoint& point, bool isStartedTextSel
     setIsTextSelectionDowned(false);
     hideMagnifier();
 
-    EditorState editorState = m_page->editorState();
+    EditorState editorState = m_viewImpl->page()->editorState();
     if (editorState.selectionIsRange || editorState.isContentEditable) {
         if (editorState.selectionIsRange)
             updateHandlers();
@@ -517,7 +543,7 @@ void TextSelection::textSelectionUp(const IntPoint& point, bool isStartedTextSel
         setIsTextSelectionMode(false);
 
 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
-    m_page->getTextStyleStateForSelection();
+    m_viewImpl->page()->getTextStyleStateForSelection();
 #endif
 }
 
@@ -543,10 +569,6 @@ void TextSelection::textSelectionHandleDown(const IntPoint& position)
         if (selectedHandle->isMouseDowned())
             return;
     }
-
-    EditorState editorState = m_page->editorState();
-    if (editorState.isContentEditable)
-        setIsTextSelectionMode(false);
 }
 
 void TextSelection::textSelectionHandleMove(const IntPoint& position)
@@ -568,12 +590,45 @@ void TextSelection::textSelectionHandleUp()
 
 bool TextSelection::isEnabled()
 {
-    return ewk_settings_text_selection_enabled_get(ewk_view_settings_get(m_object));
+    return ewk_settings_text_selection_enabled_get(ewk_view_settings_get(m_viewImpl->view()));
 }
 
 bool TextSelection::isAutomaticClearEnabled()
 {
-    return ewk_settings_clear_text_selection_automatically_get(ewk_view_settings_get(m_object));
+    return ewk_settings_clear_text_selection_automatically_get(ewk_view_settings_get(m_viewImpl->view()));
+}
+
+void TextSelection::requestToShow()
+{
+    if (m_showTimer)
+        ecore_timer_del(m_showTimer);
+    m_showTimer = ecore_timer_loop_add((double)200.0/1000.0, showTimerCallback, this);
+}
+
+Eina_Bool TextSelection::showTimerCallback(void* data)
+{
+    TextSelection* textSelection = static_cast<TextSelection*>(data);
+    textSelection->showHandlesAndContextMenu();
+
+    return ECORE_CALLBACK_RENEW;
+}
+
+void TextSelection::showHandlesAndContextMenu()
+{
+    WebCore::IntRect leftRect, rightRect;
+    if (m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect)) {
+        if ((leftRect == m_lastLeftHandleRect) && (rightRect == m_lastRightHandleRect)) {
+            if (m_showTimer) {
+                ecore_timer_del(m_showTimer);
+                m_showTimer = 0;
+            }
+
+            updateHandlesAndContextMenu(true);
+        }
+
+        m_lastLeftHandleRect = leftRect;
+        m_lastRightHandleRect = rightRect;
+    }
 }
 
 } // namespace WebKit