REGRESSION (r168046): [New Multicolumn] Selection into and out of column-span element...
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 May 2014 21:00:19 +0000 (21:00 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 May 2014 21:00:19 +0000 (21:00 +0000)
https://bugs.webkit.org/show_bug.cgi?id=132066

Reviewed by Oliver Hunt.

Make a new SelectionIterator struct that knows how to drill into and out of
column span placeholders. Also change spans to be selection roots (in the painting
sense).

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::isSelectionRoot):
(WebCore::RenderBlock::selectionGaps):
* rendering/RenderView.cpp:
(WebCore::SelectionIterator::SelectionIterator):
(WebCore::SelectionIterator::checkForSpanner):
(WebCore::SelectionIterator::current):
(WebCore::SelectionIterator::next):
(WebCore::RenderView::subtreeSelectionBounds):
(WebCore::RenderView::repaintSubtreeSelection):
(WebCore::RenderView::setSubtreeSelection):

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

Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderView.cpp

index 2fd7a02..67acad9 100644 (file)
@@ -1,3 +1,26 @@
+2014-05-01  David Hyatt  <hyatt@apple.com>
+
+        REGRESSION (r168046): [New Multicolumn] Selection into and out of column-span elements doesn't work
+        https://bugs.webkit.org/show_bug.cgi?id=132066
+
+        Reviewed by Oliver Hunt.
+
+        Make a new SelectionIterator struct that knows how to drill into and out of
+        column span placeholders. Also change spans to be selection roots (in the painting
+        sense).
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::isSelectionRoot):
+        (WebCore::RenderBlock::selectionGaps):
+        * rendering/RenderView.cpp:
+        (WebCore::SelectionIterator::SelectionIterator):
+        (WebCore::SelectionIterator::checkForSpanner):
+        (WebCore::SelectionIterator::current):
+        (WebCore::SelectionIterator::next):
+        (WebCore::RenderView::subtreeSelectionBounds):
+        (WebCore::RenderView::repaintSubtreeSelection):
+        (WebCore::RenderView::setSubtreeSelection):
+
 2014-05-01  Simon Fraser  <simon.fraser@apple.com>
 
         Don't always make backing store for -webkit-backface-visibility:hidden
index 87f3b8c..55c657e 100644 (file)
@@ -2294,7 +2294,7 @@ bool RenderBlock::isSelectionRoot() const
         || isPositioned() || isFloating()
         || isTableCell() || isInlineBlockOrInlineTable()
         || hasTransform() || hasReflection() || hasMask() || isWritingModeRoot()
-        || isRenderFlowThread())
+        || isRenderFlowThread() || style().columnSpan() == ColumnSpanAll)
         return true;
     
     if (view().selectionStart()) {
@@ -2413,7 +2413,7 @@ GapRects RenderBlock::selectionGaps(RenderBlock& rootBlock, const LayoutPoint& r
     if (!isRenderBlockFlow()) // FIXME: Make multi-column selection gap filling work someday.
         return result;
 
-    if (hasColumns() || hasTransform() || style().columnSpan() || isInFlowRenderFlowThread()) {
+    if (hasColumns() || hasTransform() || style().columnSpan() == ColumnSpanAll || isInFlowRenderFlowThread()) {
         // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
         lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
         lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight(), cache);
index f2cba97..0d24260 100644 (file)
@@ -44,6 +44,7 @@
 #include "RenderLayerCompositor.h"
 #include "RenderMultiColumnFlowThread.h"
 #include "RenderMultiColumnSet.h"
+#include "RenderMultiColumnSpannerPlaceholder.h"
 #include "RenderNamedFlowThread.h"
 #include "RenderSelectionInfo.h"
 #include "RenderWidget.h"
 
 namespace WebCore {
 
+struct SelectionIterator {
+    RenderObject* m_current;
+    Vector<RenderMultiColumnSpannerPlaceholder*> m_spannerStack;
+    
+    SelectionIterator(RenderObject* o)
+    {
+        m_current = o;
+        checkForSpanner();
+    }
+    
+    void checkForSpanner()
+    {
+        if (!m_current || !m_current->isRenderMultiColumnSpannerPlaceholder())
+            return;
+        RenderMultiColumnSpannerPlaceholder* placeholder = toRenderMultiColumnSpannerPlaceholder(m_current);
+        m_spannerStack.append(placeholder);
+        m_current = placeholder->spanner();
+    }
+    
+    RenderObject* current()
+    {
+        return m_current;
+    }
+    
+    RenderObject* next()
+    {
+        RenderObject* currentSpan = m_spannerStack.isEmpty() ? 0 : m_spannerStack.last()->spanner();
+        m_current = m_current->nextInPreOrder(currentSpan);
+        checkForSpanner();
+        if (!m_current && currentSpan) {
+            RenderObject* placeholder = m_spannerStack.last();
+            m_spannerStack.removeLast();
+            m_current = placeholder->nextInPreOrder();
+            checkForSpanner();
+        }
+        return m_current;
+    }
+};
+
 RenderView::RenderView(Document& document, PassRef<RenderStyle> style)
     : RenderBlockFlow(document, std::move(style))
     , m_frameView(*document.view())
@@ -684,6 +724,7 @@ LayoutRect RenderView::subtreeSelectionBounds(const SelectionSubtreeRoot& root,
 
     RenderObject* os = root.selectionStart();
     RenderObject* stop = rendererAfterPosition(root.selectionEnd(), root.selectionEndPos());
+    SelectionIterator selectionIterator(os);
     while (os && os != stop) {
         if ((os->canBeSelectionLeaf() || os == root.selectionStart() || os == root.selectionEnd()) && os->selectionState() != SelectionNone) {
             // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
@@ -698,7 +739,7 @@ LayoutRect RenderView::subtreeSelectionBounds(const SelectionSubtreeRoot& root,
             }
         }
 
-        os = os->nextInPreOrder();
+        os = selectionIterator.next();
     }
 
     // Now create a single bounding box rect that encloses the whole selection.
@@ -732,7 +773,8 @@ void RenderView::repaintSubtreeSelection(const SelectionSubtreeRoot& root) const
     HashSet<RenderBlock*> processedBlocks;
 
     RenderObject* end = rendererAfterPosition(root.selectionEnd(), root.selectionEndPos());
-    for (RenderObject* o = root.selectionStart(); o && o != end; o = o->nextInPreOrder()) {
+    SelectionIterator selectionIterator(root.selectionStart());
+    for (RenderObject* o = selectionIterator.current(); o && o != end; o = selectionIterator.next()) {
         if (!o->canBeSelectionLeaf() && o != root.selectionStart() && o != root.selectionEnd())
             continue;
         if (o->selectionState() == SelectionNone)
@@ -885,6 +927,7 @@ void RenderView::setSubtreeSelection(SelectionSubtreeRoot& root, RenderObject* s
 
     RenderObject* os = root.selectionStart();
     RenderObject* stop = rendererAfterPosition(root.selectionEnd(), root.selectionEndPos());
+    SelectionIterator selectionIterator(os);
     while (os && os != stop) {
         if ((os->canBeSelectionLeaf() || os == root.selectionStart() || os == root.selectionEnd())
             && os->selectionState() != SelectionNone) {
@@ -902,7 +945,7 @@ void RenderView::setSubtreeSelection(SelectionSubtreeRoot& root, RenderObject* s
             }
         }
 
-        os = os->nextInPreOrder();
+        os = selectionIterator.next();
     }
 
     // Now clear the selection.
@@ -928,11 +971,12 @@ void RenderView::setSubtreeSelection(SelectionSubtreeRoot& root, RenderObject* s
 
     RenderObject* o = start;
     stop = rendererAfterPosition(end, endPos);
-
+    selectionIterator = SelectionIterator(o);
+    
     while (o && o != stop) {
         if (o != start && o != end && o->canBeSelectionLeaf())
             o->setSelectionStateIfNeeded(SelectionInside);
-        o = o->nextInPreOrder();
+        o = selectionIterator.next();
     }
 
     if (blockRepaintMode != RepaintNothing)
@@ -941,6 +985,7 @@ void RenderView::setSubtreeSelection(SelectionSubtreeRoot& root, RenderObject* s
     // Now that the selection state has been updated for the new objects, walk them again and
     // put them in the new objects list.
     o = start;
+    selectionIterator = SelectionIterator(o);
     while (o && o != stop) {
         if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
             std::unique_ptr<RenderSelectionInfo> selectionInfo = std::make_unique<RenderSelectionInfo>(o, true);
@@ -965,7 +1010,7 @@ void RenderView::setSubtreeSelection(SelectionSubtreeRoot& root, RenderObject* s
             }
         }
 
-        o = o->nextInPreOrder();
+        o = selectionIterator.next();
     }
 
     if (blockRepaintMode == RepaintNothing)