Diff
Modified: trunk/LayoutTests/ChangeLog (254784 => 254785)
--- trunk/LayoutTests/ChangeLog 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/LayoutTests/ChangeLog 2020-01-18 02:13:16 UTC (rev 254785)
@@ -1,3 +1,16 @@
+2020-01-17 Megan Gardner <[email protected]>
+
+ Use Visible Position to calculate Positions for highlights
+ https://bugs.webkit.org/show_bug.cgi?id=206314
+
+ Reviewed by Ryosuke Niwa.
+
+ * highlight/resources/highlight-frame.html:
+ * http/wpt/css/css-highlight-api/highlight-text-across-elements.html:
+ * http/wpt/css/css-highlight-api/highlight-text-cascade.html:
+ * http/wpt/css/css-highlight-api/highlight-text-replace.html:
+ * http/wpt/css/css-highlight-api/highlight-text.html:
+
2020-01-17 Canhai Chen <[email protected]>
AX: Unable to use AccessibilityObject::replaceTextInRange to insert text at first time when the text fields are empty
Modified: trunk/LayoutTests/highlight/resources/highlight-frame.html (254784 => 254785)
--- trunk/LayoutTests/highlight/resources/highlight-frame.html 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/LayoutTests/highlight/resources/highlight-frame.html 2020-01-18 02:13:16 UTC (rev 254785)
@@ -13,6 +13,6 @@
<script>
let highlight = document.getElementById('highlight');
-let highlightRangeGroup = new HighlightRangeGroup(new StaticRange({startContainer: highlight, startOffset: 0, endContainer: highlight, endOffset: 4}));
+let highlightRangeGroup = new HighlightRangeGroup(new StaticRange({startContainer: highlight.childNodes[0], startOffset: 0, endContainer: highlight.childNodes[0], endOffset: 4}));
CSS.highlights.set("example", highlightRangeGroup);
</script>
Modified: trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text-across-elements.html (254784 => 254785)
--- trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text-across-elements.html 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text-across-elements.html 2020-01-18 02:13:16 UTC (rev 254785)
@@ -34,12 +34,12 @@
let textElement3 = document.getElementById('text3');
let textElement4 = document.getElementById('text4');
let textElement5 = document.getElementById('text5');
- let highlightRangeGroup1 = new HighlightRangeGroup(new StaticRange({startContainer: textElement1, startOffset: 4, endContainer: textElement1, endOffset: 7}));
+ let highlightRangeGroup1 = new HighlightRangeGroup(new StaticRange({startContainer: textElement1.childNodes[0], startOffset: 4, endContainer: textElement1.childNodes[0], endOffset: 7}));
- let highlightRangeGroup2 = new HighlightRangeGroup(new StaticRange({startContainer: textElement1, startOffset: 10, endContainer: textElement2, endOffset: 4}));
- highlightRangeGroup2.add(new StaticRange({startContainer: textElement2, startOffset: 10, endContainer: textElement3, endOffset: 5}));
+ let highlightRangeGroup2 = new HighlightRangeGroup(new StaticRange({startContainer: textElement1.childNodes[0], startOffset: 10, endContainer: textElement2.childNodes[0], endOffset: 4}));
+ highlightRangeGroup2.add(new StaticRange({startContainer: textElement2.childNodes[0], startOffset: 10, endContainer: textElement3.childNodes[0], endOffset: 5}));
- let highlightRangeGroup3 = new HighlightRangeGroup(new StaticRange({startContainer: textElement3, startOffset: 10, endContainer: textElement5, endOffset: 12}));
+ let highlightRangeGroup3 = new HighlightRangeGroup(new StaticRange({startContainer: textElement3.childNodes[0], startOffset: 10, endContainer: textElement5.childNodes[0], endOffset: 12}));
CSS.highlights.set("example-highlight1", highlightRangeGroup1);
CSS.highlights.set("example-highlight2", highlightRangeGroup2);
Modified: trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text-cascade.html (254784 => 254785)
--- trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text-cascade.html 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text-cascade.html 2020-01-18 02:13:16 UTC (rev 254785)
@@ -26,8 +26,8 @@
let textElement1 = document.getElementById('text1');
let textElement2 = document.getElementById('text2');
let textElement3 = document.getElementById('text3');
- let highlightRangeGroup = new HighlightRangeGroup(new StaticRange({startContainer: textElement1, startOffset: 0, endContainer: textElement1, endOffset: 3}));
- highlightRangeGroup.add(new StaticRange({startContainer: textElement2, startOffset: 5, endContainer: textElement2, endOffset: 9}));
+ let highlightRangeGroup = new HighlightRangeGroup(new StaticRange({startContainer: textElement1.childNodes[0], startOffset: 0, endContainer: textElement1.childNodes[0], endOffset: 3}));
+ highlightRangeGroup.add(new StaticRange({startContainer: textElement2.childNodes[0], startOffset: 5, endContainer: textElement2.childNodes[0], endOffset: 9}));
CSS.highlights.set("example-highlight", highlightRangeGroup);
</script>
Modified: trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text-replace.html (254784 => 254785)
--- trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text-replace.html 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text-replace.html 2020-01-18 02:13:16 UTC (rev 254785)
@@ -18,10 +18,10 @@
<script>
let textElement = document.getElementById('text1');
- let highlightRangeGroup1 = new HighlightRangeGroup(new StaticRange({startContainer: textElement, startOffset: 1, endContainer: textElement, endOffset: 2}));
+ let highlightRangeGroup1 = new HighlightRangeGroup(new StaticRange({startContainer: textElement.childNodes[0], startOffset: 1, endContainer: textElement.childNodes[0], endOffset: 2}));
- let highlightRangeGroup2 = new HighlightRangeGroup(new StaticRange({startContainer: textElement, startOffset: 3, endContainer: textElement, endOffset: 4}));
- highlightRangeGroup2.add(new StaticRange({startContainer: textElement, startOffset: 5, endContainer: textElement, endOffset: 6}));
+ let highlightRangeGroup2 = new HighlightRangeGroup(new StaticRange({startContainer: textElement.childNodes[0], startOffset: 3, endContainer: textElement.childNodes[0], endOffset: 4}));
+ highlightRangeGroup2.add(new StaticRange({startContainer: textElement.childNodes[0], startOffset: 5, endContainer: textElement.childNodes[0], endOffset: 6}));
CSS.highlights.set("example-highlight", highlightRangeGroup1);
CSS.highlights.set("example-highlight", highlightRangeGroup2);
Modified: trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text.html (254784 => 254785)
--- trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text.html 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/LayoutTests/http/wpt/css/css-highlight-api/highlight-text.html 2020-01-18 02:13:16 UTC (rev 254785)
@@ -26,14 +26,14 @@
<script>
let textElement = document.getElementById('text1');
- let highlightRangeGroup1 = new HighlightRangeGroup(new StaticRange({startContainer: textElement, startOffset: 1, endContainer: textElement, endOffset: 2}));
+ let highlightRangeGroup1 = new HighlightRangeGroup(new StaticRange({startContainer: textElement.childNodes[0], startOffset: 1, endContainer: textElement.childNodes[0], endOffset: 2}));
- let highlightRangeGroup2 = new HighlightRangeGroup(new StaticRange({startContainer: textElement, startOffset: 3, endContainer: textElement, endOffset: 4}));
- highlightRangeGroup2.add(new StaticRange({startContainer: textElement, startOffset: 5, endContainer: textElement, endOffset: 6}));
+ let highlightRangeGroup2 = new HighlightRangeGroup(new StaticRange({startContainer: textElement.childNodes[0], startOffset: 3, endContainer: textElement.childNodes[0], endOffset: 4}));
+ highlightRangeGroup2.add(new StaticRange({startContainer: textElement.childNodes[0], startOffset: 5, endContainer: textElement.childNodes[0], endOffset: 6}));
- let highlightRangeGroup3 = new HighlightRangeGroup(new StaticRange({startContainer: textElement, startOffset: 7, endContainer: textElement, endOffset: 8}));
- highlightRangeGroup3.add(new StaticRange({startContainer: textElement, startOffset: 9, endContainer: textElement, endOffset: 10}));
- highlightRangeGroup3.add(new StaticRange({startContainer: textElement, startOffset: 12, endContainer: textElement, endOffset: 13}));
+ let highlightRangeGroup3 = new HighlightRangeGroup(new StaticRange({startContainer: textElement.childNodes[0], startOffset: 7, endContainer: textElement.childNodes[0], endOffset: 8}));
+ highlightRangeGroup3.add(new StaticRange({startContainer: textElement.childNodes[0], startOffset: 9, endContainer: textElement.childNodes[0], endOffset: 10}));
+ highlightRangeGroup3.add(new StaticRange({startContainer: textElement.childNodes[0], startOffset: 12, endContainer: textElement.childNodes[0], endOffset: 13}));
CSS.highlights.set("example-highlight1", highlightRangeGroup1);
Modified: trunk/Source/WebCore/ChangeLog (254784 => 254785)
--- trunk/Source/WebCore/ChangeLog 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/Source/WebCore/ChangeLog 2020-01-18 02:13:16 UTC (rev 254785)
@@ -1,3 +1,42 @@
+2020-01-17 Megan Gardner <[email protected]>
+
+ Use Visible Position to calculate Positions for highlights
+ https://bugs.webkit.org/show_bug.cgi?id=206314
+
+ Reviewed by Ryosuke Niwa.
+
+ When after layout is complete create a VisibleSelection from and highlight StaticRanges which
+ don't have position data yet. This will make sure that the information is availble when
+ rendering, as Visible Positions and Visible Selections cannot be made while rendering.
+ Also, add the ability to make a VisibleSelection from a Static Range to simplify the code.
+
+ Updated Test:
+ * LayoutTests/http/wpt/css/css-highlight-api/highlight-text-across-elements.html:
+ * LayoutTests/http/wpt/css/css-highlight-api/highlight-text-cascade.html:
+ * LayoutTests/http/wpt/css/css-highlight-api/highlight-text-replace.html:
+ * LayoutTests/http/wpt/css/css-highlight-api/highlight-text.html:
+
+ * Modules/highlight/HighlightRangeGroup.cpp:
+ (WebCore::HighlightRangeGroup::HighlightRangeGroup):
+ (WebCore::HighlightRangeGroup::create):
+ (WebCore::HighlightRangeGroup::initializeSetLike):
+ (WebCore::HighlightRangeGroup::removeFromSetLike):
+ (WebCore::HighlightRangeGroup::clearFromSetLike):
+ (WebCore::HighlightRangeGroup::addToSetLike):
+ * Modules/highlight/HighlightRangeGroup.h:
+ (WebCore::HighlightRangeData::create):
+ (WebCore::HighlightRangeData::HighlightRangeData):
+ (WebCore::HighlightRangeGroup::rangesData const):
+ (WebCore::HighlightRangeGroup::ranges const): Deleted.
+ * Modules/highlight/HighlightRangeGroup.idl:
+ * editing/VisibleSelection.cpp:
+ (WebCore::VisibleSelection::create):
+ * editing/VisibleSelection.h:
+ * rendering/InlineTextBox.cpp:
+ (WebCore::InlineTextBox::collectMarkedTextsForHighlights const):
+ * rendering/SelectionRangeData.cpp:
+ (WebCore::SelectionRangeData::selectionStateForRenderer):
+
2020-01-17 Canhai Chen <[email protected]>
AX: Unable to use AccessibilityObject::replaceTextInRange to insert text at first time when the text fields are empty
Modified: trunk/Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp (254784 => 254785)
--- trunk/Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp 2020-01-18 02:13:16 UTC (rev 254785)
@@ -32,12 +32,14 @@
#include "PropertySetCSSStyleDeclaration.h"
#include "StaticRange.h"
#include "StyleProperties.h"
+#include <wtf/Ref.h>
namespace WebCore {
HighlightRangeGroup::HighlightRangeGroup(Ref<StaticRange>&& range)
{
- m_ranges.append(WTFMove(range));
+ auto myRange = WTFMove(range);
+ addToSetLike(myRange.get());
}
Ref<HighlightRangeGroup> HighlightRangeGroup::create(StaticRange& range)
@@ -47,27 +49,28 @@
void HighlightRangeGroup::initializeSetLike(DOMSetAdapter& set)
{
- for (auto& range : m_ranges)
- set.add<IDLInterface<StaticRange>>(range);
+ for (auto& rangeData : m_rangesData)
+ set.add<IDLInterface<StaticRange>>(rangeData->range);
}
bool HighlightRangeGroup::removeFromSetLike(const StaticRange& range)
{
- return m_ranges.removeFirstMatching([&range](const Ref<StaticRange>& current) {
- return current.get() == range;
+ return m_rangesData.removeFirstMatching([&range](const Ref<HighlightRangeData>& current) {
+ return current.get().range.get() == range;
});
}
void HighlightRangeGroup::clearFromSetLike()
{
- m_ranges.clear();
+ m_rangesData.clear();
}
bool HighlightRangeGroup::addToSetLike(StaticRange& range)
{
- if (notFound != m_ranges.findMatching([&range](const Ref<StaticRange>& current) { return current.get() == range; }))
+ if (notFound != m_rangesData.findMatching([&range](const Ref<HighlightRangeData>& current) { return current.get().range.get() == range; }))
return false;
- m_ranges.append(makeRef(range));
+ m_rangesData.append(HighlightRangeData::create(range));
+
return true;
}
Modified: trunk/Source/WebCore/Modules/highlight/HighlightRangeGroup.h (254784 => 254785)
--- trunk/Source/WebCore/Modules/highlight/HighlightRangeGroup.h 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/Source/WebCore/Modules/highlight/HighlightRangeGroup.h 2020-01-18 02:13:16 UTC (rev 254785)
@@ -26,6 +26,7 @@
#pragma once
#include "ExceptionOr.h"
+#include "Position.h"
#include "StaticRange.h"
#include <wtf/RefCounted.h>
@@ -36,6 +37,23 @@
class StaticRange;
class PropertySetCSSStyleDeclaration;
+struct HighlightRangeData : RefCounted<HighlightRangeData>, public CanMakeWeakPtr<HighlightRangeData> {
+
+ HighlightRangeData(Ref<StaticRange>&& range)
+ : range(WTFMove(range))
+ {
+ }
+
+ static Ref<HighlightRangeData> create(Ref<StaticRange>&& range)
+ {
+ return adoptRef(*new HighlightRangeData(WTFMove(range)));
+ }
+
+ Ref<StaticRange> range;
+ Optional<Position> startPosition;
+ Optional<Position> endPosition;
+};
+
class HighlightRangeGroup : public RefCounted<HighlightRangeGroup> {
public:
static Ref<HighlightRangeGroup> create(StaticRange&);
@@ -45,12 +63,12 @@
bool removeFromSetLike(const StaticRange&);
void initializeSetLike(DOMSetAdapter&);
- const Vector<Ref<StaticRange>>& ranges() const { return m_ranges; }
+ const Vector<Ref<HighlightRangeData>>& rangesData() const { return m_rangesData; }
// FIXME: Add WEBCORE_EXPORT CSSStyleDeclaration& style();
private:
- Vector<Ref<StaticRange>> m_ranges; // TODO: use a HashSet instead of a Vector <rdar://problem/57760614>
+ Vector<Ref<HighlightRangeData>> m_rangesData; // FIXME: use a HashSet instead of a Vector <rdar://problem/57760614>
explicit HighlightRangeGroup(Ref<StaticRange>&&);
};
Modified: trunk/Source/WebCore/dom/Document.cpp (254784 => 254785)
--- trunk/Source/WebCore/dom/Document.cpp 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/Source/WebCore/dom/Document.cpp 2020-01-18 02:13:16 UTC (rev 254785)
@@ -2740,6 +2740,39 @@
return *m_highlightMap;
}
+void Document::updateHighlightPositions()
+{
+ Vector<WeakPtr<HighlightRangeData>> rangesData;
+ if (m_highlightMap) {
+ for (auto& highlight : m_highlightMap->map()) {
+ for (auto& rangeData : highlight.value->rangesData()) {
+ if (rangeData->startPosition && rangeData->endPosition)
+ continue;
+ if (&rangeData->range->startContainer()->treeScope() != &rangeData->range->endContainer()->treeScope())
+ continue;
+ rangesData.append(makeWeakPtr(rangeData.ptr()));
+ }
+ }
+ }
+
+ for (auto& weakRangeData : rangesData) {
+ if (auto* rangeData = weakRangeData.get()) {
+ VisibleSelection visibleSelection(rangeData->range);
+ Position startPosition;
+ Position endPosition;
+ if (!rangeData->startPosition.hasValue())
+ startPosition = visibleSelection.visibleStart().deepEquivalent();
+ if (!rangeData->endPosition.hasValue())
+ endPosition = visibleSelection.visibleEnd().deepEquivalent(); // <MMG> switch to END
+ if (!weakRangeData.get())
+ continue;
+
+ rangeData->startPosition = startPosition;
+ rangeData->endPosition = endPosition;
+ }
+ }
+}
+
ScriptableDocumentParser* Document::scriptableDocumentParser() const
{
return parser() ? parser()->asScriptableDocumentParser() : nullptr;
Modified: trunk/Source/WebCore/dom/Document.h (254784 => 254785)
--- trunk/Source/WebCore/dom/Document.h 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/Source/WebCore/dom/Document.h 2020-01-18 02:13:16 UTC (rev 254785)
@@ -1550,6 +1550,7 @@
TextManipulationController* textManipulationControllerIfExists() { return m_textManipulationController.get(); }
HighlightMap& highlightMap();
+ void updateHighlightPositions();
protected:
enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
Modified: trunk/Source/WebCore/editing/VisibleSelection.cpp (254784 => 254785)
--- trunk/Source/WebCore/editing/VisibleSelection.cpp 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/Source/WebCore/editing/VisibleSelection.cpp 2020-01-18 02:13:16 UTC (rev 254785)
@@ -32,6 +32,7 @@
#include "HTMLInputElement.h"
#include "Settings.h"
#include "ShadowRoot.h"
+#include "StaticRange.h"
#include "TextIterator.h"
#include "VisibleUnits.h"
#include <stdio.h>
@@ -96,6 +97,16 @@
validate();
}
+VisibleSelection::VisibleSelection(const StaticRange& staticRange, EAffinity affinity, bool isDirectional)
+ : m_base(createLegacyEditingPosition(staticRange.startContainer(), staticRange.startOffset()))
+ , m_extent(createLegacyEditingPosition(staticRange.endContainer(), staticRange.endOffset()))
+ , m_affinity(affinity)
+ , m_isDirectional(isDirectional)
+{
+ ASSERT(&staticRange.startContainer()->treeScope() == &staticRange.endContainer()->treeScope());
+ validate();
+}
+
VisibleSelection VisibleSelection::selectionFromContentsOfNode(Node* node)
{
ASSERT(!editingIgnoresContent(*node));
Modified: trunk/Source/WebCore/editing/VisibleSelection.h (254784 => 254785)
--- trunk/Source/WebCore/editing/VisibleSelection.h 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/Source/WebCore/editing/VisibleSelection.h 2020-01-18 02:13:16 UTC (rev 254785)
@@ -31,6 +31,7 @@
namespace WebCore {
class Position;
+class StaticRange;
const EAffinity SEL_DEFAULT_AFFINITY = DOWNSTREAM;
enum SelectionDirection : uint8_t { DirectionForward, DirectionBackward, DirectionRight, DirectionLeft };
@@ -45,6 +46,7 @@
VisibleSelection(const Position&, const Position&, EAffinity = SEL_DEFAULT_AFFINITY, bool isDirectional = false);
WEBCORE_EXPORT VisibleSelection(const Range&, EAffinity = SEL_DEFAULT_AFFINITY, bool isDirectional = false);
+ WEBCORE_EXPORT VisibleSelection(const StaticRange&, EAffinity = SEL_DEFAULT_AFFINITY, bool isDirectional = false);
WEBCORE_EXPORT VisibleSelection(const VisiblePosition&, bool isDirectional = false);
WEBCORE_EXPORT VisibleSelection(const VisiblePosition&, const VisiblePosition&, bool isDirectional = false);
Modified: trunk/Source/WebCore/page/Page.cpp (254784 => 254785)
--- trunk/Source/WebCore/page/Page.cpp 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/Source/WebCore/page/Page.cpp 2020-01-18 02:13:16 UTC (rev 254785)
@@ -1351,6 +1351,10 @@
#endif
layoutIfNeeded();
+
+ forEachDocument([] (Document& document) {
+ document.updateHighlightPositions();
+ });
}
void Page::suspendScriptedAnimations()
Modified: trunk/Source/WebCore/rendering/InlineTextBox.cpp (254784 => 254785)
--- trunk/Source/WebCore/rendering/InlineTextBox.cpp 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/Source/WebCore/rendering/InlineTextBox.cpp 2020-01-18 02:13:16 UTC (rev 254785)
@@ -1043,11 +1043,10 @@
auto renderStyle = parentRenderer.getUncachedPseudoStyle({ PseudoId::Highlight, highlight.key }, &parentStyle);
if (!renderStyle)
continue;
- for (auto& staticRange : highlight.value->ranges()) {
- Position startPos = createLegacyEditingPosition(staticRange->startContainer(), staticRange->startOffset());
- Position endPos = createLegacyEditingPosition(staticRange->endContainer(), staticRange->endOffset());
-
- if (startPos.isNotNull() && endPos.isNotNull()) {
+ for (auto& rangeData : highlight.value->rangesData()) {
+ if (rangeData->startPosition && rangeData->endPosition) {
+ Position startPos = rangeData->startPosition.value();
+ Position endPos = rangeData->endPosition.value();
RenderObject* startRenderer = startPos.deprecatedNode()->renderer();
int startOffset = startPos.deprecatedEditingOffset();
RenderObject* endRenderer = endPos.deprecatedNode()->renderer();
Modified: trunk/Source/WebCore/rendering/SelectionRangeData.cpp (254784 => 254785)
--- trunk/Source/WebCore/rendering/SelectionRangeData.cpp 2020-01-18 02:00:16 UTC (rev 254784)
+++ trunk/Source/WebCore/rendering/SelectionRangeData.cpp 2020-01-18 02:13:16 UTC (rev 254785)
@@ -167,13 +167,13 @@
// Planned fix in a followup: <rdar://problem/58095923>
// https://bugs.webkit.org/show_bug.cgi?id=205529
- if (&renderer == m_selectionContext.start() || renderer.isDescendantOf(m_selectionContext.start())) {
+ if (&renderer == m_selectionContext.start()) {
if (m_selectionContext.start() && m_selectionContext.end() && m_selectionContext.start() == m_selectionContext.end())
return RenderObject::SelectionBoth;
if (m_selectionContext.start())
return RenderObject::SelectionStart;
}
- if (&renderer == m_selectionContext.end() || renderer.isDescendantOf(m_selectionContext.end()))
+ if (&renderer == m_selectionContext.end())
return RenderObject::SelectionEnd;
RenderObject* selectionEnd = nullptr;