Title: [209427] trunk
Revision
209427
Author
za...@apple.com
Date
2016-12-06 15:06:42 -0800 (Tue, 06 Dec 2016)

Log 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.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (209426 => 209427)


--- trunk/LayoutTests/ChangeLog	2016-12-06 23:01:56 UTC (rev 209426)
+++ trunk/LayoutTests/ChangeLog	2016-12-06 23:06:42 UTC (rev 209427)
@@ -1,3 +1,13 @@
+2016-12-06  Zalan Bujtas  <za...@apple.com>
+
+        Can not select whole line when using flexbox
+        https://bugs.webkit.org/show_bug.cgi?id=165299
+
+        Reviewed by David Hyatt.
+
+        * fast/flexbox/flexbox-fail-to-select-same-line-expected.html: Added.
+        * fast/flexbox/flexbox-fail-to-select-same-line.html: Added.
+
 2016-12-06  Jer Noble  <jer.no...@apple.com>
 
         YouTube sometimes pauses when switching tabs

Added: trunk/LayoutTests/fast/flexbox/flexbox-fail-to-select-same-line-expected.html (0 => 209427)


--- trunk/LayoutTests/fast/flexbox/flexbox-fail-to-select-same-line-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/flexbox/flexbox-fail-to-select-same-line-expected.html	2016-12-06 23:06:42 UTC (rev 209427)
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests that we can select flex content when they share the same line.</title>
+<style>
+div {
+  color: transparent;
+  font-size: 10px;
+}
+
+div::selection {
+	background-color: green;
+}
+</style>
+</head>
+<body>
+<div>&nbsp&nbsp</div>
+<script>
+  document.execCommand('selectAll', false, null);
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/flexbox/flexbox-fail-to-select-same-line.html (0 => 209427)


--- trunk/LayoutTests/fast/flexbox/flexbox-fail-to-select-same-line.html	                        (rev 0)
+++ trunk/LayoutTests/fast/flexbox/flexbox-fail-to-select-same-line.html	2016-12-06 23:06:42 UTC (rev 209427)
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests that we can select flex content when they share the same line.</title>
+<style>
+.line {
+  display: flex;
+  color: transparent;
+  font-size: 10px;
+}
+
+div::selection {
+  background-color: green;
+}
+</style>
+</head>
+<body>
+<div class="line"><div>&nbsp</div><div>&nbsp</div></div>
+<script>
+  document.execCommand('selectAll', false, null);
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (209426 => 209427)


--- trunk/Source/WebCore/ChangeLog	2016-12-06 23:01:56 UTC (rev 209426)
+++ trunk/Source/WebCore/ChangeLog	2016-12-06 23:06:42 UTC (rev 209427)
@@ -1,3 +1,25 @@
+2016-12-06  Zalan Bujtas  <za...@apple.com>
+
+        Can not select whole line when using flexbox
+        https://bugs.webkit.org/show_bug.cgi?id=165299
+
+        Reviewed by David Hyatt.
+
+        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):
+
 2016-12-06  Ryosuke Niwa  <rn...@webkit.org>
 
         Add more assertions to ElementQueue diagnose a bug

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (209426 => 209427)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2016-12-06 23:01:56 UTC (rev 209426)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2016-12-06 23:06:42 UTC (rev 209427)
@@ -2201,38 +2201,6 @@
     return logicalRight;
 }
 
-RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) const
-{
-    if (isSelectionRoot())
-        return nullptr;
-
-    const RenderElement* object = this;
-    RenderObject* sibling;
-    do {
-        sibling = object->previousSibling();
-        while (sibling && (!is<RenderBlock>(*sibling) || downcast<RenderBlock>(*sibling).isSelectionRoot()))
-            sibling = sibling->previousSibling();
-
-        offset -= LayoutSize(downcast<RenderBlock>(*object).logicalLeft(), downcast<RenderBlock>(*object).logicalTop());
-        object = object->parent();
-    } while (!sibling && is<RenderBlock>(object) && !downcast<RenderBlock>(*object).isSelectionRoot());
-
-    if (!sibling)
-        return nullptr;
-
-    RenderBlock* beforeBlock = downcast<RenderBlock>(sibling);
-
-    offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
-
-    RenderObject* child = beforeBlock->lastChild();
-    while (is<RenderBlock>(child)) {
-        beforeBlock = downcast<RenderBlock>(child);
-        offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
-        child = beforeBlock->lastChild();
-    }
-    return beforeBlock;
-}
-
 TrackedRendererListHashSet* RenderBlock::positionedObjects() const
 {
     return positionedDescendantsMap().positionedRenderers(*this);

Modified: trunk/Source/WebCore/rendering/RenderBlock.h (209426 => 209427)


--- trunk/Source/WebCore/rendering/RenderBlock.h	2016-12-06 23:01:56 UTC (rev 209426)
+++ trunk/Source/WebCore/rendering/RenderBlock.h	2016-12-06 23:06:42 UTC (rev 209427)
@@ -176,7 +176,7 @@
     LayoutRect logicalRightSelectionGap(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
         RenderBoxModelObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
     void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
-    RenderBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const;
+    bool isSelectionRoot() const;
 
     LayoutRect logicalRectToPhysicalRect(const LayoutPoint& physicalPosition, const LayoutRect& logicalRect);
 
@@ -457,7 +457,6 @@
         return selectionGapRectsForRepaint(repaintContainer);
     }
     bool shouldPaintSelectionGaps() const final;
-    bool isSelectionRoot() const;
     GapRects selectionGaps(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
         LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo* = 0);
     // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow

Modified: trunk/Source/WebCore/rendering/RootInlineBox.cpp (209426 => 209427)


--- trunk/Source/WebCore/rendering/RootInlineBox.cpp	2016-12-06 23:01:56 UTC (rev 209426)
+++ trunk/Source/WebCore/rendering/RootInlineBox.cpp	2016-12-06 23:06:42 UTC (rev 209427)
@@ -641,29 +641,64 @@
     return prevBottom;
 }
 
+static RenderBlock* blockBeforeWithinSelectionRoot(const RenderBlockFlow& blockFlow, LayoutSize& offset)
+{
+    if (blockFlow.isSelectionRoot())
+        return nullptr;
+
+    const RenderElement* object = &blockFlow;
+    RenderObject* sibling;
+    do {
+        sibling = object->previousSibling();
+        while (sibling && (!is<RenderBlock>(*sibling) || downcast<RenderBlock>(*sibling).isSelectionRoot()))
+            sibling = sibling->previousSibling();
+
+        offset -= LayoutSize(downcast<RenderBlock>(*object).logicalLeft(), downcast<RenderBlock>(*object).logicalTop());
+        object = object->parent();
+    } while (!sibling && is<RenderBlock>(object) && !downcast<RenderBlock>(*object).isSelectionRoot());
+
+    if (!sibling)
+        return nullptr;
+
+    RenderBlock* beforeBlock = downcast<RenderBlock>(sibling);
+
+    offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
+
+    RenderObject* child = beforeBlock->lastChild();
+    while (is<RenderBlock>(child)) {
+        beforeBlock = downcast<RenderBlock>(child);
+        offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
+        child = beforeBlock->lastChild();
+    }
+    return beforeBlock;
+}
+
 LayoutUnit RootInlineBox::selectionTopAdjustedForPrecedingBlock() const
 {
     const RootInlineBox& rootBox = root();
     LayoutUnit top = selectionTop();
 
-    RenderObject::SelectionState blockSelectionState = rootBox.blockFlow().selectionState();
+    auto blockSelectionState = rootBox.blockFlow().selectionState();
     if (blockSelectionState != RenderObject::SelectionInside && blockSelectionState != RenderObject::SelectionEnd)
         return top;
 
     LayoutSize offsetToBlockBefore;
-    if (RenderBlock* block = rootBox.blockFlow().blockBeforeWithinSelectionRoot(offsetToBlockBefore)) {
-        if (is<RenderBlockFlow>(*block)) {
-            if (RootInlineBox* lastLine = downcast<RenderBlockFlow>(*block).lastRootBox()) {
-                RenderObject::SelectionState lastLineSelectionState = lastLine->selectionState();
-                if (lastLineSelectionState != RenderObject::SelectionInside && lastLineSelectionState != RenderObject::SelectionStart)
-                    return top;
+    auto* blockBefore = blockBeforeWithinSelectionRoot(rootBox.blockFlow(), offsetToBlockBefore);
+    if (!is<RenderBlockFlow>(blockBefore))
+        return top;
 
-                LayoutUnit lastLineSelectionBottom = lastLine->selectionBottom() + offsetToBlockBefore.height();
-                top = std::max(top, lastLineSelectionBottom);
-            }
-        }
+    // Do not adjust blocks sharing the same line.
+    if (!offsetToBlockBefore.height())
+        return top;
+
+    if (auto* lastLine = downcast<RenderBlockFlow>(*blockBefore).lastRootBox()) {
+        RenderObject::SelectionState lastLineSelectionState = lastLine->selectionState();
+        if (lastLineSelectionState != RenderObject::SelectionInside && lastLineSelectionState != RenderObject::SelectionStart)
+            return top;
+
+        LayoutUnit lastLineSelectionBottom = lastLine->selectionBottom() + offsetToBlockBefore.height();
+        top = std::max(top, lastLineSelectionBottom);
     }
-
     return top;
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to