Changeset 209427 in webkit


Ignore:
Timestamp:
Dec 6, 2016 3:06:42 PM (7 years ago)
Author:
Alan Bujtas
Message:

Can not select whole line when using flexbox
https://bugs.webkit.org/show_bug.cgi?id=165299

Reviewed by David Hyatt.

Source/WebCore:

RootInlineBox::selectionTopAdjustedForPrecedingBlock assumes that the preceding block is
always above the current line. However in certain layout contexts (flex as an example) the block before
could just be on the same line as the current one.

This patch checks if we actually need to adjust the selection top to avoid vertical selection overlap.

Test: fast/flexbox/flexbox-fail-to-select-same-line.html

  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::blockBeforeWithinSelectionRoot): Deleted.

  • rendering/RenderBlock.h:
  • rendering/RootInlineBox.cpp:

(WebCore::blockBeforeWithinSelectionRoot):
(WebCore::RootInlineBox::selectionTopAdjustedForPrecedingBlock):

LayoutTests:

  • fast/flexbox/flexbox-fail-to-select-same-line-expected.html: Added.
  • fast/flexbox/flexbox-fail-to-select-same-line.html: Added.
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r209425 r209427  
     12016-12-06  Zalan Bujtas  <zalan@apple.com>
     2
     3        Can not select whole line when using flexbox
     4        https://bugs.webkit.org/show_bug.cgi?id=165299
     5
     6        Reviewed by David Hyatt.
     7
     8        * fast/flexbox/flexbox-fail-to-select-same-line-expected.html: Added.
     9        * fast/flexbox/flexbox-fail-to-select-same-line.html: Added.
     10
    1112016-12-06  Jer Noble  <jer.noble@apple.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r209426 r209427  
     12016-12-06  Zalan Bujtas  <zalan@apple.com>
     2
     3        Can not select whole line when using flexbox
     4        https://bugs.webkit.org/show_bug.cgi?id=165299
     5
     6        Reviewed by David Hyatt.
     7
     8        RootInlineBox::selectionTopAdjustedForPrecedingBlock assumes that the preceding block is
     9        always above the current line. However in certain layout contexts (flex as an example) the block before
     10        could just be on the same line as the current one.
     11
     12        This patch checks if we actually need to adjust the selection top to avoid vertical selection overlap.
     13
     14        Test: fast/flexbox/flexbox-fail-to-select-same-line.html
     15
     16        * rendering/RenderBlock.cpp:
     17        (WebCore::RenderBlock::blockBeforeWithinSelectionRoot): Deleted.
     18        * rendering/RenderBlock.h:
     19        * rendering/RootInlineBox.cpp:
     20        (WebCore::blockBeforeWithinSelectionRoot):
     21        (WebCore::RootInlineBox::selectionTopAdjustedForPrecedingBlock):
     22
    1232016-12-06  Ryosuke Niwa  <rniwa@webkit.org>
    224
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r208985 r209427  
    22022202}
    22032203
    2204 RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) const
    2205 {
    2206     if (isSelectionRoot())
    2207         return nullptr;
    2208 
    2209     const RenderElement* object = this;
    2210     RenderObject* sibling;
    2211     do {
    2212         sibling = object->previousSibling();
    2213         while (sibling && (!is<RenderBlock>(*sibling) || downcast<RenderBlock>(*sibling).isSelectionRoot()))
    2214             sibling = sibling->previousSibling();
    2215 
    2216         offset -= LayoutSize(downcast<RenderBlock>(*object).logicalLeft(), downcast<RenderBlock>(*object).logicalTop());
    2217         object = object->parent();
    2218     } while (!sibling && is<RenderBlock>(object) && !downcast<RenderBlock>(*object).isSelectionRoot());
    2219 
    2220     if (!sibling)
    2221         return nullptr;
    2222 
    2223     RenderBlock* beforeBlock = downcast<RenderBlock>(sibling);
    2224 
    2225     offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
    2226 
    2227     RenderObject* child = beforeBlock->lastChild();
    2228     while (is<RenderBlock>(child)) {
    2229         beforeBlock = downcast<RenderBlock>(child);
    2230         offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
    2231         child = beforeBlock->lastChild();
    2232     }
    2233     return beforeBlock;
    2234 }
    2235 
    22362204TrackedRendererListHashSet* RenderBlock::positionedObjects() const
    22372205{
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r208985 r209427  
    177177        RenderBoxModelObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
    178178    void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
    179     RenderBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const;
     179    bool isSelectionRoot() const;
    180180
    181181    LayoutRect logicalRectToPhysicalRect(const LayoutPoint& physicalPosition, const LayoutRect& logicalRect);
     
    458458    }
    459459    bool shouldPaintSelectionGaps() const final;
    460     bool isSelectionRoot() const;
    461460    GapRects selectionGaps(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    462461        LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo* = 0);
  • trunk/Source/WebCore/rendering/RootInlineBox.cpp

    r208112 r209427  
    642642}
    643643
     644static RenderBlock* blockBeforeWithinSelectionRoot(const RenderBlockFlow& blockFlow, LayoutSize& offset)
     645{
     646    if (blockFlow.isSelectionRoot())
     647        return nullptr;
     648
     649    const RenderElement* object = &blockFlow;
     650    RenderObject* sibling;
     651    do {
     652        sibling = object->previousSibling();
     653        while (sibling && (!is<RenderBlock>(*sibling) || downcast<RenderBlock>(*sibling).isSelectionRoot()))
     654            sibling = sibling->previousSibling();
     655
     656        offset -= LayoutSize(downcast<RenderBlock>(*object).logicalLeft(), downcast<RenderBlock>(*object).logicalTop());
     657        object = object->parent();
     658    } while (!sibling && is<RenderBlock>(object) && !downcast<RenderBlock>(*object).isSelectionRoot());
     659
     660    if (!sibling)
     661        return nullptr;
     662
     663    RenderBlock* beforeBlock = downcast<RenderBlock>(sibling);
     664
     665    offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
     666
     667    RenderObject* child = beforeBlock->lastChild();
     668    while (is<RenderBlock>(child)) {
     669        beforeBlock = downcast<RenderBlock>(child);
     670        offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
     671        child = beforeBlock->lastChild();
     672    }
     673    return beforeBlock;
     674}
     675
    644676LayoutUnit RootInlineBox::selectionTopAdjustedForPrecedingBlock() const
    645677{
     
    647679    LayoutUnit top = selectionTop();
    648680
    649     RenderObject::SelectionState blockSelectionState = rootBox.blockFlow().selectionState();
     681    auto blockSelectionState = rootBox.blockFlow().selectionState();
    650682    if (blockSelectionState != RenderObject::SelectionInside && blockSelectionState != RenderObject::SelectionEnd)
    651683        return top;
    652684
    653685    LayoutSize offsetToBlockBefore;
    654     if (RenderBlock* block = rootBox.blockFlow().blockBeforeWithinSelectionRoot(offsetToBlockBefore)) {
    655         if (is<RenderBlockFlow>(*block)) {
    656             if (RootInlineBox* lastLine = downcast<RenderBlockFlow>(*block).lastRootBox()) {
    657                 RenderObject::SelectionState lastLineSelectionState = lastLine->selectionState();
    658                 if (lastLineSelectionState != RenderObject::SelectionInside && lastLineSelectionState != RenderObject::SelectionStart)
    659                     return top;
    660 
    661                 LayoutUnit lastLineSelectionBottom = lastLine->selectionBottom() + offsetToBlockBefore.height();
    662                 top = std::max(top, lastLineSelectionBottom);
    663             }
    664         }
    665     }
    666 
     686    auto* blockBefore = blockBeforeWithinSelectionRoot(rootBox.blockFlow(), offsetToBlockBefore);
     687    if (!is<RenderBlockFlow>(blockBefore))
     688        return top;
     689
     690    // Do not adjust blocks sharing the same line.
     691    if (!offsetToBlockBefore.height())
     692        return top;
     693
     694    if (auto* lastLine = downcast<RenderBlockFlow>(*blockBefore).lastRootBox()) {
     695        RenderObject::SelectionState lastLineSelectionState = lastLine->selectionState();
     696        if (lastLineSelectionState != RenderObject::SelectionInside && lastLineSelectionState != RenderObject::SelectionStart)
     697            return top;
     698
     699        LayoutUnit lastLineSelectionBottom = lastLine->selectionBottom() + offsetToBlockBefore.height();
     700        top = std::max(top, lastLineSelectionBottom);
     701    }
    667702    return top;
    668703}
Note: See TracChangeset for help on using the changeset viewer.