[CSS Regions] Selection highlight doesn't match DOM selection
authorrego@igalia.com <rego@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 Apr 2014 10:22:47 +0000 (10:22 +0000)
committerrego@igalia.com <rego@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 Apr 2014 10:22:47 +0000 (10:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=131511

Reviewed by David Hyatt.

Source/WebCore:
This patch implements a subtrees approach to fix selection interaction in CSS Regions.

The idea is to divide the Render tree in subtrees. One subtree will be the RenderView (which is always present),
then for each RenderNamedFlowThread (which are children of RenderView) we will have an extra subtree.

For each subtree it determines the start and end positions according to the DOM tree. So, every subtree will
always have a start and end position, and the selection algorithm will be able to reach the end from the start
without problems (this allows us to remove the changes introduced in r155058).

Then selection related methods in RenderView are adapted to ensure that they are called for each subtree. Making
the selection highlight to match DOM selection as expected.

Test: fast/regions/selection/selecting-text-including-region.html

* CMakeLists.txt: Add new class SelectionSubtreeRoot to build file.
* WebCore.vcxproj/WebCore.vcxproj: Ditto.
* WebCore.vcxproj/WebCore.vcxproj.filters: Ditto.
* WebCore.xcodeproj/project.pbxproj: Ditto.
* rendering/RenderNamedFlowThread.h: Inherit from SelectionSubtreeRoot.
* rendering/RenderObject.cpp:
(WebCore::RenderObject::selectionRoot): New method to return the RenderNamedFlowThread if any or the RenderView
otherwise.
(WebCore::RenderObject::selectionStartEnd): If it's inside a RenderNamedFlowThread use specific method instead
of the RenderView's one.
* rendering/RenderObject.h: Add new method signature.
* rendering/RenderView.cpp:
(WebCore::RenderView::selectionBounds): Adapt method to subtrees approach.
(WebCore::RenderView::subtreeSelectionBounds): Modify previous method in order to use SelectionSubtreeRoot
objects.
(WebCore::RenderView::repaintSelection): Adapt method to subtrees approach.
(WebCore::RenderView::repaintSubtreeSelection): Modify previous method in order to use SelectionSubtreeRoot
objects.
(getNextOrPrevRenderObjectBasedOnDirection): Deleted method from r155058 as it is not needed anymore. Each
subtree will have start and end positions, so the selection algorithm will always find the end.
(WebCore::RenderView::setSelection): Adapt method to subtrees approach.
(WebCore::RenderView::splitSelectionBetweenSubtrees): Determine start and end positions for each subtree and
call setSubtreeSelection().
(WebCore::RenderView::setSubtreeSelection): Modify previous method in order to use SelectionSubtreeRoot objects.
* rendering/RenderView.h: Inherit from SelectionSubtreeRoot. Add signature for new helper methods receiving
SelectionSubtreeRoot objects.
* rendering/SelectionSubtreeRoot.cpp: Added.
(WebCore::SelectionSubtreeRoot::SelectionSubtreeRoot):
(WebCore::SelectionSubtreeRoot::selectionStartEndPositions):
* rendering/SelectionSubtreeRoot.h: Added. New class to identify root elements for the subtrees. With some basic
attributes and methods to store the start and end positions and offsets.
(WebCore::SelectionSubtreeRoot::selectionStart):
(WebCore::SelectionSubtreeRoot::selectionStartPos):
(WebCore::SelectionSubtreeRoot::selectionEnd):
(WebCore::SelectionSubtreeRoot::selectionEndPos):
(WebCore::SelectionSubtreeRoot::setSelectionStart):
(WebCore::SelectionSubtreeRoot::setSelectionStartPos):
(WebCore::SelectionSubtreeRoot::setSelectionEnd):
(WebCore::SelectionSubtreeRoot::setSelectionEndPos):

LayoutTests:
Add new test to check highlight of render objects moved under RenderNamedFlowThread in the render tree.

Updated some tests to avoid issues with selection gap filling in the new implementation.

* fast/regions/selection/selecting-text-including-region-expected.html: Added.
* fast/regions/selection/selecting-text-including-region.html: Added.
* fast/regions/selection/selecting-text-through-different-region-flows-2-expected.html: Updated.
* fast/regions/selection/selecting-text-through-different-region-flows-2.html: Updated.
* fast/regions/selection/selection-direction-expected.html: Updated.
* fast/regions/selection/selection-direction.html: Updated.

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

19 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/regions/selection/selecting-text-including-region-expected.html [new file with mode: 0644]
LayoutTests/fast/regions/selection/selecting-text-including-region.html [new file with mode: 0644]
LayoutTests/fast/regions/selection/selecting-text-through-different-region-flows-2-expected.html
LayoutTests/fast/regions/selection/selecting-text-through-different-region-flows-2.html
LayoutTests/fast/regions/selection/selection-direction-expected.html
LayoutTests/fast/regions/selection/selection-direction.html
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/rendering/RenderNamedFlowThread.h
Source/WebCore/rendering/RenderObject.cpp
Source/WebCore/rendering/RenderObject.h
Source/WebCore/rendering/RenderView.cpp
Source/WebCore/rendering/RenderView.h
Source/WebCore/rendering/SelectionSubtreeRoot.cpp [new file with mode: 0644]
Source/WebCore/rendering/SelectionSubtreeRoot.h [new file with mode: 0644]

index d20cc8c..77c003c 100644 (file)
@@ -1,3 +1,21 @@
+2014-04-22  Manuel Rego Casasnovas  <rego@igalia.com>
+
+        [CSS Regions] Selection highlight doesn't match DOM selection
+        https://bugs.webkit.org/show_bug.cgi?id=131511
+
+        Reviewed by David Hyatt.
+
+        Add new test to check highlight of render objects moved under RenderNamedFlowThread in the render tree.
+
+        Updated some tests to avoid issues with selection gap filling in the new implementation.
+
+        * fast/regions/selection/selecting-text-including-region-expected.html: Added.
+        * fast/regions/selection/selecting-text-including-region.html: Added.
+        * fast/regions/selection/selecting-text-through-different-region-flows-2-expected.html: Updated.
+        * fast/regions/selection/selecting-text-through-different-region-flows-2.html: Updated.
+        * fast/regions/selection/selection-direction-expected.html: Updated.
+        * fast/regions/selection/selection-direction.html: Updated.
+
 2014-04-21  Brent Fulgham  <bfulgham@apple.com>
 
         [Mac] After a horizontal overflow scroll with a mechanical wheel mouse, vertical scrolling no longer works
diff --git a/LayoutTests/fast/regions/selection/selecting-text-including-region-expected.html b/LayoutTests/fast/regions/selection/selecting-text-including-region-expected.html
new file mode 100644 (file)
index 0000000..a502d2b
--- /dev/null
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../resources/helper.js"></script>
+    <link rel="stylesheet" href="../resources/region-style.css"></link>
+    <style>
+        * {
+            margin: 0px;
+            padding: 0px;
+        }
+
+        body {
+            line-height: 20px;
+            font-size: 20px;
+            font-family: Ahem;
+        }
+
+        #outside-1 {
+            position: absolute;
+            top: 0px;
+        }
+
+        #outside-2 {
+            position: absolute;
+            top: 100px;
+        }
+
+        #region {
+            position: absolute;
+            top: 200px;
+            background-color: cyan;
+        }
+
+        #description {
+            position: absolute;
+            top: 350px;
+        }
+    </style>
+    <script>
+        onMouseUpLogSelection("selected-content");
+    </script>
+</head>
+<body onload="selectContentByIds('word1', 'word2');" style="margin-top: 0;">
+    <div id="outside-1" class="bigBox">
+        X X X X X X X X
+        X X X X X X X X
+        X X X <span id="word1" class="token">X</span> X X X X
+        X X X X X X X X
+        X X X X X X X X
+    </div>
+    <div id="region" class="bigBox">
+        X X X X X X X X
+        X X X X X X X X
+        X X X X X X X X
+        X X X X X X X X
+        X X X X X X X X
+    </div>
+    <div id="outside-2" class="bigBox">
+        X X X X X X X X
+        X X X X X X X X
+        X X X <span id="word2" class="token">X</span> X X X X
+        X X X X X X X X
+        X X X X X X X X
+    </div>
+    <div id="description" class="description">
+        <h1><a href="https://bugs.webkit.org/show_bug.cgi?id=131511">Bug #131511 - [CSS Regions] Selection highlight doesn't match DOM selection</a></h1>
+        <p>This test checks the selection in 2 text wrapping a content node. If you select from <span class="token">X</span> to <span class="token">X</span> you will see that region text is highlighted and included in the selected content (because of the content of the region is between bot texts in the DOM).</p>
+        <dl>
+            <dt>Selected content:</dt>
+            <dd id="selected-content"></dd>
+        </dl>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/fast/regions/selection/selecting-text-including-region.html b/LayoutTests/fast/regions/selection/selecting-text-including-region.html
new file mode 100644 (file)
index 0000000..fa24e53
--- /dev/null
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../resources/helper.js"></script>
+    <link rel="stylesheet" href="../resources/region-style.css"></link>
+    <style>
+        * {
+            margin: 0px;
+            padding: 0px;
+        }
+
+        body {
+            line-height: 20px;
+            font-size: 20px;
+            font-family: Ahem;
+        }
+
+        #region {
+            background-color: cyan;
+        }
+
+        #description {
+            position: absolute;
+            top: 350px;
+        }
+    </style>
+    <script>
+        onMouseUpLogSelection("selected-content");
+    </script>
+</head>
+<body onload="selectContentByIds('word1', 'word2');" style="margin-top: 0;">
+    <div class="bigBox float">
+        X X X X X X X X
+        X X X X X X X X
+        X X X <span id="word1" class="token">X</span> X X X X
+        X X X X X X X X
+        X X X X X X X X
+    </div>
+    <div class="clear"></div>
+    <div class="flowArticle">
+        X X X X X X X X
+        X X X X X X X X
+        X X X X X X X X
+        X X X X X X X X
+        X X X X X X X X
+    </div>
+    <div class="bigBox float">
+        X X X X X X X X
+        X X X X X X X X
+        X X X <span id="word2" class="token">X</span> X X X X
+        X X X X X X X X
+        X X X X X X X X
+    </div>
+    <div class="clear"></div>
+    <div id="region" class="regionArticle bigBox"></div>
+    <div id="description" class="description">
+        <h1><a href="https://bugs.webkit.org/show_bug.cgi?id=131511">Bug #131511 - [CSS Regions] Selection highlight doesn't match DOM selection</a></h1>
+        <p>This test checks the selection in 2 text wrapping a content node. If you select from <span class="token">X</span> to <span class="token">X</span> you will see that region text is highlighted and included in the selected content (because of the content of the region is between bot texts in the DOM).</p>
+        <dl>
+            <dt>Selected content:</dt>
+            <dd id="selected-content"></dd>
+        </dl>
+    </div>
+</body>
+</html>
index 700ac24..aa229fd 100644 (file)
@@ -3,19 +3,56 @@
 <head>
 <script src="../resources/helper.js"></script>
 <style>
-body { width: 600px; }
-#footNote { font-size: 13px; }
+* {
+    margin: 0px;
+    padding: 0px;
+    font-size: 20px;
+    font-family: Ahem;
+    line-height: 20px;
+}
+#content1 {
+    height: 100px;
+    width: 200px;
+    position: absolute;
+    top: 50px;
+}
+#nestedRegion {
+    height: 100px;
+    width: 200px;
+    color: red;
+    position: absolute;
+    top: 250px;
+}
+#content2 {
+    height: 100px;
+    width: 200px;
+    position: absolute;
+    top: 150px;
+}
 </style>
 </head>
 <body onload="selectBaseAndExtent('start', 0, 'end', 1)">
-<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>
+<h1>Selecting text through different CSS-Region flows</h1>
+<div id="content1">
+    X X X X X
+    X X X X X
+    X X <span id="start">X</span> X X
+    X X X X X
+    X X X X XX
+</div>
+<div id="nestedRegion">
+    X X X X X
+    X X X X X
+    X X <span id="end">X</span> X X
+    X X X X X
+    X X X X X
+</div>
+<div id="content2">
+    X X X X X
+    X X X X X
+    X X X X X
+    X X X X X
+    X X X X X
 </div>
 </body>
 </html>
index 9b083b2..3760ae1 100644 (file)
@@ -3,30 +3,73 @@
 <head>
 <script src="../resources/helper.js"></script>
 <style>
-body { width: 600px; }
+* {
+    margin: 0px;
+    padding: 0px;
+    font-size: 20px;
+    font-family: Ahem;
+    line-height: 20px;
+}
+
+#nestedRegion {
+    -webkit-flow-into: nestedRegion;
+    color: red;
+}
 
-#footNote {
-    -webkit-flow-into: footNote;
-    display: block;
-    font-size: 13px;
+#content {
+    -webkit-flow-into: content;
 }
 
-#footNoteRegion { -webkit-flow-from: footNote; }
-#content { -webkit-flow-into: content; }
-#region { -webkit-flow-from: content; }
+#nestedRegionRegion {
+    -webkit-flow-from: nestedRegion;
+    height: 100px;
+    width: 200px;
+}
+#region {
+    -webkit-flow-from: content;
+    height: 200px;
+    width: 200px;
+}
+
+#content1 {
+    height: 100px;
+}
+
+#content2 {
+    height: 100px;
+}
+
+h1 {
+    height: 50px;
+}
 </style>
 </head>
 <body>
 
+<h1>Selecting text through different CSS-Region flows</h1>
 <div id="region"></div>
-<div id="footNoteRegion"></div>
+<div id="nestedRegionRegion"></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 id="content1">
+        X X X X X
+        X X X X X
+        X X <span id="start">X</span> X X
+        X X X X X
+        X X X X XX
+    </div>
+    <div id="nestedRegion">
+        X X X X X
+        X X X X X
+        X X <span id="end">X</span> X X
+        X X X X X
+        X X X X X
+    </div>
+    <div id="content2">
+        X X X X X
+        X X X X X
+        X X X X X
+        X X X X X
+        X X X X X
     </div>
 </div>
 
index b18d682..08699a1 100644 (file)
@@ -7,6 +7,7 @@
             width: 200px;
             position: absolute;
             top: 100px;
+            color: red;
         }
 
         #outside {
             width: 200px;
             position: absolute;
             top: 0px;
+            color: green;
         }
 
         body {
             margin-top: 0;
+            font-size: 20px;
+            font-family: Ahem;
+            line-height: 20px;
         }
 
         #description {
             position: absolute;
             top: 200px;
         }
+
+        h1 {
+            line-height: 50px;
+        }
     </style>
 </head>
-<body onload="selectContentByRange(100, 10, 100, 110);">
-    <div id="region">inside region inside region inside region inside region</div>
-    <div id="outside">outside region outside region outside region outside region</div>
+<body onload="selectContentByRange(100, 50, 100, 150);">
+    <div id="region">
+        X X X X X
+        X X X X X
+        X X X X X
+        X X X X X
+        X X X X XX
+    </div>
+    <div id="outside">
+        X X X X X
+        X X X X X
+        X X X X X
+        X X X X X
+        X X X X X
+    </div>
     <div id="description">
         <h1><a href="https://bugs.webkit.org/show_bug.cgi?id=121501">Bug #121501 - [CSS Regions] Layout Test for selection direction</a></h1>
-        <p>Selection is based in DOM tree, so if you select text from "outside region" to "inside region" the highlighted area is exactly the opposite to what the user is actually selecting.</p>
+        <p>Selection is based in DOM tree, so if you select text from "green" to "red" the highlighted area is exactly the opposite to what the user is actually selecting.</p>
     </div>
 </body>
 </html>
index 5c702d1..98f084d 100644 (file)
@@ -4,6 +4,7 @@
     <style>
         #source {
             -webkit-flow-into: content;
+            color: red;
         }
 
         #region {
         #outside {
             height: 100px;
             width: 200px;
+            color: green;
+            float: left;
         }
 
         body {
             margin-top: 0;
+            font-size: 20px;
+            font-family: Ahem;
+            line-height: 20px;
         }
 
         #description {
             width: 600px;
         }
+
+        h1 {
+            line-height: 50px;
+        }
+
+        .clear {
+            clear: both;
+        }
     </style>
 </head>
-<body onload="selectContentByRange(100, 10, 100, 110);">
-    <div id="source">inside region inside region inside region inside region</div>
-    <div id="outside">outside region outside region outside region outside region</div>
+<body onload="selectContentByRange(100, 50, 100, 150);">
+    <div id="source">
+        X X X X X
+        X X X X X
+        X X X X X
+        X X X X X
+        X X X X XX
+    </div>
+    <div id="outside">
+        X X X X X
+        X X X X X
+        X X X X X
+        X X X X X
+        X X X X X
+    </div>
+    <div class="clear"></div>
     <div id="region"></div>
     <div id="description">
         <h1><a href="https://bugs.webkit.org/show_bug.cgi?id=121501">Bug #121501 - [CSS Regions] Layout Test for selection direction</a></h1>
-        <p>Selection is based in DOM tree, so if you select text from "outside region" to "inside region" the highlighted area is exactly the opposite to what the user is actually selecting.</p>
+        <p>Selection is based in DOM tree, so if you select text from "green" to "red" the highlighted area is exactly the opposite to what the user is actually selecting.</p>
     </div>
 </body>
 </html>
index ef2daca..2064ee0 100644 (file)
@@ -2340,6 +2340,7 @@ set(WebCore_SOURCES
     rendering/RenderVTTCue.cpp
     rendering/RenderWidget.cpp
     rendering/RootInlineBox.cpp
+    rendering/SelectionSubtreeRoot.cpp
     rendering/ScrollBehavior.cpp
     rendering/SimpleLineLayout.cpp
     rendering/SimpleLineLayoutFunctions.cpp
index 86ea83e..8b97df0 100644 (file)
@@ -1,3 +1,64 @@
+2014-04-22  Manuel Rego Casasnovas  <rego@igalia.com>
+
+        [CSS Regions] Selection highlight doesn't match DOM selection
+        https://bugs.webkit.org/show_bug.cgi?id=131511
+
+        Reviewed by David Hyatt.
+
+        This patch implements a subtrees approach to fix selection interaction in CSS Regions.
+
+        The idea is to divide the Render tree in subtrees. One subtree will be the RenderView (which is always present),
+        then for each RenderNamedFlowThread (which are children of RenderView) we will have an extra subtree.
+
+        For each subtree it determines the start and end positions according to the DOM tree. So, every subtree will
+        always have a start and end position, and the selection algorithm will be able to reach the end from the start
+        without problems (this allows us to remove the changes introduced in r155058).
+
+        Then selection related methods in RenderView are adapted to ensure that they are called for each subtree. Making
+        the selection highlight to match DOM selection as expected.
+
+        Test: fast/regions/selection/selecting-text-including-region.html
+
+        * CMakeLists.txt: Add new class SelectionSubtreeRoot to build file.
+        * WebCore.vcxproj/WebCore.vcxproj: Ditto.
+        * WebCore.vcxproj/WebCore.vcxproj.filters: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * rendering/RenderNamedFlowThread.h: Inherit from SelectionSubtreeRoot.
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::selectionRoot): New method to return the RenderNamedFlowThread if any or the RenderView
+        otherwise.
+        (WebCore::RenderObject::selectionStartEnd): If it's inside a RenderNamedFlowThread use specific method instead
+        of the RenderView's one.
+        * rendering/RenderObject.h: Add new method signature.
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::selectionBounds): Adapt method to subtrees approach.
+        (WebCore::RenderView::subtreeSelectionBounds): Modify previous method in order to use SelectionSubtreeRoot
+        objects.
+        (WebCore::RenderView::repaintSelection): Adapt method to subtrees approach.
+        (WebCore::RenderView::repaintSubtreeSelection): Modify previous method in order to use SelectionSubtreeRoot
+        objects.
+        (getNextOrPrevRenderObjectBasedOnDirection): Deleted method from r155058 as it is not needed anymore. Each
+        subtree will have start and end positions, so the selection algorithm will always find the end.
+        (WebCore::RenderView::setSelection): Adapt method to subtrees approach.
+        (WebCore::RenderView::splitSelectionBetweenSubtrees): Determine start and end positions for each subtree and
+        call setSubtreeSelection().
+        (WebCore::RenderView::setSubtreeSelection): Modify previous method in order to use SelectionSubtreeRoot objects.
+        * rendering/RenderView.h: Inherit from SelectionSubtreeRoot. Add signature for new helper methods receiving
+        SelectionSubtreeRoot objects.
+        * rendering/SelectionSubtreeRoot.cpp: Added.
+        (WebCore::SelectionSubtreeRoot::SelectionSubtreeRoot):
+        (WebCore::SelectionSubtreeRoot::selectionStartEndPositions):
+        * rendering/SelectionSubtreeRoot.h: Added. New class to identify root elements for the subtrees. With some basic
+        attributes and methods to store the start and end positions and offsets.
+        (WebCore::SelectionSubtreeRoot::selectionStart):
+        (WebCore::SelectionSubtreeRoot::selectionStartPos):
+        (WebCore::SelectionSubtreeRoot::selectionEnd):
+        (WebCore::SelectionSubtreeRoot::selectionEndPos):
+        (WebCore::SelectionSubtreeRoot::setSelectionStart):
+        (WebCore::SelectionSubtreeRoot::setSelectionStartPos):
+        (WebCore::SelectionSubtreeRoot::setSelectionEnd):
+        (WebCore::SelectionSubtreeRoot::setSelectionEndPos):
+
 2014-04-21  Brent Fulgham  <bfulgham@apple.com>
 
         [Mac] Follow-up: After a horizontal overflow scroll with a mechanical wheel mouse, vertical scrolling no longer works
index bd7ddcc..387746c 100644 (file)
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="..\rendering\SelectionSubtreeRoot.cpp" />
     <ClCompile Include="..\rendering\SimpleLineLayout.cpp" />
     <ClCompile Include="..\rendering\SimpleLineLayoutFunctions.cpp" />
     <ClCompile Include="..\rendering\TextPaintStyle.cpp" />
     <ClInclude Include="..\rendering\RenderWidget.h" />
     <ClInclude Include="..\rendering\RootInlineBox.h" />
     <ClInclude Include="..\rendering\ScrollBehavior.h" />
+    <ClInclude Include="..\rendering\SelectionSubtreeRoot.h" />
     <ClInclude Include="..\rendering\SimpleLineLayout.h" />
     <ClInclude Include="..\rendering\SimpleLineLayoutFunctions.h" />
     <ClInclude Include="..\rendering\SimpleLineLayoutResolver.h" />
index 1d7b6cd..a7319f6 100644 (file)
     <ClCompile Include="..\platform\graphics\cairo\TiledBackingStoreBackendCairo.cpp">
       <Filter>platform\graphics\cairo</Filter>
     </ClCompile>
+    <ClCompile Include="..\rendering\SelectionSubtreeRoot.cpp">
+      <Filter>rendering</Filter>
+    </ClCompile>
     <ClCompile Include="..\rendering\SimpleLineLayout.cpp">
       <Filter>rendering</Filter>
     </ClCompile>
     <ClInclude Include="..\rendering\SimpleLineLayoutResolver.h">
       <Filter>rendering</Filter>
     </ClInclude>
+    <ClInclude Include="..\rendering\SelectionSubtreeRoot.h">
+      <Filter>rendering</Filter>
+    </ClInclude>
     <ClInclude Include="..\rendering\SimpleLineLayout.h">
       <Filter>rendering</Filter>
     </ClInclude>
index 5a9c169..63658fe 100644 (file)
                CDC8B5AD1804AE5D0016E685 /* SourceBufferPrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC8B5AC1804AE5D0016E685 /* SourceBufferPrivateClient.h */; };
                CDCA82961679100F00875714 /* TextTrackRepresentationIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDCA82941679100F00875714 /* TextTrackRepresentationIOS.mm */; };
                CDCA98EB18B2C8EB00C12FF9 /* CDMPrivateMediaPlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCA98EA18B2C8EB00C12FF9 /* CDMPrivateMediaPlayer.cpp */; };
+               CDCFABBD18C0AF78006F8450 /* SelectionSubtreeRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = CDCFABBB18C0AE31006F8450 /* SelectionSubtreeRoot.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               CDCFABBE18C0AF84006F8450 /* SelectionSubtreeRoot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCFABBC18C0AF19006F8450 /* SelectionSubtreeRoot.cpp */; };
                CDD525D7145B6DD0008D204D /* JSHTMLMediaElementCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF65CCC145B6AFE00C4C7AA /* JSHTMLMediaElementCustom.cpp */; };
                CDD7089618359F6F002B3DC6 /* SampleMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDD7089418359F6E002B3DC6 /* SampleMap.cpp */; };
                CDD7089718359F6F002B3DC6 /* SampleMap.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD7089518359F6F002B3DC6 /* SampleMap.h */; };
                CDCA98E918B2C8D000C12FF9 /* CDMPrivateMediaPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMPrivateMediaPlayer.h; sourceTree = "<group>"; };
                CDCA98EA18B2C8EB00C12FF9 /* CDMPrivateMediaPlayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDMPrivateMediaPlayer.cpp; sourceTree = "<group>"; };
                CDCE5CD014633BC900D47CCA /* EventTargetFactory.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EventTargetFactory.in; sourceTree = "<group>"; };
+               CDCFABBB18C0AE31006F8450 /* SelectionSubtreeRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionSubtreeRoot.h; sourceTree = "<group>"; };
+               CDCFABBC18C0AF19006F8450 /* SelectionSubtreeRoot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionSubtreeRoot.cpp; sourceTree = "<group>"; };
                CDD1E525167BA56400CE820B /* TextTrackRepresentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextTrackRepresentation.h; sourceTree = "<group>"; };
                CDD7089418359F6E002B3DC6 /* SampleMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SampleMap.cpp; sourceTree = "<group>"; };
                CDD7089518359F6F002B3DC6 /* SampleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SampleMap.h; sourceTree = "<group>"; };
                                A8CFF5DA0A155A05000A4234 /* RootInlineBox.h */,
                                5D925B650F64D4DD00B847F0 /* ScrollBehavior.cpp */,
                                5D925B660F64D4DD00B847F0 /* ScrollBehavior.h */,
+                               CDCFABBC18C0AF19006F8450 /* SelectionSubtreeRoot.cpp */,
+                               CDCFABBB18C0AE31006F8450 /* SelectionSubtreeRoot.h */,
                                E48944A0180B57D800F165D8 /* SimpleLineLayout.cpp */,
                                E48944A1180B57D800F165D8 /* SimpleLineLayout.h */,
                                E4E9B11A18145692003ACCDF /* SimpleLineLayoutFunctions.cpp */,
                                2D3A0E3613A7D76100E85AF0 /* SVGParsingError.h in Headers */,
                                A10DBF4718F92317000D70C6 /* QuickLookHandleClient.h in Headers */,
                                84C6784D1214814700A92902 /* SVGPathBlender.h in Headers */,
+                               CDCFABBD18C0AF78006F8450 /* SelectionSubtreeRoot.h in Headers */,
                                8476C9EB11DF6A2900555B02 /* SVGPathBuilder.h in Headers */,
                                8419D2A7120D92D000141F8F /* SVGPathByteStream.h in Headers */,
                                8419D2A9120D92D000141F8F /* SVGPathByteStreamBuilder.h in Headers */,
                                BCE1C43B0D9830D3003B02F2 /* JSLocation.cpp in Sources */,
                                BCE1C4400D9830F4003B02F2 /* JSLocationCustom.cpp in Sources */,
                                8FAC774D119872CB0015AE94 /* JSMainThreadExecState.cpp in Sources */,
+                               CDCFABBE18C0AF84006F8450 /* SelectionSubtreeRoot.cpp in Sources */,
                                CD27F6E51457685A0078207D /* JSMediaController.cpp in Sources */,
                                CDAB6D2D17C814EE00C60B34 /* JSMediaControlsHost.cpp in Sources */,
                                FD23A12513F5FA5900F67001 /* JSMediaElementAudioSourceNode.cpp in Sources */,
index a905e5a..d6b702a 100644 (file)
@@ -28,6 +28,7 @@
 #define RenderNamedFlowThread_h
 
 #include "RenderFlowThread.h"
+#include "SelectionSubtreeRoot.h"
 #include "Timer.h"
 #include <wtf/HashCountedSet.h>
 #include <wtf/ListHashSet.h>
@@ -43,7 +44,7 @@ typedef ListHashSet<RenderNamedFlowThread*> RenderNamedFlowThreadList;
 typedef HashCountedSet<RenderNamedFlowThread*> RenderNamedFlowThreadCountedSet;
 typedef ListHashSet<Element*> NamedFlowContentElements;
 
-class RenderNamedFlowThread final : public RenderFlowThread {
+class RenderNamedFlowThread final : public RenderFlowThread, public SelectionSubtreeRoot {
 public:
     RenderNamedFlowThread(Document&, PassRef<RenderStyle>, PassRef<WebKitNamedFlow>);
     virtual ~RenderNamedFlowThread();
index f13bb13..a00307c 100644 (file)
@@ -1520,9 +1520,18 @@ Color RenderObject::selectionEmphasisMarkColor() const
     return selectionColor(CSSPropertyWebkitTextEmphasisColor);
 }
 
+SelectionSubtreeRoot& RenderObject::selectionRoot() const
+{
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (flowThread && flowThread->isRenderNamedFlowThread())
+        return *toRenderNamedFlowThread(flowThread);
+
+    return view();
+}
+
 void RenderObject::selectionStartEnd(int& spos, int& epos) const
 {
-    view().selectionStartEnd(spos, epos);
+    selectionRoot().selectionStartEndPositions(spos, epos);
 }
 
 void RenderObject::handleDynamicFloatPositionChange()
index 730477e..ca8a6de 100644 (file)
@@ -60,6 +60,7 @@ class RenderLayer;
 class RenderLayerModelObject;
 class RenderNamedFlowThread;
 class RenderTheme;
+class SelectionSubtreeRoot;
 class TransformState;
 class VisiblePosition;
 #if PLATFORM(IOS)
@@ -850,6 +851,7 @@ public:
     virtual void imageChanged(CachedImage*, const IntRect* = 0) override;
     virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) { }
 
+    SelectionSubtreeRoot& selectionRoot() const;
     void selectionStartEnd(int& spos, int& epos) const;
     
     void removeFromParent();
index 985870a..700cec0 100644 (file)
@@ -35,6 +35,7 @@
 #include "HTMLIFrameElement.h"
 #include "HitTestResult.h"
 #include "ImageQualityController.h"
+#include "NodeTraversal.h"
 #include "Page.h"
 #include "RenderGeometryMap.h"
 #include "RenderIterator.h"
@@ -660,13 +661,27 @@ static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset
 
 IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
 {
+    LayoutRect selRect = subtreeSelectionBounds(*this, clipToVisibleContent);
+
+    if (m_flowThreadController) {
+        for (auto* namedFlowThread : *m_flowThreadController->renderNamedFlowThreadList()) {
+            LayoutRect currRect = subtreeSelectionBounds(*namedFlowThread, clipToVisibleContent);
+            selRect.unite(currRect);
+        }
+    }
+
+    return pixelSnappedIntRect(selRect);
+}
+
+LayoutRect RenderView::subtreeSelectionBounds(const SelectionSubtreeRoot& root, bool clipToVisibleContent) const
+{
     typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> SelectionMap;
     SelectionMap selectedObjects;
 
-    RenderObject* os = m_selectionStart;
-    RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
+    RenderObject* os = root.selectionStart();
+    RenderObject* stop = rendererAfterPosition(root.selectionEnd(), root.selectionEndPos());
     while (os && os != stop) {
-        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
+        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.
             selectedObjects.set(os, std::make_unique<RenderSelectionInfo>(os, clipToVisibleContent));
             RenderBlock* cb = os->containingBlock();
@@ -695,16 +710,26 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
         }
         selRect.unite(currRect);
     }
-    return pixelSnappedIntRect(selRect);
+    return selRect;
 }
 
 void RenderView::repaintSelection() const
 {
+    repaintSubtreeSelection(*this);
+
+    if (m_flowThreadController) {
+        for (auto* namedFlowThread : *m_flowThreadController->renderNamedFlowThreadList())
+            repaintSubtreeSelection(*namedFlowThread);
+    }
+}
+
+void RenderView::repaintSubtreeSelection(const SelectionSubtreeRoot& root) const
+{
     HashSet<RenderBlock*> processedBlocks;
 
-    RenderObject* end = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
-    for (RenderObject* o = m_selectionStart; o && o != end; o = o->nextInPreOrder()) {
-        if (!o->canBeSelectionLeaf() && o != m_selectionStart && o != m_selectionEnd)
+    RenderObject* end = rendererAfterPosition(root.selectionEnd(), root.selectionEndPos());
+    for (RenderObject* o = root.selectionStart(); o && o != end; o = o->nextInPreOrder()) {
+        if (!o->canBeSelectionLeaf() && o != root.selectionStart() && o != root.selectionEnd())
             continue;
         if (o->selectionState() == SelectionNone)
             continue;
@@ -733,27 +758,6 @@ void RenderView::setMaximalOutlineSize(int o)
     }
 }
 
-// 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.
@@ -768,10 +772,94 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
         m_selectionEnd == end && m_selectionEndPos == endPos && !caretChanged)
         return;
 
+    // Set global positions for new selection.
+    m_selectionStart = start;
+    m_selectionStartPos = startPos;
+    m_selectionEnd = end;
+    m_selectionEndPos = endPos;
+
+    // If there is no RenderNamedFlowThreads we follow the regular selection.
+    if (!hasRenderNamedFlowThreads()) {
+        setSubtreeSelection(*this, start, startPos, end, endPos, blockRepaintMode);
+        return;
+    }
+
+    splitSelectionBetweenSubtrees(start, startPos, end, endPos, blockRepaintMode);
+}
+
+void RenderView::splitSelectionBetweenSubtrees(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
+{
+    // Get ranges.
+    typedef HashMap<SelectionSubtreeRoot*, RefPtr<Range> > RenderSubtreesMap;
+    RenderSubtreesMap renderSubtreesMap;
+
+    // Initialize map for RenderView and all RenderNamedFlowThreads.
+    renderSubtreesMap.set(this, nullptr);
+    for (auto* namedFlowThread : *flowThreadController().renderNamedFlowThreadList())
+        renderSubtreesMap.set(namedFlowThread, nullptr);
+
+    if (start && end) {
+        RefPtr<Range> initialRange = Range::create(document(), start->node(), startPos, end->node(), endPos);
+
+        Node* startNode = initialRange->startContainer();
+        Node* endNode = initialRange->endContainer();
+        Node* stopNode = initialRange->pastLastNode();
+
+        for (Node* node = startNode; node != stopNode; node = NodeTraversal::next(node)) {
+            RenderObject* renderer = node->renderer();
+            if (!renderer || !renderer->canBeSelectionLeaf())
+                continue;
+
+            SelectionSubtreeRoot& root = renderer->selectionRoot();
+            RefPtr<Range> range = renderSubtreesMap.get(&root);
+            if (!range) {
+                range = Range::create(document());
+
+                if (node == startNode)
+                    range->setStart(node, startPos);
+                else
+                    range->setStart(node, 0);
+
+                renderSubtreesMap.set(&root, range);
+            }
+
+            if (node == endNode)
+                range->setEnd(node, endPos);
+            else
+                range->setEnd(node, node->offsetInCharacters() ? node->maxCharacterOffset() : node->childNodeCount());
+        }
+    }
+
+    for (RenderSubtreesMap::iterator i = renderSubtreesMap.begin(); i != renderSubtreesMap.end(); ++i) {
+        RefPtr<Range> range = i->value;
+
+        RenderObject* newStart;
+        int newStartPos;
+        RenderObject* newEnd;
+        int newEndPos;
+
+        if (range) {
+            newStart = range->startContainer()->renderer();
+            newStartPos = range->startOffset();
+            newEnd = range->endContainer()->renderer();
+            newEndPos = range->endOffset();
+        } else {
+            newStart = 0;
+            newStartPos = -1;
+            newEnd = 0;
+            newEndPos = -1;
+        }
+
+        setSubtreeSelection(*i->key, newStart, newStartPos, newEnd, newEndPos, blockRepaintMode);
+    }
+}
+
+void RenderView::setSubtreeSelection(SelectionSubtreeRoot& root, RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
+{
     // Record the old selected objects.  These will be used later
     // when we compare against the new selected objects.
-    int oldStartPos = m_selectionStartPos;
-    int oldEndPos = m_selectionEndPos;
+    int oldStartPos = root.selectionStartPos();
+    int oldEndPos = root.selectionEndPos();
 
     // Objects each have a single selection rect to examine.
     typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> SelectedObjectMap;
@@ -785,12 +873,11 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
     SelectedBlockMap oldSelectedBlocks;
     SelectedBlockMap newSelectedBlocks;
 
-    RenderObject* os = m_selectionStart;
-    RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
-    bool exploringBackwards = false;
-    bool continueExploring = os && (os != stop);
-    while (continueExploring) {
-        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
+    RenderObject* os = root.selectionStart();
+    RenderObject* stop = rendererAfterPosition(root.selectionEnd(), root.selectionEndPos());
+    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.
             oldSelectedObjects.set(os, std::make_unique<RenderSelectionInfo>(os, true));
             if (blockRepaintMode == RepaintNewXOROld) {
@@ -805,7 +892,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
             }
         }
 
-        os = getNextOrPrevRenderObjectBasedOnDirection(os, stop, continueExploring, exploringBackwards);
+        os = os->nextInPreOrder();
     }
 
     // Now clear the selection.
@@ -814,12 +901,12 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
         i->key->setSelectionStateIfNeeded(SelectionNone);
 
     // set selection start and end
-    m_selectionStart = start;
-    m_selectionStartPos = startPos;
-    m_selectionEnd = end;
-    m_selectionEndPos = endPos;
+    root.setSelectionStart(start);
+    root.setSelectionStartPos(startPos);
+    root.setSelectionEnd(end);
+    root.setSelectionEndPos(endPos);
 
-    // Update the selection status of all objects between m_selectionStart and m_selectionEnd
+    // Update the selection status of all objects between selectionStart and selectionEnd
     if (start && start == end)
         start->setSelectionStateIfNeeded(SelectionBoth);
     else {
@@ -844,9 +931,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
     // 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;
-    exploringBackwards = false;
-    continueExploring = o && (o != stop);
-    while (continueExploring) {
+    while (o && o != stop) {
         if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
             newSelectedObjects.set(o, std::make_unique<RenderSelectionInfo>(o, true));
             RenderBlock* cb = o->containingBlock();
@@ -859,7 +944,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
             }
         }
 
-        o = getNextOrPrevRenderObjectBasedOnDirection(o, stop, continueExploring, exploringBackwards);
+        o = o->nextInPreOrder();
     }
 
     if (blockRepaintMode == RepaintNothing)
@@ -870,9 +955,9 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
         RenderObject* obj = i->key;
         RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
         RenderSelectionInfo* oldInfo = i->value.get();
-        if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
-            (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
-            (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
+        if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state()
+            || (root.selectionStart() == obj && oldStartPos != root.selectionStartPos())
+            || (root.selectionEnd() == obj && oldEndPos != root.selectionEndPos())) {
             oldInfo->repaint();
             if (newInfo) {
                 newInfo->repaint();
@@ -921,12 +1006,6 @@ void RenderView::clearSelection()
     setSelection(0, -1, 0, -1, RepaintNewMinusOld);
 }
 
-void RenderView::selectionStartEnd(int& startPos, int& endPos) const
-{
-    startPos = m_selectionStartPos;
-    endPos = m_selectionEndPos;
-}
-
 bool RenderView::printing() const
 {
     return document().printing();
index 4ba7f19..6bb3809 100644 (file)
 #include "PODFreeListArena.h"
 #include "Region.h"
 #include "RenderBlockFlow.h"
+#include "SelectionSubtreeRoot.h"
 #include <memory>
 #include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
 
 namespace WebCore {
 
@@ -37,7 +39,7 @@ class ImageQualityController;
 class RenderLayerCompositor;
 class RenderQuote;
 
-class RenderView final : public RenderBlockFlow {
+class RenderView final : public RenderBlockFlow, public SelectionSubtreeRoot {
 public:
     RenderView(Document&, PassRef<RenderStyle>);
     virtual ~RenderView();
@@ -86,7 +88,6 @@ public:
     RenderObject* selectionStart() const { return m_selectionStart; }
     RenderObject* selectionEnd() const { return m_selectionEnd; }
     IntRect selectionBounds(bool clipToVisibleContent = true) const;
-    void selectionStartEnd(int& startPos, int& endPos) const;
     void repaintSelection() const;
 
     bool printing() const;
@@ -296,6 +297,11 @@ private:
     friend class LayoutStateMaintainer;
     friend class LayoutStateDisabler;
 
+    void splitSelectionBetweenSubtrees(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode);
+    void setSubtreeSelection(SelectionSubtreeRoot&, RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode);
+    LayoutRect subtreeSelectionBounds(const SelectionSubtreeRoot&, bool clipToVisibleContent = true) const;
+    void repaintSubtreeSelection(const SelectionSubtreeRoot&) const;
+
 private:
     FrameView& m_frameView;
 
diff --git a/Source/WebCore/rendering/SelectionSubtreeRoot.cpp b/Source/WebCore/rendering/SelectionSubtreeRoot.cpp
new file mode 100644 (file)
index 0000000..c9a9071
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SelectionSubtreeRoot.h"
+
+namespace WebCore {
+
+SelectionSubtreeRoot::SelectionSubtreeRoot()
+    : m_selectionStart(nullptr)
+    , m_selectionStartPos(-1)
+    , m_selectionEnd(nullptr)
+    , m_selectionEndPos(-1)
+{
+}
+
+void SelectionSubtreeRoot::selectionStartEndPositions(int& startPos, int& endPos) const
+{
+    startPos = m_selectionStartPos;
+    endPos = m_selectionEndPos;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/SelectionSubtreeRoot.h b/Source/WebCore/rendering/SelectionSubtreeRoot.h
new file mode 100644 (file)
index 0000000..061d4ed
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef SelectionSubtreeRoot_h
+#define SelectionSubtreeRoot_h
+
+#include "RenderObject.h"
+
+namespace WebCore {
+
+class SelectionSubtreeRoot {
+public:
+
+    SelectionSubtreeRoot();
+
+    RenderObject* selectionStart() const { return m_selectionStart; }
+    int selectionStartPos() const { return m_selectionStartPos; }
+    RenderObject* selectionEnd() const { return m_selectionEnd; }
+    int selectionEndPos() const { return m_selectionEndPos; }
+
+    void setSelectionStart(RenderObject* selectionStart) { m_selectionStart = selectionStart; }
+    void setSelectionStartPos(int selectionStartPos) { m_selectionStartPos = selectionStartPos; }
+    void setSelectionEnd(RenderObject* selectionEnd) { m_selectionEnd = selectionEnd; }
+    void setSelectionEndPos(int selectionEndPos) { m_selectionEndPos = selectionEndPos; }
+
+    void selectionStartEndPositions(int& startPos, int& endPos) const;
+
+private:
+
+    RenderObject* m_selectionStart;
+    int m_selectionStartPos;
+    RenderObject* m_selectionEnd;
+    int m_selectionEndPos;
+
+};
+
+} // namespace WebCore
+
+#endif // SelectionSubtreeRoot_h