Keep Selections within Shadow DOM boundaries
authormegan_gardner@apple.com <megan_gardner@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Jul 2018 19:46:23 +0000 (19:46 +0000)
committermegan_gardner@apple.com <megan_gardner@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Jul 2018 19:46:23 +0000 (19:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187556
<rdar://problem/41664567>

Reviewed by Ryosuke Niwa.

Source/WebCore:

Expose needed functionality to WebKit to help with determing editing and shadow dom boundries.

Only exposing functionality to WebKit.

* dom/TreeScope.h:
* editing/Editing.h:
* editing/VisibleSelection.cpp:
(WebCore::VisibleSelection::adjustPositionForEnd const):
(WebCore::VisibleSelection::adjustPositionForStart const):
(WebCore::adjustPositionForEnd): Deleted.
(WebCore::adjustPositionForStart): Deleted.
* editing/VisibleSelection.h:

Source/WebKit:

Update rangeForPosition to take into account both editing and shadow DOM boundries.

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::rangeForPoint):
(WebKit::WebPage::updateSelectionWithTouches):
(WebKit::rangeForPosition): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@233778 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/dom/TreeScope.h
Source/WebCore/editing/Editing.h
Source/WebCore/editing/VisibleSelection.cpp
Source/WebCore/editing/VisibleSelection.h
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

index 7f45388..237493b 100644 (file)
@@ -1,3 +1,24 @@
+2018-07-12  Megan Gardner  <megan_gardner@apple.com>
+
+        Keep Selections within Shadow DOM boundaries
+        https://bugs.webkit.org/show_bug.cgi?id=187556
+        <rdar://problem/41664567>
+
+        Reviewed by Ryosuke Niwa.
+
+        Expose needed functionality to WebKit to help with determing editing and shadow dom boundries.
+
+        Only exposing functionality to WebKit.
+
+        * dom/TreeScope.h:
+        * editing/Editing.h:
+        * editing/VisibleSelection.cpp:
+        (WebCore::VisibleSelection::adjustPositionForEnd const):
+        (WebCore::VisibleSelection::adjustPositionForStart const):
+        (WebCore::adjustPositionForEnd): Deleted.
+        (WebCore::adjustPositionForStart): Deleted.
+        * editing/VisibleSelection.h:
+        
 2018-07-12  Sihui Liu  <sihui_liu@apple.com>
 
         IndexedDB: database file of subframe cannot be removed
index 14de123..b164bd9 100644 (file)
@@ -76,7 +76,7 @@ public:
     // https://dom.spec.whatwg.org/#retarget
     Node& retargetToScope(Node&) const;
 
-    Node* ancestorNodeInThisScope(Node*) const;
+    WEBCORE_EXPORT Node* ancestorNodeInThisScope(Node*) const;
     WEBCORE_EXPORT Element* ancestorElementInThisScope(Element*) const;
 
     void addImageMap(HTMLMapElement&);
index 2b372c0..ade4310 100644 (file)
@@ -121,7 +121,7 @@ Position lastPositionInOrAfterNode(Node*);
 Position firstEditablePositionAfterPositionInRoot(const Position&, ContainerNode* root);
 Position lastEditablePositionBeforePositionInRoot(const Position&, ContainerNode* root);
 
-int comparePositions(const Position&, const Position&);
+WEBCORE_EXPORT int comparePositions(const Position&, const Position&);
 
 WEBCORE_EXPORT bool isEditablePosition(const Position&, EditableType = ContentIsEditable);
 bool isRichlyEditablePosition(const Position&);
index 18650ab..3d9bfba 100644 (file)
@@ -468,7 +468,7 @@ void VisibleSelection::setWithoutValidation(const Position& base, const Position
     m_selectionType = base == extent ? CaretSelection : RangeSelection;
 }
 
-static Position adjustPositionForEnd(const Position& currentPosition, Node* startContainerNode)
+Position VisibleSelection::adjustPositionForEnd(const Position& currentPosition, Node* startContainerNode)
 {
     TreeScope& treeScope = startContainerNode->treeScope();
 
@@ -486,7 +486,7 @@ static Position adjustPositionForEnd(const Position& currentPosition, Node* star
     return Position();
 }
 
-static Position adjustPositionForStart(const Position& currentPosition, Node* endContainerNode)
+Position VisibleSelection::adjustPositionForStart(const Position& currentPosition, Node* endContainerNode)
 {
     TreeScope& treeScope = endContainerNode->treeScope();
 
index 3015e6d..a943da8 100644 (file)
@@ -105,6 +105,9 @@ public:
     Node* nonBoundaryShadowTreeRootNode() const;
 
     WEBCORE_EXPORT bool isInPasswordField() const;
+    
+    WEBCORE_EXPORT static Position adjustPositionForEnd(const Position& currentPosition, Node* startContainerNode);
+    WEBCORE_EXPORT static Position adjustPositionForStart(const Position& currentPosition, Node* startContainerNode);
 
 #if ENABLE(TREE_DEBUGGING)
     void debugPosition() const;
index cd8c32f..e160561 100644 (file)
@@ -1,3 +1,18 @@
+2018-07-12  Megan Gardner  <megan_gardner@apple.com>
+
+        Keep Selections within Shadow DOM boundaries
+        https://bugs.webkit.org/show_bug.cgi?id=187556
+        <rdar://problem/41664567>
+
+        Reviewed by Ryosuke Niwa.
+
+        Update rangeForPosition to take into account both editing and shadow DOM boundries.
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::rangeForPoint):
+        (WebKit::WebPage::updateSelectionWithTouches):
+        (WebKit::rangeForPosition): Deleted.
+        
 2018-07-12  Jer Noble  <jer.noble@apple.com>
 
         REGRESSION (r230163): Videos cannot be seen full screen in Complete Anatomy app
index aac8c5e..d3e30b7 100644 (file)
@@ -1215,31 +1215,36 @@ void WebPage::selectWithGesture(const IntPoint& point, uint32_t granularity, uin
     send(Messages::WebPageProxy::GestureCallback(point, gestureType, gestureState, static_cast<uint32_t>(flags), callbackID));
 }
 
-static RefPtr<Range> rangeForPosition(Frame* frame, const VisiblePosition& position, bool baseIsStart)
+static RefPtr<Range> rangeForPoint(Frame* frame, const IntPoint& point, bool baseIsStart)
 {
+    IntPoint pointInDocument = frame->view()->rootViewToContents(point);
+    Position result = frame->visiblePositionForPoint(pointInDocument).deepEquivalent();
     RefPtr<Range> range;
-    VisiblePosition result = position;
-
+    
+    HitTestResult hitTest = frame->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent);
+    if (hitTest.targetNode())
+        result = frame->eventHandler().selectionExtentRespectingEditingBoundary(frame->selection().selection(), hitTest.localPoint(), hitTest.targetNode()).deepEquivalent();
+    
+    VisibleSelection existingSelection = frame->selection().selection();
+    Position selectionStart = existingSelection.visibleStart().deepEquivalent();
+    Position selectionEnd = existingSelection.visibleEnd().deepEquivalent();
+    
     if (baseIsStart) {
-        VisiblePosition selectionStart = frame->selection().selection().visibleStart();
-        bool wouldFlip = position <= selectionStart;
-
-        if (wouldFlip)
+        if (comparePositions(result, selectionStart) <= 0)
             result = selectionStart.next();
-
+        else if (&selectionStart.anchorNode()->treeScope() != &hitTest.targetNode()->treeScope())
+            result = VisibleSelection::adjustPositionForEnd(result, selectionStart.containerNode());
         if (result.isNotNull())
             range = Range::create(*frame->document(), selectionStart, result);
     } else {
-        VisiblePosition selectionEnd = frame->selection().selection().visibleEnd();
-        bool wouldFlip = position >= selectionEnd;
-
-        if (wouldFlip)
+        if (comparePositions(selectionEnd, result) <= 0)
             result = selectionEnd.previous();
-
+        else if (&hitTest.targetNode()->treeScope() != &selectionEnd.anchorNode()->treeScope())
+            result = VisibleSelection::adjustPositionForStart(result, selectionEnd.containerNode());
         if (result.isNotNull())
             range = Range::create(*frame->document(), result, selectionEnd);
     }
-
+    
     return range;
 }
 
@@ -1324,7 +1329,7 @@ void WebPage::updateSelectionWithTouches(const IntPoint& point, uint32_t touches
             if (result.isNotNull())
                 range = Range::create(*frame.document(), result, result);
         } else
-            range = rangeForPosition(&frame, position, baseIsStart);
+            range = rangeForPoint(&frame, point, baseIsStart);
         break;
 
     case SelectionTouch::EndedMovingForward:
@@ -1336,10 +1341,7 @@ void WebPage::updateSelectionWithTouches(const IntPoint& point, uint32_t touches
         break;
 
     case SelectionTouch::Moved:
-        HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::AllowChildFrameContent);
-        if (result.targetNode())
-            position = m_page->mainFrame().eventHandler().selectionExtentRespectingEditingBoundary(frame.selection().selection(), result.localPoint(), result.targetNode());
-        range = rangeForPosition(&frame, position, baseIsStart);
+        range = rangeForPoint(&frame, point, baseIsStart);
         break;
     }
     if (range)