Changeset 280872 in webkit


Ignore:
Timestamp:
Aug 10, 2021 4:51:41 PM (11 months ago)
Author:
Wenson Hsieh
Message:

[Live Text] Unable to start drag on image when the first piece of text inside the image is selected
https://bugs.webkit.org/show_bug.cgi?id=228967
rdar://80471465

Reviewed by Tim Horton.

When selecting text inside an image element using Live Text, if the text selection contains the very first
character (in DOM order) that appears in the image element's shadow root, the user will be unable to start an
image drag on the same image by clicking another part of the image that does not contain Live Text. This happens
because DragController::startDrag to handle the drag as a selection drag rather than an image drag, which (in
turn) happens because DragController::draggableElement computes a drag source type of
DragSourceAction::Selection.

This occurs because FrameSelection::contains(const LayoutPoint&) returns true for any point inside the
shadow root of an image element with Live Text that does NOT hit-test to a text node, because we end up hit-
testing to the image overlay container div as our innerNode, which means that the DOM position for the given
point is going to be at the first position inside the image overlay container. Since this canonicalizes to the
beginning of the first text node (in DOM order) inside the image overlay, if that first text node happens to be
selected, we'll end up believing that the layout point (which is not over any text inside the image) is inside
the selection.

To avoid this, we make a minor adjustment to the logic in FrameSelection::contains, so that we handle text
inside image overlays by mapping the selected text range to absolute quads, and then checking whether the given
point (in absolute coordinates) is contained in any of those quads.

While we could theoretically use this approach for all selections, it's both more expensive than a hit-test and
might result in compatibility issues, so we just limit it to the case where we know (a-prior) that all
selectable text is arbitrarily positioned using transforms.

This change fixes an API test that currently fails on macOS: DragAndDropTests.DragElementWithImageOverlay

  • editing/FrameSelection.cpp:

(WebCore::FrameSelection::contains const):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r280870 r280872  
     12021-08-10  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Live Text] Unable to start drag on image when the first piece of text inside the image is selected
     4        https://bugs.webkit.org/show_bug.cgi?id=228967
     5        rdar://80471465
     6
     7        Reviewed by Tim Horton.
     8
     9        When selecting text inside an image element using Live Text, if the text selection contains the very first
     10        character (in DOM order) that appears in the image element's shadow root, the user will be unable to start an
     11        image drag on the same image by clicking another part of the image that does not contain Live Text. This happens
     12        because `DragController::startDrag` to handle the drag as a selection drag rather than an image drag, which (in
     13        turn) happens because `DragController::draggableElement` computes a drag source type of
     14        `DragSourceAction::Selection`.
     15
     16        This occurs because `FrameSelection::contains(const LayoutPoint&)` returns `true` for any point inside the
     17        shadow root of an image element with Live Text that does NOT hit-test to a text node, because we end up hit-
     18        testing to the image overlay container `div` as our `innerNode`, which means that the DOM position for the given
     19        point is going to be at the first position inside the image overlay container. Since this canonicalizes to the
     20        beginning of the first text node (in DOM order) inside the image overlay, if that first text node happens to be
     21        selected, we'll end up believing that the layout point (which is not over any text inside the image) is inside
     22        the selection.
     23
     24        To avoid this, we make a minor adjustment to the logic in `FrameSelection::contains`, so that we handle text
     25        inside image overlays by mapping the selected text range to absolute quads, and then checking whether the given
     26        point (in absolute coordinates) is contained in any of those quads.
     27
     28        While we could theoretically use this approach for all selections, it's both more expensive than a hit-test and
     29        might result in compatibility issues, so we just limit it to the case where we know (a-prior) that all
     30        selectable text is arbitrarily positioned using transforms.
     31
     32        This change fixes an API test that currently fails on macOS: DragAndDropTests.DragElementWithImageOverlay
     33
     34        * editing/FrameSelection.cpp:
     35        (WebCore::FrameSelection::contains const):
     36
    1372021-08-10  Chris Dumez  <cdumez@apple.com>
    238
  • trunk/Source/WebCore/editing/FrameSelection.cpp

    r280178 r280872  
    19141914    HitTestResult result(point);
    19151915    m_document->hitTest(HitTestRequest(), result);
    1916     Node* innerNode = result.innerNode();
     1916    RefPtr innerNode = result.innerNode();
    19171917    if (!innerNode || !innerNode->renderer())
    19181918        return false;
     1919
     1920    if (HTMLElement::isInsideImageOverlay(*range) && HTMLElement::isInsideImageOverlay(*innerNode)) {
     1921        for (auto quad : RenderObject::absoluteTextQuads(*range, { RenderObject::BoundingRectBehavior::UseSelectionHeight })) {
     1922            if (!quad.isEmpty() && quad.containsPoint(point))
     1923                return true;
     1924        }
     1925        return false;
     1926    }
    19191927
    19201928    return WebCore::contains<ComposedTree>(*range, makeBoundaryPoint(innerNode->renderer()->positionForPoint(result.localPoint(), nullptr)));
Note: See TracChangeset for help on using the changeset viewer.