Patch by Javier Fernandez <jfernandez@igalia.com> on 2013-09-04
Reviewed by David Hyatt.
Source/WebCore:
When using CSS Regions is usual that the RenderTree doesn't match
the DOM Tree in terms of relative position of the nodes. Besides,
usually the content of a certain node is split and spread across
multiple blocks, rendered in different positions.
Regarding the Selection, this problem is even more important; the
selection direction changes when crossing the FlowThread
boundaries. This weird behavior is also present in other layouts
using non-regular positioning mechanisms, like absolute,
static. However, for those layouts the RenderTree preserves the
order of the nodes, unlike the CSS Regions layout model.
Because of how the RenderTree is generated with CSS Regions, the
RenderView::setSelection algorithm is not able to repaint some of
the rectangles defined during the selection process. In order to
face this issue, the proposed fix determines whether it should
backwards traversing the RenderTree, from the "stop" node to the
RenderView node.
Test: fast/regions/selecting-text-through-different-region-flows-2.html
* rendering/RenderView.cpp:
(WebCore::getNextOrPrevRenderObjectBasedOnDirection): Added.
(WebCore::RenderView::setSelection):
LayoutTests:
* fast/regions/selecting-text-through-different-region-flows-2-expected.html: Added.
* fast/regions/selecting-text-through-different-region-flows-2.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@155058
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2013-09-04 Javier Fernandez <jfernandez@igalia.com>
+
+ <https://webkit.org/b/119622> [CSSRegions] Not possible to clear the selection when mixing content from different FlowThreads
+
+ Reviewed by David Hyatt.
+
+ * fast/regions/selecting-text-through-different-region-flows-2-expected.html: Added.
+ * fast/regions/selecting-text-through-different-region-flows-2.html: Added.
+
2013-09-04 Oliver Hunt <oliver@apple.com>
Fix fast/storage/serialized script value, and add new tests for Map and Set
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+body { width: 600px; }
+#footNote { font-size: 13px; }
+</style>
+<script>
+function selectText()
+{
+ var selection = window.getSelection();
+
+ var start = document.getElementById("start");
+ var end = document.getElementById("end");
+
+ selection.setBaseAndExtent(start, 0, end, 0);
+}
+</script>
+</head>
+<body onload="selectText()">
+<div id="content">
+ <h1 style="margin-top: 0px">Selecting text through different CSS-Region flows</h1>
+ <div>
+ This text contains a footnote as a nested region what is diplayed <span id="start">below<span> the article. (1) If you start selecting
+ text from this article until somewhere in the footnote and then click somewhere, the selection should be cleared.
+ </div>
+ <div id="footNote">(1) This is a footnote. Footnotes can be quite long and go over several lines. This footnote
+ is nested inside the text <span id="end">above<span> and displayed here with the help of css-regions.</span></div>
+</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+body { width: 600px; }
+
+#footNote {
+ -webkit-flow-into: footNote;
+ display: block;
+ font-size: 13px;
+}
+
+#footNoteRegion { -webkit-flow-from: footNote; }
+#content { -webkit-flow-into: content; }
+#region { -webkit-flow-from: content; }
+</style>
+</head>
+<body>
+
+<div id="region"></div>
+<div id="footNoteRegion"></div>
+<div id="content">
+ <h1 style="margin-top: 0px">Selecting text through different CSS-Region flows</h1>
+ <div id="contentText">
+ This text contains a footnote as a nested region what is diplayed <span id="start">below</span> the article. (1) <span id="footNote">
+ <span><span></span>(1) This is a footnote. Footnotes can be quite long and go over several lines. This footnote
+ is nested inside the text <span id="end">above</span> and displayed here with the help of css-regions.</span></span> If you start selecting
+ text from this article until somewhere in the footnote and then click somewhere, the selection should be cleared.
+ </div>
+</div>
+
+<script>
+if (window.testRunner) {
+ // We are positioning the mouse to the center of the contentText and start holding the mouse down
+ var start = document.getElementById("start");
+ var xStartPosition = start.offsetLeft + 0;
+ var yStartPosition = start.offsetTop + start.offsetHeight / 2;
+ eventSender.mouseMoveTo(xStartPosition, yStartPosition);
+ eventSender.mouseDown();
+
+ // We are positioning the mouse to the center of the footNote (what is a different region flow) and release the button
+ var end = document.getElementById("end");
+ var xEndPosition = end.offsetLeft + 0;
+ var yEndPosition = end.offsetTop + end.offsetHeight / 2;
+ eventSender.mouseMoveTo(xEndPosition, yEndPosition);
+ eventSender.mouseUp();
+}
+</script>
+</body>
+</html>
+2013-09-04 Javier Fernandez <jfernandez@igalia.com>
+
+ <https://webkit.org/b/119622> [CSSRegions] Not possible to clear the selection when mixing content from different FlowThreads
+
+ Reviewed by David Hyatt.
+
+ When using CSS Regions is usual that the RenderTree doesn't match
+ the DOM Tree in terms of relative position of the nodes. Besides,
+ usually the content of a certain node is split and spread across
+ multiple blocks, rendered in different positions.
+
+ Regarding the Selection, this problem is even more important; the
+ selection direction changes when crossing the FlowThread
+ boundaries. This weird behavior is also present in other layouts
+ using non-regular positioning mechanisms, like absolute,
+ static. However, for those layouts the RenderTree preserves the
+ order of the nodes, unlike the CSS Regions layout model.
+
+ Because of how the RenderTree is generated with CSS Regions, the
+ RenderView::setSelection algorithm is not able to repaint some of
+ the rectangles defined during the selection process. In order to
+ face this issue, the proposed fix determines whether it should
+ backwards traversing the RenderTree, from the "stop" node to the
+ RenderView node.
+
+ Test: fast/regions/selecting-text-through-different-region-flows-2.html
+
+ * rendering/RenderView.cpp:
+ (WebCore::getNextOrPrevRenderObjectBasedOnDirection): Added.
+ (WebCore::RenderView::setSelection):
+
2013-09-04 Eric Carlson <eric.carlson@apple.com>
Get MEDIA_STREAM compiling on OSX
}
#endif
+// When exploring the RenderTree looking for the nodes involved in the Selection, sometimes it's
+// required to change the traversing direction because the "start" position is below the "end" one.
+static inline RenderObject* getNextOrPrevRenderObjectBasedOnDirection(const RenderObject* o, const RenderObject* stop, bool& continueExploring, bool& exploringBackwards)
+{
+ RenderObject* next;
+ if (exploringBackwards) {
+ next = o->previousInPreOrder();
+ continueExploring = next && !(next)->isRenderView();
+ } else {
+ next = o->nextInPreOrder();
+ continueExploring = next && next != stop;
+ exploringBackwards = !next && (next != stop);
+ if (exploringBackwards) {
+ next = stop->previousInPreOrder();
+ continueExploring = next && !next->isRenderView();
+ }
+ }
+
+ return next;
+}
+
void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
{
// Make sure both our start and end objects are defined.
m_selectionEnd == end && m_selectionEndPos == endPos && !caretChanged)
return;
- if ((start && end) && (start->flowThreadContainingBlock() != end->flowThreadContainingBlock()))
- return;
-
// Record the old selected objects. These will be used later
// when we compare against the new selected objects.
int oldStartPos = m_selectionStartPos;
RenderObject* os = m_selectionStart;
RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
- while (os && os != stop) {
+ bool exploringBackwards = false;
+ bool continueExploring = os && (os != stop);
+ while (continueExploring) {
if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
// Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
oldSelectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, true)));
}
}
- os = os->nextInPreOrder();
+ os = getNextOrPrevRenderObjectBasedOnDirection(os, stop, continueExploring, exploringBackwards);
}
// Now clear the selection.
// 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;
- while (o && o != stop) {
+ exploringBackwards = false;
+ continueExploring = o && (o != stop);
+ while (continueExploring) {
if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
newSelectedObjects.set(o, adoptPtr(new RenderSelectionInfo(o, true)));
RenderBlock* cb = o->containingBlock();
}
}
- o = o->nextInPreOrder();
+ o = getNextOrPrevRenderObjectBasedOnDirection(o, stop, continueExploring, exploringBackwards);
}
if (blockRepaintMode == RepaintNothing)