Implement the work of longtap on image in accordance with Browser UX.
authorYuni Jeong <yhnet.jung@samsung.com>
Fri, 22 Mar 2013 08:16:36 +0000 (17:16 +0900)
committerGerrit Code Review <gerrit2@kim11>
Thu, 28 Mar 2013 07:57:50 +0000 (16:57 +0900)
[Title] Implement the work of longTap on image in accordance with Browser UX.
[Issue#] P130114-4165
[Problem] The work of longTap on image differs with Browser UX.
[Cause] Not implemented.
[Solution] Implement the work of longTap on image in accordance with Browser UX.

Change-Id: I8d6d9e47abf2d6b35f5c436d35b6f7571218fdbd

Source/WebCore/dom/Range.cpp
Source/WebCore/dom/Range.h
Source/WebCore/page/ContextMenuController.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/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp

index 3a9fb48..8d3961e 100644 (file)
 #include <wtf/text/CString.h>
 #include <wtf/text/StringBuilder.h>
 
+#if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
+#include "RenderImage.h"
+#endif
+
 namespace WebCore {
 
 using namespace std;
@@ -1625,6 +1629,49 @@ void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight, RangeInFi
         *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixedPosition : NotFixedPosition);
 }
 
+#if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
+void Range::boundingBoxEx(Vector<IntRect>& rects, bool useSelectionHeight, RangeInFixedPosition* inFixed) const
+{
+    Node* startContainer = m_start.container();
+    Node* endContainer = m_end.container();
+
+    if (!startContainer || !endContainer) {
+        if (inFixed)
+            *inFixed = NotFixedPosition;
+        return;
+    }
+
+    bool allFixed = true;
+    bool someFixed = false;
+
+    Node* stopNode = pastLastNode();
+    for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
+        RenderObject* r = node->renderer();
+        if (r && r->isText()) {
+            RenderText* renderText = toRenderText(r);
+            int startOffset = node == startContainer ? m_start.offset() : 0;
+            int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max();
+            bool isFixed = false;
+            renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSelectionHeight, &isFixed);
+            allFixed &= isFixed;
+            someFixed |= isFixed;
+        } else if (r && r->isImage()) {
+            RenderImage* renderImage= toRenderImage(r);
+            int startOffset = node == startContainer ? m_start.offset() : 0;
+            int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max();
+            bool isFixed = false;
+            IntRect r = renderImage->absoluteBoundingBoxRect();
+            rects.append(r);
+            allFixed &= isFixed;
+            someFixed |= isFixed;
+        }
+    }
+
+    if (inFixed)
+        *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixedPosition : NotFixedPosition);
+}
+#endif
+
 void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight, RangeInFixedPosition* inFixed) const
 {
     Node* startContainer = m_start.container();
index b84bd61..044da33 100644 (file)
@@ -122,6 +122,9 @@ public:
     
     // Not transform-friendly
     void textRects(Vector<IntRect>&, bool useSelectionHeight = false, RangeInFixedPosition* = 0) const;
+#if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
+    void boundingBoxEx(Vector<IntRect>&, bool useSelectionHeight = false, RangeInFixedPosition* = 0) const;
+#endif
     // Transform-friendly
     void textQuads(Vector<FloatQuad>&, bool useSelectionHeight = false, RangeInFixedPosition* = 0) const;
     void getBorderAndTextQuads(Vector<FloatQuad>&) const;
index 5159d1b..d24eeb4 100755 (executable)
@@ -907,7 +907,7 @@ void ContextMenuController::populate()
         }
 
 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_TEXT_SELECTION_MODE)
-        if (!linkURL.isEmpty() && imageURL.isEmpty() && mediaURL.isEmpty())
+        if ((!linkURL.isEmpty() || !imageURL.isEmpty()) && mediaURL.isEmpty())
             appendItem(TextSelectionModeItem, m_contextMenu.get());
 #endif
 
index fc49015..a5c2453 100755 (executable)
@@ -696,7 +696,7 @@ static Eina_Bool _ewk_view_smart_gesture_start(Ewk_View_Smart_Data* smartData, c
             if (priv->exceedTouchMoveThreshold)
                 priv->focusRing->hide();
         } else {
-            if (!event->type == EWK_GESTURE_LONG_PRESS) {
+            if (event->type != EWK_GESTURE_LONG_PRESS) {
 #if ENABLE(TIZEN_CONTEXT_MENU_WEBKIT_2)
                 if (!priv->pageClient->isContextMenuVisible())
 #endif
@@ -728,6 +728,10 @@ static Eina_Bool _ewk_view_smart_gesture_start(Ewk_View_Smart_Data* smartData, c
         // 1. Check to start dragging.
         if (hitTestResultData.isDragSupport) {
             priv->pageClient->setDragPoint(scenePoint);
+#if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
+            if (priv->focusRing)
+                priv->focusRing->show(IntRect(), true);
+#endif
             priv->gestureClient->showContextMenu(scenePoint);
             break;
         }
@@ -736,6 +740,10 @@ static Eina_Bool _ewk_view_smart_gesture_start(Ewk_View_Smart_Data* smartData, c
         if (!hitTestResultData.absoluteImageURL.isEmpty()
             || !hitTestResultData.absoluteLinkURL.isEmpty()
             || !hitTestResultData.absoluteMediaURL.isEmpty()) {
+#if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
+            if (priv->focusRing)
+                priv->focusRing->show(IntRect(), true);
+#endif
             priv->gestureClient->showContextMenu(scenePoint);
             break;
         }
@@ -793,9 +801,9 @@ static Eina_Bool _ewk_view_smart_gesture_end(Ewk_View_Smart_Data* smartData, con
 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
     if (priv->focusRing) {
 #if ENABLE(TIZEN_CONTEXT_MENU_WEBKIT_2)
-            if (!priv->pageClient->isContextMenuVisible())
+        if (!priv->pageClient->isContextMenuVisible())
 #endif
-                priv->focusRing->hide();
+            priv->focusRing->hide();
     }
 #endif
 
index 10e4596..7a5b8ef 100755 (executable)
@@ -51,7 +51,7 @@ FocusRing::~FocusRing()
 
 Eina_Bool FocusRing::showTimerCallback(void* data)
 {
-    static_cast<FocusRing*>(data)->internalShow(true, IntRect());
+    static_cast<FocusRing*>(data)->show(IntRect());
     return ECORE_CALLBACK_CANCEL;
 }
 
@@ -80,14 +80,9 @@ void FocusRing::requestToShow(const IntPoint& position)
     m_showTimer = ecore_timer_add((double)s_showTimerTime/1000.0, showTimerCallback, this);
 }
 
-void FocusRing::show(const WebCore::IntRect& rect)
+void FocusRing::show(const IntRect& rect, const bool includeOnlyImage)
 {
-    internalShow(false, rect);
-}
-
-void FocusRing::internalShow(bool needHitTest, const IntRect& rect)
-{
-    if (needHitTest)
+    if (rect.isEmpty())
         m_showTimer = 0;
 
     PageClientImpl* pageClientImpl = ewkViewGetPageClient(m_viewWidget);
@@ -96,13 +91,18 @@ void FocusRing::internalShow(bool needHitTest, const IntRect& rect)
     IntRect focusRingRect(rect);
     Color focusRingColor;
 
-    if (needHitTest) {
+    if (rect.isEmpty()) {
 #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
         IntPoint contentsPosition = m_viewImpl->transformFromScene().mapPoint(m_position);
         WebHitTestResult::Data hitTestResultData = pageClientImpl->page()->hitTestResultAtPoint(contentsPosition);
         if (hitTestResultData.focusedRect.isEmpty())
             return;
 
+        if (!hitTestResultData.absoluteImageURL.isEmpty() && hitTestResultData.absoluteLinkURL.isEmpty()) {
+            if (!includeOnlyImage)
+                return;
+        }
+
         focusRingRect = hitTestResultData.focusedRect;
         focusRingColor = hitTestResultData.focusedColor;
 #endif // #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
@@ -201,7 +201,7 @@ void FocusRing::updateScrollAndScale(const WebCore::IntPoint& previousScrollPosi
     rect.moveBy(previousScrollPosition);
     rect.scale(1 / previousScale);
 
-    internalShow(false, enclosingIntRect(rect));
+    show(enclosingIntRect(rect));
 #else
     UNUSED_PARAM(previousScrollPosition);
     UNUSED_PARAM(previousScale);
index 5d84466..dda8e27 100755 (executable)
@@ -42,7 +42,7 @@ public:
 
     void requestToShow(const WebCore::IntPoint&);
 
-    void show(const WebCore::IntRect&);
+    void show(const WebCore::IntRect&, const bool includeOnlyImage = false);
     void hide(bool = true);
 
     void updateScrollAndScale(const WebCore::IntPoint&, float);
index 1cd2233..1a4e445 100755 (executable)
 #include "DataObjectTizen.h"
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_TEXT_SELECTION_MODE)
+#include "HTMLImageElement.h"
+#endif
+
 using namespace JSC;
 using namespace WebCore;
 using namespace std;
@@ -1159,38 +1163,39 @@ void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
 void WebPage::selectLink(WebCore::IntPoint positionForSelection, bool& result)
 {
     result = false;
-
     Frame* frame = m_page->focusController()->focusedOrMainFrame();
     if (!frame)
         return;
+
     FrameView* frameView = frame->view();
     if (!frameView)
         return;
 
     HitTestResult hitTestResult = frame->eventHandler()->hitTestResultAtPoint(frameView->windowToContents(positionForSelection), false);
 
-    Element* URLElement = hitTestResult.URLElement();
-    if (!URLElement)
-        return;
-
     RefPtr<Range> range;
-    for (Node* childNode = URLElement->firstChild(); childNode; childNode = childNode->traverseNextNode(URLElement)) {
-        if (childNode->isTextNode()) {
-            if (!range)
-                range = VisibleSelection::selectionFromContentsOfNode(childNode).toNormalizedRange();
-            else {
-                RefPtr<Range> extendedRange = VisibleSelection::selectionFromContentsOfNode(childNode).toNormalizedRange();
-                range->setEnd(childNode, extendedRange->endOffset());
+    Element* URLElement = hitTestResult.URLElement();
+    if (URLElement) {
+        for (Node* childNode = URLElement->firstChild(); childNode; childNode = childNode->traverseNextNode(URLElement)) {
+            RenderObject* r = childNode->renderer();
+            if (r && (r->isText() || r->isImage())) {
+                if (!range)
+                    range = VisibleSelection::selectionFromContentsOfNode(childNode).toNormalizedRange();
+                else if (!hitTestResult.image()) {
+                    RefPtr<Range> extendedRange = VisibleSelection::selectionFromContentsOfNode(childNode).toNormalizedRange();
+                    range->setEnd(childNode, extendedRange->endOffset());
+                }
             }
         }
-    }
-
-    if (!range)
-        range = VisibleSelection::selectionFromContentsOfNode(URLElement).toNormalizedRange();
+        if(!range)
+            range = VisibleSelection::selectionFromContentsOfNode(URLElement).toNormalizedRange();
+    } else
+        range = VisibleSelection::selectionFromContentsOfNode(hitTestResult.innerNonSharedNode()).toNormalizedRange();
 
     WebCore::FrameSelection* frameSelection = frame->selection();
     if (!frameSelection)
         return;
+
     EAffinity affinity = frameSelection->affinity();
     frameSelection->setSelectedRange(range.get(), affinity, true);
 
index 68437f5..e6afc26 100755 (executable)
@@ -840,8 +840,12 @@ static IntRect getFocusedRect(HitTestResult hitTestResult, Page* page)
         focusableNode = focusableNode->parentNode();
     }
 
-    if (!isFocusRingDrawable)
+    if (!isFocusRingDrawable) {
+        if (node->hasTagName(HTMLNames::imgTag))
+            return getNodeRect(node, node, !hitTestResult.absoluteImageURL().isEmpty());
+
         return IntRect();
+    }
 
     return getNodeRect(node, focusableNode, !hitTestResult.absoluteImageURL().isEmpty());
 }
@@ -1238,16 +1242,16 @@ void WebPage::selectClosestWord(const IntPoint& point, bool isStartedTextSelecti
     result = true;
 }
 
-void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result)
+void WebPage::setLeftSelection(const IntPoint& point, bool& result)
 {
     result = false;
 
     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
-    WebCore::FrameSelection* frameSelection = focusedFrame->selection();
+    FrameSelection* frameSelection = focusedFrame->selection();
     if (!frameSelection->isRange())
         return;
 
-    WebCore::Node* selectionEndNode = frameSelection->end().deprecatedNode();
+    Node* selectionEndNode = frameSelection->end().deprecatedNode();
     if (!selectionEndNode || !selectionEndNode->renderer())
         return;
 
@@ -1255,8 +1259,8 @@ void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result)
     if (!frameView)
         return;
 
-    WebCore::IntPoint pos = frameView->windowToContents(point);
-    WebCore::IntRect leftRect, rightRect;
+    IntPoint pos = frameView->windowToContents(point);
+    IntRect leftRect, rightRect;
     getSelectionHandlers(leftRect, rightRect);
     if ((rightRect.y() + rightRect.height()) < pos.y())
         pos.setY(rightRect.y() + (rightRect.height()/2));
@@ -1264,7 +1268,7 @@ void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result)
     if (selectionEndNode->rendererIsEditable() && !selectionEndNode->rendererIsRichlyEditable()) {
         const int boundariesWidth = 2;
 
-        WebCore::IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
+        IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
         // here we cheat input field that we actually are just inside of if
         if (pos.y() < rect.y() + boundariesWidth)
             pos.setY(rect.y() + boundariesWidth);
@@ -1272,21 +1276,21 @@ void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result)
             pos.setY(rect.maxY() - boundariesWidth - 1);
     }
 
-    OwnPtr<WebCore::VisiblePosition> position = adoptPtr(new WebCore::VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
-    WebCore::Position extent = frameSelection->extent();
+    OwnPtr<VisiblePosition> position = adoptPtr(new VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
+    Position extent = frameSelection->extent();
 
-    WebCore::Node* newSelectionStartNode = position->deepEquivalent().deprecatedNode();
+    Node* newSelectionStartNode = position->deepEquivalent().deprecatedNode();
 
     // both start and end nodes should be in the same area type: both should be editable or both should be not editable
     // Check if the new position is before the extent's position
     if (newSelectionStartNode
         && selectionEndNode->isContentEditable() == newSelectionStartNode->isContentEditable()
-        && WebCore::comparePositions(position->deepEquivalent(), extent) < 0) {
+        && comparePositions(position->deepEquivalent(), extent) < 0) {
         // Change the 'base' and 'extent' positions to 'start' and 'end' positions.
         // We do it, because without this, the other modification of the selection
         // would destroy the 'start' and/or 'end' positions and set them to
         // the 'base'/'extent' positions accordingly
-        WebCore::VisibleSelection sel(frameSelection->start(), frameSelection->end());
+        VisibleSelection sel(frameSelection->start(), frameSelection->end());
         frameSelection->setSelection(sel);
 
         bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling();
@@ -1303,17 +1307,17 @@ void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result)
 }
 
 
-void WebPage::setRightSelection(const WebCore::IntPoint& point, bool& result)
+void WebPage::setRightSelection(const IntPoint& point, bool& result)
 {
     result = false;
 
     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
-    WebCore::FrameSelection* frameSelection = focusedFrame->selection();
+    FrameSelection* frameSelection = focusedFrame->selection();
 
     if (!frameSelection->isRange())
         return;
 
-    WebCore::Node* selectionStartNode = frameSelection->start().deprecatedNode();
+    Node* selectionStartNode = frameSelection->start().deprecatedNode();
     if (!selectionStartNode || !selectionStartNode->renderer())
         return;
 
@@ -1321,11 +1325,11 @@ void WebPage::setRightSelection(const WebCore::IntPoint& point, bool& result)
     if (!frameView)
         return;
 
-    WebCore::IntPoint pos = frameView->windowToContents(point);
+    IntPoint pos = frameView->windowToContents(point);
     if (selectionStartNode->rendererIsEditable() && !selectionStartNode->rendererIsRichlyEditable()) {
         const int boundariesWidth = 2;
 
-        WebCore::IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
+        IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
         // here we cheat input field that we actually are just inside of if
         if (pos.y() < rect.y() + boundariesWidth)
             pos.setY(rect.y() + boundariesWidth);
@@ -1333,22 +1337,22 @@ void WebPage::setRightSelection(const WebCore::IntPoint& point, bool& result)
             pos.setY(rect.maxY() - boundariesWidth - 1);
     }
 
-    OwnPtr<WebCore::VisiblePosition> position = adoptPtr(new WebCore::VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
-    WebCore::Position base = frameSelection->base();
+    OwnPtr<VisiblePosition> position = adoptPtr(new VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
+    Position base = frameSelection->base();
 
-    WebCore::Node* newSelectionEndNode = position->deepEquivalent().deprecatedNode();
+    Node* newSelectionEndNode = position->deepEquivalent().deprecatedNode();
 
     // both start and end nodes should be in the same area type: both should be editable or both should be not editable
     // Check if the new position is after the base's position
     if (newSelectionEndNode
         && selectionStartNode->isContentEditable() == newSelectionEndNode->isContentEditable()
-        && WebCore::comparePositions(position->deepEquivalent(), base) > 0) {
+        && comparePositions(position->deepEquivalent(), base) > 0) {
         // Change the 'base' and 'extent' positions to 'start' and 'end' positions.
         // We do it, because without this, the other modifications of the selection
         // would destroy the 'start' and/or 'end' positions and set them to
         // the 'base'/'extent' positions accordingly
 
-        WebCore::VisibleSelection sel(frameSelection->start(), frameSelection->end());
+        VisibleSelection sel(frameSelection->start(), frameSelection->end());
         frameSelection->setSelection(sel);
 
         bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling();
@@ -1369,14 +1373,25 @@ void WebPage::getSelectionHandlers(IntRect& leftRect, IntRect& rightRect)
         return;
 
     // Is this check necessary? Leaving it for safety.
-    WebCore::RenderView* root = focusedFrame->contentRenderer();
+    RenderView* root = focusedFrame->contentRenderer();
     if (!root)
         return;
 
-    RefPtr<WebCore::Range> selectedRange = focusedFrame->selection()->toNormalizedRange();
+    RefPtr<Range> selectedRange = focusedFrame->selection()->toNormalizedRange();
 
-    Vector<WebCore::IntRect> rects;
-    selectedRange->textRects(rects, true);
+    Vector<IntRect> rects, tempRects;
+    selectedRange->boundingBoxEx(tempRects, true);
+
+    IntRect boundsRect =  enclosingIntRect(focusedFrame->selection()->bounds());
+    for (size_t i = 0; i < tempRects.size(); i++) {
+        if (boundsRect.contains(tempRects[i]))
+            rects.append(tempRects[i]);
+        else {
+            tempRects[i].intersect(boundsRect);
+            if (!tempRects[i].isEmpty())
+                rects.append(tempRects[i]);
+        }
+    }
 
     unsigned size = rects.size();
     if (size > 0) {
@@ -1388,7 +1403,7 @@ void WebPage::getSelectionHandlers(IntRect& leftRect, IntRect& rightRect)
         if (size == 1) {
             Element* selectionRoot = focusedFrame->selection()->rootEditableElement();
             if (selectionRoot) {
-                WebCore::IntRect editorRect = focusedFrame->view()->contentsToWindow(selectionRoot->getPixelSnappedRect());
+                IntRect editorRect = focusedFrame->view()->contentsToWindow(selectionRoot->getPixelSnappedRect());
 
 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
                 if (m_editorState.editorRect != editorRect) {
@@ -1435,13 +1450,13 @@ void WebPage::selectionRangeClear(bool& result)
     result = false;
 
     Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
-    WebCore::FrameSelection* frameSelection = focusedFrame->selection();
+    FrameSelection* frameSelection = focusedFrame->selection();
     if (frameSelection && frameSelection->isRange() && frameSelection->isContentEditable()) {
-        WebCore::VisiblePosition visiblePos(frameSelection->extent());
+        VisiblePosition visiblePos(frameSelection->extent());
         if (visiblePos.isNull())
             return;
-        WebCore::VisibleSelection newSelection = WebCore::VisibleSelection(visiblePos);
-        frameSelection->setSelection(newSelection, WebCore::CharacterGranularity);
+        VisibleSelection newSelection = VisibleSelection(visiblePos);
+        frameSelection->setSelection(newSelection, CharacterGranularity);
         frameSelection->setCaretBlinkingSuspended(false);
     } else
         selectionClearAllSelection(m_page->mainFrame());
@@ -1454,7 +1469,7 @@ void WebPage::selectionClearAllSelection(Frame* frame)
     if (!frame)
         return;
 
-    WebCore::FrameSelection* frameSelection = frame->selection();
+    FrameSelection* frameSelection = frame->selection();
     if (frameSelection)
         frameSelection->clear();
 
@@ -1467,7 +1482,6 @@ void WebPage::selectionClearAllSelection(Frame* frame)
     } else if (frame->tree()->nextSibling())
         selectionClearAllSelection(frame->tree()->nextSibling());
 }
-
 #endif
 
 #if ENABLE(TIZEN_LINK_MAGNIFIER)