Diff
Modified: trunk/Source/WebCore/CMakeLists.txt (222696 => 222697)
--- trunk/Source/WebCore/CMakeLists.txt 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/CMakeLists.txt 2017-10-02 04:46:32 UTC (rev 222697)
@@ -2749,7 +2749,7 @@
rendering/RenderWidget.cpp
rendering/RootInlineBox.cpp
rendering/ScrollAlignment.cpp
- rendering/SelectionSubtreeRoot.cpp
+ rendering/SelectionRangeData.cpp
rendering/SimpleLineLayout.cpp
rendering/SimpleLineLayoutCoverage.cpp
rendering/SimpleLineLayoutFlowContents.cpp
Modified: trunk/Source/WebCore/ChangeLog (222696 => 222697)
--- trunk/Source/WebCore/ChangeLog 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/ChangeLog 2017-10-02 04:46:32 UTC (rev 222697)
@@ -1,3 +1,98 @@
+2017-10-01 Zalan Bujtas <[email protected]>
+
+ RenderView does not need to be a SelectionSubtreeRoot
+ https://bugs.webkit.org/show_bug.cgi?id=177713
+
+ Reviewed by Darin Adler and Antti Koivisto.
+
+ 1. SelectionSubtreeRoot -> SelectionRangeData
+ 2. Move all selection logic from RenderView to SelectionRangeData
+ 3. class RenderView : public SelectionSubtreeRoot -> SelectionRangeData m_selection;
+ 4. Remove redundant code
+ 5. General modernization
+
+ No change in functionality.
+
+ * editing/FrameSelection.cpp:
+ (WebCore::FrameSelection::setNeedsSelectionUpdate):
+ (WebCore::DragCaretController::nodeWillBeRemoved):
+ (WebCore::FrameSelection::respondToNodeModification):
+ (WebCore::FrameSelection::prepareForDestruction):
+ (WebCore::FrameSelection::focusedOrActiveStateChanged):
+ (WebCore::FrameSelection::updateAppearance):
+ (WebCore::FrameSelection::selectionBounds const):
+ * page/FrameView.cpp:
+ (WebCore::FrameView::paintContentsForSnapshot):
+ * platform/DragImage.cpp:
+ (WebCore::ScopedFrameSelectionState::ScopedFrameSelectionState):
+ (WebCore::ScopedFrameSelectionState::~ScopedFrameSelectionState):
+ (WebCore::createDragImageForRange):
+ * rendering/InlineTextBox.cpp:
+ (WebCore::InlineTextBox::selectionState):
+ (WebCore::InlineTextBox::selectionStartEnd const):
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::isSelectionRoot const):
+ * rendering/RenderObject.cpp:
+ (WebCore::RenderObject::isSelectionBorder const):
+ * rendering/RenderObject.h:
+ * rendering/RenderReplaced.cpp:
+ (WebCore::RenderReplaced::isSelected const):
+ * rendering/RenderText.cpp:
+ (WebCore::RenderText::collectSelectionRectsForLineBoxes):
+ * rendering/RenderTextLineBoxes.cpp:
+ (WebCore::RenderTextLineBoxes::setSelectionState):
+ * rendering/RenderView.cpp:
+ (WebCore::RenderView::RenderView):
+ (WebCore::SelectionIterator::SelectionIterator): Deleted.
+ (WebCore::SelectionIterator::current const): Deleted.
+ (WebCore::SelectionIterator::next): Deleted.
+ (WebCore::SelectionIterator::checkForSpanner): Deleted.
+ (WebCore::rendererAfterPosition): Deleted.
+ (WebCore::RenderView::selectionBounds const): Deleted.
+ (WebCore::RenderView::subtreeSelectionBounds const): Deleted.
+ (WebCore::RenderView::repaintSelection const): Deleted.
+ (WebCore::RenderView::repaintSubtreeSelection const): Deleted.
+ (WebCore::RenderView::setSelection): Deleted.
+ (WebCore::isValidObjectForNewSelection): Deleted.
+ (WebCore::RenderView::clearSubtreeSelection const): Deleted.
+ (WebCore::RenderView::applySubtreeSelection): Deleted.
+ (WebCore::RenderView::getSelection const): Deleted.
+ (WebCore::RenderView::clearSelection): Deleted.
+ * rendering/RenderView.h:
+ * rendering/SelectionSubtreeRoot.cpp:
+ (WebCore::rendererAfterPosition):
+ (WebCore::SelectionIterator::SelectionIterator):
+ (WebCore::SelectionIterator::current const):
+ (WebCore::SelectionIterator::next):
+ (WebCore::SelectionIterator::checkForSpanner):
+ (WebCore::SelectionRangeData::SelectionRangeData):
+ (WebCore::SelectionRangeData::set):
+ (WebCore::SelectionRangeData::clear):
+ (WebCore::SelectionRangeData::repaint const):
+ (WebCore::SelectionRangeData::bounds const):
+ (WebCore::SelectionRangeData::collectAndClear const):
+ (WebCore::SelectionRangeData::apply):
+ (WebCore::SelectionRangeData::isValidRendererForNewSelection const):
+ (WebCore::SelectionSubtreeRoot::SelectionSubtreeRoot): Deleted.
+ * rendering/SelectionSubtreeRoot.h:
+ (WebCore::SelectionRangeData::Context::operator== const):
+ (WebCore::SelectionRangeData::get const):
+ (WebCore::SelectionRangeData::start const):
+ (WebCore::SelectionRangeData::end const):
+ (WebCore::SelectionRangeData::startPosition const):
+ (WebCore::SelectionRangeData::endPosition const):
+ (WebCore::SelectionSubtreeRoot::OldSelectionData::OldSelectionData): Deleted.
+ (WebCore::SelectionSubtreeRoot::SelectionSubtreeData::SelectionSubtreeData): Deleted.
+ (WebCore::SelectionSubtreeRoot::SelectionSubtreeData::selectionStart const): Deleted.
+ (WebCore::SelectionSubtreeRoot::SelectionSubtreeData::selectionStartPos const): Deleted.
+ (WebCore::SelectionSubtreeRoot::SelectionSubtreeData::selectionEnd const): Deleted.
+ (WebCore::SelectionSubtreeRoot::SelectionSubtreeData::selectionEndPos const): Deleted.
+ (WebCore::SelectionSubtreeRoot::SelectionSubtreeData::selectionStartEndPositions const): Deleted.
+ (WebCore::SelectionSubtreeRoot::SelectionSubtreeData::clearSelection): Deleted.
+ (WebCore::SelectionSubtreeRoot::selectionData): Deleted.
+ (WebCore::SelectionSubtreeRoot::selectionData const): Deleted.
+ (WebCore::SelectionSubtreeRoot::setSelectionData): Deleted.
+
2017-10-01 Sam Weinig <[email protected]>
[Settings] Enums should not be passed by const reference
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (222696 => 222697)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-10-02 04:46:32 UTC (rev 222697)
@@ -6432,8 +6432,8 @@
CDCA98EB18B2C8EB00C12FF9 /* LegacyCDMPrivateMediaPlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCA98EA18B2C8EB00C12FF9 /* LegacyCDMPrivateMediaPlayer.cpp */; };
CDCD41E71C3DDB0900965D99 /* ParsedContentRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCD41E51C3DDB0900965D99 /* ParsedContentRange.cpp */; };
CDCD41E81C3DDB0A00965D99 /* ParsedContentRange.h in Headers */ = {isa = PBXBuildFile; fileRef = CDCD41E61C3DDB0900965D99 /* ParsedContentRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 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 */; };
+ CDCFABBD18C0AF78006F8450 /* SelectionRangeData.h in Headers */ = {isa = PBXBuildFile; fileRef = CDCFABBB18C0AE31006F8450 /* SelectionRangeData.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ CDCFABBE18C0AF84006F8450 /* SelectionRangeData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCFABBC18C0AF19006F8450 /* SelectionRangeData.cpp */; };
CDD7089618359F6F002B3DC6 /* SampleMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDD7089418359F6E002B3DC6 /* SampleMap.cpp */; };
CDD7089718359F6F002B3DC6 /* SampleMap.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD7089518359F6F002B3DC6 /* SampleMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
CDDC1E7A18A952F30027A9D4 /* MediaSourcePrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDC1E7918A952F30027A9D4 /* MediaSourcePrivateClient.h */; };
@@ -15214,8 +15214,8 @@
CDCD41E51C3DDB0900965D99 /* ParsedContentRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParsedContentRange.cpp; sourceTree = "<group>"; };
CDCD41E61C3DDB0900965D99 /* ParsedContentRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParsedContentRange.h; 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>"; };
+ CDCFABBB18C0AE31006F8450 /* SelectionRangeData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionRangeData.h; sourceTree = "<group>"; };
+ CDCFABBC18C0AF19006F8450 /* SelectionRangeData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionRangeData.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>"; };
@@ -26128,8 +26128,8 @@
A8CFF5DA0A155A05000A4234 /* RootInlineBox.h */,
5D925B650F64D4DD00B847F0 /* ScrollAlignment.cpp */,
5D925B660F64D4DD00B847F0 /* ScrollAlignment.h */,
- CDCFABBC18C0AF19006F8450 /* SelectionSubtreeRoot.cpp */,
- CDCFABBB18C0AE31006F8450 /* SelectionSubtreeRoot.h */,
+ CDCFABBC18C0AF19006F8450 /* SelectionRangeData.cpp */,
+ CDCFABBB18C0AE31006F8450 /* SelectionRangeData.h */,
E48944A0180B57D800F165D8 /* SimpleLineLayout.cpp */,
E48944A1180B57D800F165D8 /* SimpleLineLayout.h */,
11E067EB1E62461300162D16 /* SimpleLineLayoutCoverage.cpp */,
@@ -30040,9 +30040,9 @@
974D2DA5146A535D00D51F8B /* SecurityPolicy.h in Headers */,
2D5BC42716F882EE007048D0 /* SecurityPolicyViolationEvent.h in Headers */,
B2C3DA2F0D006C1D00EF6F26 /* SegmentedString.h in Headers */,
+ CDCFABBD18C0AF78006F8450 /* SelectionRangeData.h in Headers */,
BEA807C90F714A0300524199 /* SelectionRect.h in Headers */,
51405C89190B014400754F94 /* SelectionRectGatherer.h in Headers */,
- CDCFABBD18C0AF78006F8450 /* SelectionSubtreeRoot.h in Headers */,
E44B4BB4141650D7002B1D8B /* SelectorChecker.h in Headers */,
432D3FE818A8658400D7DC03 /* SelectorCheckerTestFunctions.h in Headers */,
26B999971804D54200D01121 /* SelectorCompiler.h in Headers */,
@@ -33965,9 +33965,9 @@
1AF7AFC71A48A8BC00C8E4E7 /* SecurityOriginPolicy.cpp in Sources */,
974D2DA4146A535D00D51F8B /* SecurityPolicy.cpp in Sources */,
B2C3DA2E0D006C1D00EF6F26 /* SegmentedString.cpp in Sources */,
+ CDCFABBE18C0AF84006F8450 /* SelectionRangeData.cpp in Sources */,
BEA807C80F714A0300524199 /* SelectionRect.cpp in Sources */,
51405C88190B014400754F94 /* SelectionRectGatherer.cpp in Sources */,
- CDCFABBE18C0AF84006F8450 /* SelectionSubtreeRoot.cpp in Sources */,
E44B4BB3141650D7002B1D8B /* SelectorChecker.cpp in Sources */,
26B999961804D54200D01121 /* SelectorCompiler.cpp in Sources */,
415071571685067300C3C7B3 /* SelectorFilter.cpp in Sources */,
Modified: trunk/Source/WebCore/editing/FrameSelection.cpp (222696 => 222697)
--- trunk/Source/WebCore/editing/FrameSelection.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/editing/FrameSelection.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -387,7 +387,7 @@
{
m_pendingSelectionUpdate = true;
if (RenderView* view = m_frame->contentRenderer())
- view->clearSelection();
+ view->selection().clear();
}
void FrameSelection::updateAndRevealSelection(const AXTextStateChangeIntent& intent)
@@ -443,7 +443,7 @@
return;
if (RenderView* view = node.document().renderView())
- view->clearSelection();
+ view->selection().clear();
clear();
}
@@ -506,7 +506,7 @@
if (clearRenderTreeSelection) {
if (auto* renderView = node.document().renderView()) {
- renderView->clearSelection();
+ renderView->selection().clear();
// Trigger a selection update so the selection will be set again.
m_pendingSelectionUpdate = true;
@@ -1517,9 +1517,8 @@
m_caretBlinkTimer.stop();
#endif
- RenderView* view = m_frame->contentRenderer();
- if (view)
- view->clearSelection();
+ if (auto* view = m_frame->contentRenderer())
+ view->selection().clear();
setSelectionWithoutUpdatingAppearance(VisibleSelection(), defaultSetSelectionOptions(), AlignCursorOnScrollIfNeeded, CharacterGranularity);
m_previousCaretNode = nullptr;
@@ -1995,7 +1994,7 @@
// RenderObject::selectionForegroundColor() check if the frame is active,
// we have to update places those colors were painted.
if (RenderView* view = document->renderView())
- view->repaintSelection();
+ view->selection().repaint();
// Caret appears in the active frame.
if (activeAndFocused)
@@ -2090,7 +2089,7 @@
#endif
if (!selection.isRange()) {
- view->clearSelection();
+ view->selection().clear();
return;
}
@@ -2115,7 +2114,7 @@
RenderObject* endRenderer = endPos.deprecatedNode()->renderer();
int endOffset = endPos.deprecatedEditingOffset();
ASSERT(startOffset >= 0 && endOffset >= 0);
- view->setSelection(startRenderer, startOffset, endRenderer, endOffset);
+ view->selection().set({ startRenderer, endRenderer, startOffset, endOffset });
}
}
@@ -2232,13 +2231,13 @@
return LayoutRect();
updateSelectionByUpdatingLayoutOrStyle(*m_frame);
- RenderView* root = m_frame->contentRenderer();
- FrameView* view = m_frame->view();
- if (!root || !view)
+ auto* renderView = m_frame->contentRenderer();
+ if (!renderView)
return LayoutRect();
- LayoutRect selectionRect = root->selectionBounds(clipToVisibleContent);
- return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect)) : selectionRect;
+ auto& selection = renderView->selection();
+ auto selectionRect = clipToVisibleContent ? selection.boundsClippedToVisibleContent() : selection.bounds();
+ return clipToVisibleContent ? intersection(selectionRect, renderView->frameView().visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect)) : selectionRect;
}
void FrameSelection::getClippedVisibleTextRectangles(Vector<FloatRect>& rectangles, TextRectangleHeight textRectHeight) const
Modified: trunk/Source/WebCore/page/FrameView.cpp (222696 => 222697)
--- trunk/Source/WebCore/page/FrameView.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/page/FrameView.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -4522,8 +4522,8 @@
// after we paint the snapshot.
if (shouldPaintSelection == ExcludeSelection) {
for (auto* frame = m_frame.ptr(); frame; frame = frame->tree().traverseNext(m_frame.ptr())) {
- if (RenderView* root = frame->contentRenderer())
- root->clearSelection();
+ if (auto* renderView = frame->contentRenderer())
+ renderView->selection().clear();
}
}
Modified: trunk/Source/WebCore/platform/DragImage.cpp (222696 => 222697)
--- trunk/Source/WebCore/platform/DragImage.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/platform/DragImage.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -135,21 +135,20 @@
ScopedFrameSelectionState(Frame& frame)
: frame(frame)
{
- if (RenderView* root = frame.contentRenderer())
- root->getSelection(startRenderer, startOffset, endRenderer, endOffset);
+ if (auto* renderView = frame.contentRenderer())
+ selection = renderView->selection().get();
}
~ScopedFrameSelectionState()
{
- if (RenderView* root = frame.contentRenderer())
- root->setSelection(startRenderer, startOffset, endRenderer, endOffset, RenderView::RepaintNothing);
+ if (auto* renderView = frame.contentRenderer()) {
+ ASSERT(selection);
+ renderView->selection().set(selection.value(), SelectionRangeData::RepaintMode::Nothing);
+ }
}
const Frame& frame;
- RenderObject* startRenderer;
- RenderObject* endRenderer;
- std::optional<unsigned> startOffset;
- std::optional<unsigned> endOffset;
+ std::optional<SelectionRangeData::Context> selection;
};
#if !PLATFORM(IOS)
@@ -186,10 +185,10 @@
int startOffset = start.deprecatedEditingOffset();
int endOffset = end.deprecatedEditingOffset();
ASSERT(startOffset >= 0 && endOffset >= 0);
- view->setSelection(startRenderer, startOffset, endRenderer, endOffset, RenderView::RepaintNothing);
+ view->selection().set({ startRenderer, endRenderer, startOffset, endOffset }, SelectionRangeData::RepaintMode::Nothing);
// We capture using snapshotFrameRect() because we fake up the selection using
// FrameView but snapshotSelection() uses the selection from the Frame itself.
- return createDragImageFromSnapshot(snapshotFrameRect(frame, view->selectionBounds(), options), nullptr);
+ return createDragImageFromSnapshot(snapshotFrameRect(frame, view->selection().boundsClippedToVisibleContent(), options), nullptr);
}
#endif
Modified: trunk/Source/WebCore/rendering/InlineTextBox.cpp (222696 => 222697)
--- trunk/Source/WebCore/rendering/InlineTextBox.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/InlineTextBox.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -144,8 +144,9 @@
{
RenderObject::SelectionState state = renderer().selectionState();
if (state == RenderObject::SelectionStart || state == RenderObject::SelectionEnd || state == RenderObject::SelectionBoth) {
- unsigned startPos, endPos;
- renderer().view().getSelectionStartEnd(startPos, endPos);
+ auto& selection = renderer().view().selection();
+ auto startPos = selection.startPosition();
+ auto endPos = selection.endPosition();
// The position after a hard line break is considered to be past its end.
ASSERT(start() + len() >= (isLineBreak() ? 1 : 0));
unsigned lastSelectable = start() + len() - (isLineBreak() ? 1 : 0);
@@ -639,9 +640,8 @@
if (selectionState == RenderObject::SelectionInside)
return { 0, m_len };
- unsigned start;
- unsigned end;
- renderer().view().getSelectionStartEnd(start, end);
+ auto start = renderer().view().selection().startPosition();
+ auto end = renderer().view().selection().endPosition();
if (selectionState == RenderObject::SelectionStart)
end = renderer().textLength();
else if (selectionState == RenderObject::SelectionEnd)
Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (222696 => 222697)
--- trunk/Source/WebCore/rendering/RenderBlock.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -1865,8 +1865,8 @@
|| isRenderFragmentedFlow() || style().columnSpan() == ColumnSpanAll)
return true;
- if (view().selectionUnsplitStart()) {
- Node* startElement = view().selectionUnsplitStart()->node();
+ if (view().selection().start()) {
+ Node* startElement = view().selection().start()->node();
if (startElement && startElement->rootEditableElement() == element())
return true;
}
Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (222696 => 222697)
--- trunk/Source/WebCore/rendering/RenderObject.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -1417,8 +1417,8 @@
return st == SelectionStart
|| st == SelectionEnd
|| st == SelectionBoth
- || view().selectionUnsplitStart() == this
- || view().selectionUnsplitEnd() == this;
+ || view().selection().start() == this
+ || view().selection().end() == this;
}
void RenderObject::willBeDestroyed()
Modified: trunk/Source/WebCore/rendering/RenderObject.h (222696 => 222697)
--- trunk/Source/WebCore/rendering/RenderObject.h 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/RenderObject.h 2017-10-02 04:46:32 UTC (rev 222697)
@@ -62,7 +62,7 @@
class RenderLayerModelObject;
class RenderFragmentContainer;
class RenderTheme;
-class SelectionSubtreeRoot;
+class SelectionRangeData;
class TransformState;
class VisiblePosition;
Modified: trunk/Source/WebCore/rendering/RenderReplaced.cpp (222696 => 222697)
--- trunk/Source/WebCore/rendering/RenderReplaced.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/RenderReplaced.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -644,23 +644,22 @@
bool RenderReplaced::isSelected() const
{
- SelectionState s = selectionState();
- if (s == SelectionNone)
+ SelectionState state = selectionState();
+ if (state == SelectionNone)
return false;
- if (s == SelectionInside)
+ if (state == SelectionInside)
return true;
- unsigned selectionStart, selectionEnd;
- view().getSelectionStartEnd(selectionStart, selectionEnd);
- if (s == SelectionStart)
- return selectionStart == 0;
-
+ auto selectionStart = view().selection().startPosition();
+ auto selectionEnd = view().selection().endPosition();
+ if (state == SelectionStart)
+ return !selectionStart;
+
unsigned end = element()->hasChildNodes() ? element()->countChildNodes() : 1;
- if (s == SelectionEnd)
+ if (state == SelectionEnd)
return selectionEnd == end;
- if (s == SelectionBoth)
- return selectionStart == 0 && selectionEnd == end;
-
+ if (state == SelectionBoth)
+ return !selectionStart && selectionEnd == end;
ASSERT_NOT_REACHED();
return false;
}
Modified: trunk/Source/WebCore/rendering/RenderText.cpp (222696 => 222697)
--- trunk/Source/WebCore/rendering/RenderText.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/RenderText.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -1441,13 +1441,15 @@
// Now calculate startPos and endPos for painting selection.
// We include a selection while endPos > 0
- unsigned startPos, endPos;
+ unsigned startPos;
+ unsigned endPos;
if (selectionState() == SelectionInside) {
// We are fully selected.
startPos = 0;
endPos = textLength();
} else {
- view().getSelectionStartEnd(startPos, endPos);
+ startPos = view().selection().startPosition();
+ endPos = view().selection().endPosition();
if (selectionState() == SelectionStart)
endPos = textLength();
else if (selectionState() == SelectionEnd)
Modified: trunk/Source/WebCore/rendering/RenderTextLineBoxes.cpp (222696 => 222697)
--- trunk/Source/WebCore/rendering/RenderTextLineBoxes.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/RenderTextLineBoxes.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -446,11 +446,10 @@
return;
}
- unsigned start, end;
- renderer.view().getSelectionStartEnd(start, end);
+ auto start = renderer.view().selection().startPosition();
+ auto end = renderer.view().selection().endPosition();
if (state == RenderObject::SelectionStart) {
end = renderer.textLength();
-
// to handle selection from end of text to end of line
if (start && start == end)
start = end - 1;
Modified: trunk/Source/WebCore/rendering/RenderView.cpp (222696 => 222697)
--- trunk/Source/WebCore/rendering/RenderView.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/RenderView.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -26,7 +26,6 @@
#include "FloatQuad.h"
#include "FloatingObjects.h"
#include "Frame.h"
-#include "FrameSelection.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLBodyElement.h"
@@ -47,7 +46,6 @@
#include "RenderMultiColumnSet.h"
#include "RenderMultiColumnSpannerPlaceholder.h"
#include "RenderQuote.h"
-#include "RenderSelectionInfo.h"
#include "RenderWidget.h"
#include "ScrollbarTheme.h"
#include "Settings.h"
@@ -78,53 +76,11 @@
bool m_disallowLayout { false };
};
-struct SelectionIterator {
- SelectionIterator(RenderObject* start)
- : m_current(start)
- {
- checkForSpanner();
- }
-
- RenderObject* current() const
- {
- return m_current;
- }
-
- RenderObject* next()
- {
- RenderObject* currentSpan = m_spannerStack.isEmpty() ? nullptr : 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;
- }
-
-private:
- void checkForSpanner()
- {
- if (!is<RenderMultiColumnSpannerPlaceholder>(m_current))
- return;
- auto& placeholder = downcast<RenderMultiColumnSpannerPlaceholder>(*m_current);
- m_spannerStack.append(&placeholder);
- m_current = placeholder.spanner();
- }
-
- RenderObject* m_current { nullptr };
- Vector<RenderMultiColumnSpannerPlaceholder*> m_spannerStack;
-};
-
RenderView::RenderView(Document& document, RenderStyle&& style)
: RenderBlockFlow(document, WTFMove(style))
, m_frameView(*document.view())
+ , m_selection(*this)
, m_lazyRepaintTimer(*this, &RenderView::lazyRepaintTimerFired)
-#if ENABLE(SERVICE_CONTROLS)
- , m_selectionRectGatherer(*this)
-#endif
{
setIsRenderView();
@@ -697,290 +653,6 @@
quads.append(FloatRect(FloatPoint(), layer()->size()));
}
-static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
-{
- if (!object)
- return nullptr;
-
- RenderObject* child = object->childAt(offset);
- return child ? child : object->nextInPreOrderAfterChildren();
-}
-
-IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
-{
- LayoutRect selRect = subtreeSelectionBounds(clipToVisibleContent);
- return snappedIntRect(selRect);
-}
-
-LayoutRect RenderView::subtreeSelectionBounds(bool clipToVisibleContent) const
-{
- typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> SelectionMap;
- SelectionMap selectedObjects;
-
- RenderObject* os = selectionData().selectionStart();
- auto* selectionEnd = selectionData().selectionEnd();
- RenderObject* stop = nullptr;
- if (selectionEnd)
- stop = rendererAfterPosition(selectionEnd, selectionData().selectionEndPos().value());
- SelectionIterator selectionIterator(os);
- while (os && os != stop) {
- if ((os->canBeSelectionLeaf() || os == selectionData().selectionStart() || os == selectionData().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();
- while (cb && !is<RenderView>(*cb)) {
- std::unique_ptr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).iterator->value;
- if (blockInfo)
- break;
- blockInfo = std::make_unique<RenderSelectionInfo>(*cb, clipToVisibleContent);
- cb = cb->containingBlock();
- }
- }
-
- os = selectionIterator.next();
- }
-
- // Now create a single bounding box rect that encloses the whole selection.
- LayoutRect selRect;
- SelectionMap::iterator end = selectedObjects.end();
- for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
- RenderSelectionInfo* info = i->value.get();
- // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
- LayoutRect currRect = info->rect();
- if (RenderLayerModelObject* repaintContainer = info->repaintContainer()) {
- FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
- currRect = absQuad.enclosingBoundingBox();
- }
- selRect.unite(currRect);
- }
- return selRect;
-}
-
-void RenderView::repaintSelection() const
-{
- repaintSubtreeSelection();
-}
-
-void RenderView::repaintSubtreeSelection() const
-{
- HashSet<RenderBlock*> processedBlocks;
-
- auto* selectionEnd = selectionData().selectionEnd();
- RenderObject* end = nullptr;
- if (selectionEnd)
- end = rendererAfterPosition(selectionEnd, selectionData().selectionEndPos().value());
- SelectionIterator selectionIterator(selectionData().selectionStart());
- for (RenderObject* o = selectionIterator.current(); o && o != end; o = selectionIterator.next()) {
- if (!o->canBeSelectionLeaf() && o != selectionData().selectionStart() && o != selectionData().selectionEnd())
- continue;
- if (o->selectionState() == SelectionNone)
- continue;
-
- RenderSelectionInfo(*o, true).repaint();
-
- // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
- for (RenderBlock* block = o->containingBlock(); block && !is<RenderView>(*block); block = block->containingBlock()) {
- if (!processedBlocks.add(block).isNewEntry)
- break;
- RenderSelectionInfo(*block, true).repaint();
- }
- }
-}
-
-void RenderView::setSelection(RenderObject* start, std::optional<unsigned> startPos, RenderObject* end, std::optional<unsigned> endPos, SelectionRepaintMode blockRepaintMode)
-{
- // Make sure both our start and end objects are defined.
- // Check www.msnbc.com and try clicking around to find the case where this happened.
- if ((start && !end) || (end && !start))
- return;
-
- bool caretChanged = m_selectionWasCaret != frame().selection().isCaret();
- m_selectionWasCaret = frame().selection().isCaret();
- // Just return if the selection hasn't changed.
- if (m_selectionUnsplitStart == start && m_selectionUnsplitStartPos == startPos
- && m_selectionUnsplitEnd == end && m_selectionUnsplitEndPos == endPos && !caretChanged) {
- return;
- }
-
-#if ENABLE(SERVICE_CONTROLS)
- // Clear the current rects and create a notifier for the new rects we are about to gather.
- // The Notifier updates the Editor when it goes out of scope and is destroyed.
- std::unique_ptr<SelectionRectGatherer::Notifier> rectNotifier = m_selectionRectGatherer.clearAndCreateNotifier();
-#endif // ENABLE(SERVICE_CONTROLS)
- // Set global positions for new selection.
- m_selectionUnsplitStart = start;
- m_selectionUnsplitStartPos = startPos;
- m_selectionUnsplitEnd = end;
- m_selectionUnsplitEndPos = endPos;
- auto oldSelectionData = std::make_unique<OldSelectionData>();
- clearSubtreeSelection(blockRepaintMode, *oldSelectionData);
- setSelectionData(SelectionSubtreeData(start, startPos, end, endPos));
- applySubtreeSelection(blockRepaintMode, *oldSelectionData);
-}
-
-static inline bool isValidObjectForNewSelection(const RenderView& view, const RenderObject& object)
-{
- return (object.canBeSelectionLeaf() || &object == view.selectionData().selectionStart() || &object == view.selectionData().selectionEnd()) && object.selectionState() != RenderObject::SelectionNone && object.containingBlock();
-}
-
-void RenderView::clearSubtreeSelection(SelectionRepaintMode blockRepaintMode, OldSelectionData& oldSelectionData) const
-{
- // Record the old selected objects. These will be used later
- // when we compare against the new selected objects.
- oldSelectionData.selectionStartPos = selectionData().selectionStartPos();
- oldSelectionData.selectionEndPos = selectionData().selectionEndPos();
-
- // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
- // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
- // the union of those rects might remain the same even when changes have occurred.
-
- RenderObject* os = selectionData().selectionStart();
- auto* selectionEnd = selectionData().selectionEnd();
- RenderObject* stop = nullptr;
- if (selectionEnd)
- stop = rendererAfterPosition(selectionEnd, selectionData().selectionEndPos().value());
- SelectionIterator selectionIterator(os);
- while (os && os != stop) {
- if (isValidObjectForNewSelection(*this, *os)) {
- // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
- oldSelectionData.selectedObjects.set(os, std::make_unique<RenderSelectionInfo>(*os, true));
- if (blockRepaintMode == RepaintNewXOROld) {
- RenderBlock* cb = os->containingBlock();
- while (cb && !is<RenderView>(*cb)) {
- std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = oldSelectionData.selectedBlocks.add(cb, nullptr).iterator->value;
- if (blockInfo)
- break;
- blockInfo = std::make_unique<RenderBlockSelectionInfo>(*cb);
- cb = cb->containingBlock();
- }
- }
- }
-
- os = selectionIterator.next();
- }
-
- for (auto* selectedObject : oldSelectionData.selectedObjects.keys())
- selectedObject->setSelectionStateIfNeeded(SelectionNone);
-}
-
-void RenderView::applySubtreeSelection(SelectionRepaintMode blockRepaintMode, const OldSelectionData& oldSelectionData)
-{
- // Update the selection status of all objects between selectionStart and selectionEnd
- if (selectionData().selectionStart() && selectionData().selectionStart() == selectionData().selectionEnd())
- selectionData().selectionStart()->setSelectionStateIfNeeded(SelectionBoth);
- else {
- if (selectionData().selectionStart())
- selectionData().selectionStart()->setSelectionStateIfNeeded(SelectionStart);
- if (selectionData().selectionEnd())
- selectionData().selectionEnd()->setSelectionStateIfNeeded(SelectionEnd);
- }
-
- RenderObject* selectionStart = selectionData().selectionStart();
- auto* selectionDataEnd = selectionData().selectionEnd();
- RenderObject* selectionEnd = nullptr;
- if (selectionDataEnd)
- selectionEnd = rendererAfterPosition(selectionDataEnd, selectionData().selectionEndPos().value());
- SelectionIterator selectionIterator(selectionStart);
- for (RenderObject* currentRenderer = selectionStart; currentRenderer && currentRenderer != selectionEnd; currentRenderer = selectionIterator.next()) {
- if (currentRenderer == selectionData().selectionStart() || currentRenderer == selectionData().selectionEnd())
- continue;
- if (!currentRenderer->canBeSelectionLeaf())
- continue;
- currentRenderer->setSelectionStateIfNeeded(SelectionInside);
- }
-
- if (blockRepaintMode != RepaintNothing)
- layer()->clearBlockSelectionGapsBounds();
-
- // Now that the selection state has been updated for the new objects, walk them again and
- // put them in the new objects list.
- SelectedObjectMap newSelectedObjects;
- SelectedBlockMap newSelectedBlocks;
- selectionIterator = SelectionIterator(selectionStart);
- for (RenderObject* currentRenderer = selectionStart; currentRenderer && currentRenderer != selectionEnd; currentRenderer = selectionIterator.next()) {
- if (isValidObjectForNewSelection(*this, *currentRenderer)) {
- std::unique_ptr<RenderSelectionInfo> selectionInfo = std::make_unique<RenderSelectionInfo>(*currentRenderer, true);
-
-#if ENABLE(SERVICE_CONTROLS)
- for (auto& rect : selectionInfo->collectedSelectionRects())
- m_selectionRectGatherer.addRect(selectionInfo->repaintContainer(), rect);
- if (!currentRenderer->isTextOrLineBreak())
- m_selectionRectGatherer.setTextOnly(false);
-#endif
-
- newSelectedObjects.set(currentRenderer, WTFMove(selectionInfo));
-
- RenderBlock* containingBlock = currentRenderer->containingBlock();
- while (containingBlock && !is<RenderView>(*containingBlock)) {
- std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(containingBlock, nullptr).iterator->value;
- if (blockInfo)
- break;
- blockInfo = std::make_unique<RenderBlockSelectionInfo>(*containingBlock);
- containingBlock = containingBlock->containingBlock();
-
-#if ENABLE(SERVICE_CONTROLS)
- m_selectionRectGatherer.addGapRects(blockInfo->repaintContainer(), blockInfo->rects());
-#endif
- }
- }
- }
-
- if (blockRepaintMode == RepaintNothing)
- return;
-
- // Have any of the old selected objects changed compared to the new selection?
- for (const auto& selectedObjectInfo : oldSelectionData.selectedObjects) {
- RenderObject* obj = selectedObjectInfo.key;
- RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
- RenderSelectionInfo* oldInfo = selectedObjectInfo.value.get();
- if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state()
- || (selectionData().selectionStart() == obj && oldSelectionData.selectionStartPos != selectionData().selectionStartPos())
- || (selectionData().selectionEnd() == obj && oldSelectionData.selectionEndPos != selectionData().selectionEndPos())) {
- oldInfo->repaint();
- if (newInfo) {
- newInfo->repaint();
- newSelectedObjects.remove(obj);
- }
- }
- }
-
- // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
- for (const auto& selectedObjectInfo : newSelectedObjects)
- selectedObjectInfo.value->repaint();
-
- // Have any of the old blocks changed?
- for (const auto& selectedBlockInfo : oldSelectionData.selectedBlocks) {
- const RenderBlock* block = selectedBlockInfo.key;
- RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
- RenderBlockSelectionInfo* oldInfo = selectedBlockInfo.value.get();
- if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
- oldInfo->repaint();
- if (newInfo) {
- newInfo->repaint();
- newSelectedBlocks.remove(block);
- }
- }
- }
-
- // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
- for (const auto& selectedBlockInfo : newSelectedBlocks)
- selectedBlockInfo.value->repaint();
-}
-
-void RenderView::getSelection(RenderObject*& startRenderer, std::optional<unsigned>& startOffset, RenderObject*& endRenderer, std::optional<unsigned>& endOffset) const
-{
- startRenderer = m_selectionUnsplitStart;
- startOffset = m_selectionUnsplitStartPos;
- endRenderer = m_selectionUnsplitEnd;
- endOffset = m_selectionUnsplitEndPos;
-}
-
-void RenderView::clearSelection()
-{
- layer()->repaintBlockSelectionGaps();
- setSelection(nullptr, std::nullopt, nullptr, std::nullopt, RepaintNewMinusOld);
-}
-
bool RenderView::printing() const
{
return document().printing();
Modified: trunk/Source/WebCore/rendering/RenderView.h (222696 => 222697)
--- trunk/Source/WebCore/rendering/RenderView.h 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/RenderView.h 2017-10-02 04:46:32 UTC (rev 222697)
@@ -26,15 +26,11 @@
#include "Region.h"
#include "RenderBlockFlow.h"
#include "RenderWidget.h"
-#include "SelectionSubtreeRoot.h"
+#include "SelectionRangeData.h"
#include <memory>
#include <wtf/HashSet.h>
#include <wtf/ListHashSet.h>
-#if ENABLE(SERVICE_CONTROLS)
-#include "SelectionRectGatherer.h"
-#endif
-
namespace WebCore {
class ImageQualityController;
@@ -41,7 +37,7 @@
class RenderLayerCompositor;
class RenderQuote;
-class RenderView final : public RenderBlockFlow, public SelectionSubtreeRoot {
+class RenderView final : public RenderBlockFlow {
public:
RenderView(Document&, RenderStyle&&);
virtual ~RenderView();
@@ -85,15 +81,7 @@
// Return the renderer whose background style is used to paint the root background.
RenderElement* rendererForRootBackground() const;
- enum SelectionRepaintMode { RepaintNewXOROld, RepaintNewMinusOld, RepaintNothing };
- void setSelection(RenderObject* start, std::optional<unsigned> startPos, RenderObject* endObject, std::optional<unsigned> endPos, SelectionRepaintMode = RepaintNewXOROld);
- void getSelection(RenderObject*& startRenderer, std::optional<unsigned>& startOffset, RenderObject*& endRenderer, std::optional<unsigned>& endOffset) const;
- void clearSelection();
- RenderObject* selectionUnsplitStart() const { return m_selectionUnsplitStart; }
- RenderObject* selectionUnsplitEnd() const { return m_selectionUnsplitEnd; }
- IntRect selectionBounds(bool clipToVisibleContent = true) const;
- void repaintSelection() const;
- void getSelectionStartEnd(unsigned& start, unsigned& end) const { selectionData().selectionStartEndPositions(start, end); }
+ SelectionRangeData& selection() { return m_selection; }
bool printing() const;
@@ -312,23 +300,14 @@
bool isScrollableOrRubberbandableBox() const override;
- void clearSubtreeSelection(SelectionRepaintMode blockRepaintMode, OldSelectionData&) const;
- void applySubtreeSelection(SelectionRepaintMode, const OldSelectionData&);
- LayoutRect subtreeSelectionBounds(bool clipToVisibleContent = true) const;
- void repaintSubtreeSelection() const;
-
private:
FrameView& m_frameView;
- RenderObject* m_selectionUnsplitStart { nullptr };
- RenderObject* m_selectionUnsplitEnd { nullptr };
- std::optional<unsigned> m_selectionUnsplitStartPos;
- std::optional<unsigned> m_selectionUnsplitEndPos;
-
// Include this RenderView.
uint64_t m_rendererCount { 1 };
mutable std::unique_ptr<Region> m_accumulatedRepaintRegion;
+ SelectionRangeData m_selection;
// FIXME: Only used by embedded WebViews inside AppKit NSViews. Find a way to remove.
struct LegacyPrinting {
@@ -360,7 +339,6 @@
unsigned m_renderCounterCount { 0 };
unsigned m_renderTreeInternalMutationCounter { 0 };
- bool m_selectionWasCaret { false };
bool m_hasSoftwareFilters { false };
bool m_usesFirstLineRules { false };
bool m_usesFirstLetterRules { false };
@@ -372,9 +350,6 @@
HashSet<RenderElement*> m_visibleInViewportRenderers;
Vector<RefPtr<RenderWidget>> m_protectedRenderWidgets;
-#if ENABLE(SERVICE_CONTROLS)
- SelectionRectGatherer m_selectionRectGatherer;
-#endif
#if ENABLE(CSS_SCROLL_SNAP)
HashSet<const RenderBox*> m_boxesWithScrollSnapPositions;
#endif
Modified: trunk/Source/WebCore/rendering/RenderingAllInOne.cpp (222696 => 222697)
--- trunk/Source/WebCore/rendering/RenderingAllInOne.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/RenderingAllInOne.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -133,7 +133,7 @@
#include "RenderWidget.cpp"
#include "RootInlineBox.cpp"
#include "ScrollAlignment.cpp"
-#include "SelectionSubtreeRoot.cpp"
+#include "SelectionRangeData.cpp"
#include "SimpleLineLayout.cpp"
#include "SimpleLineLayoutCoverage.cpp"
#include "SimpleLineLayoutFlowContents.cpp"
Added: trunk/Source/WebCore/rendering/SelectionRangeData.cpp (0 => 222697)
--- trunk/Source/WebCore/rendering/SelectionRangeData.cpp (rev 0)
+++ trunk/Source/WebCore/rendering/SelectionRangeData.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
+ *
+ * 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 "SelectionRangeData.h"
+
+#include "Document.h"
+#include "FrameSelection.h"
+#include "Position.h"
+#include "Range.h"
+#include "RenderLayer.h"
+#include "RenderMultiColumnSpannerPlaceholder.h"
+#include "RenderObject.h"
+#include "RenderView.h"
+#include "VisibleSelection.h"
+
+namespace WebCore {
+
+struct SelectionData {
+ using RendererMap = HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>>;
+ using RenderBlockMap = HashMap<const RenderBlock*, std::unique_ptr<RenderBlockSelectionInfo>>;
+
+ std::optional<unsigned> startPosition;
+ std::optional<unsigned> endPosition;
+ RendererMap renderers;
+ RenderBlockMap blocks;
+};
+
+class SelectionIterator {
+public:
+ SelectionIterator(RenderObject* start)
+ : m_current(start)
+ {
+ checkForSpanner();
+ }
+
+ RenderObject* current() const
+ {
+ return m_current;
+ }
+
+ RenderObject* next()
+ {
+ RenderObject* currentSpan = m_spannerStack.isEmpty() ? nullptr : 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;
+ }
+
+private:
+ void checkForSpanner()
+ {
+ if (!is<RenderMultiColumnSpannerPlaceholder>(m_current))
+ return;
+ auto& placeholder = downcast<RenderMultiColumnSpannerPlaceholder>(*m_current);
+ m_spannerStack.append(&placeholder);
+ m_current = placeholder.spanner();
+ }
+
+ RenderObject* m_current { nullptr };
+ Vector<RenderMultiColumnSpannerPlaceholder*> m_spannerStack;
+};
+
+static RenderObject* rendererAfterPosition(const RenderObject& renderer, unsigned offset)
+{
+ auto* child = renderer.childAt(offset);
+ return child ? child : renderer.nextInPreOrderAfterChildren();
+}
+
+static bool isValidRendererForSelection(const RenderObject& renderer, const SelectionRangeData::Context& selection)
+{
+ return (renderer.canBeSelectionLeaf() || &renderer == selection.start || &renderer == selection.end)
+ && renderer.selectionState() != RenderObject::SelectionNone
+ && renderer.containingBlock();
+}
+
+static RenderBlock* containingBlockBelowView(const RenderObject& renderer)
+{
+ auto* containingBlock = renderer.containingBlock();
+ return is<RenderView>(containingBlock) ? nullptr : containingBlock;
+}
+
+static SelectionData collect(const SelectionRangeData::Context& selection, bool repaintDifference)
+{
+ SelectionData oldSelectionData { selection.startPosition, selection.endPosition, { }, { } };
+ // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
+ // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
+ // the union of those rects might remain the same even when changes have occurred.
+ RenderObject* start = selection.start;
+ RenderObject* stop = nullptr;
+ if (selection.end)
+ stop = rendererAfterPosition(*selection.end, selection.endPosition.value());
+ SelectionIterator selectionIterator(start);
+ while (start && start != stop) {
+ if (isValidRendererForSelection(*start, selection)) {
+ // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
+ oldSelectionData.renderers.set(start, std::make_unique<RenderSelectionInfo>(*start, true));
+ if (repaintDifference) {
+ for (auto* block = containingBlockBelowView(*start); block; block = containingBlockBelowView(*block)) {
+ auto& blockInfo = oldSelectionData.blocks.add(block, nullptr).iterator->value;
+ if (blockInfo)
+ break;
+ blockInfo = std::make_unique<RenderBlockSelectionInfo>(*block);
+ }
+ }
+ }
+ start = selectionIterator.next();
+ }
+ return oldSelectionData;
+}
+
+SelectionRangeData::SelectionRangeData(RenderView& view)
+ : m_renderView(view)
+#if ENABLE(SERVICE_CONTROLS)
+ , m_selectionRectGatherer(view)
+#endif
+{
+}
+
+void SelectionRangeData::set(const Context& selection, RepaintMode blockRepaintMode)
+{
+ // Make sure both our start and end objects are defined.
+ // Check www.msnbc.com and try clicking around to find the case where this happened.
+ if ((selection.start && !selection.end) || (selection.end && !selection.start))
+ return;
+ // Just return if the selection hasn't changed.
+ auto isCaret = m_renderView.frame().selection().isCaret();
+ if (selection == m_selectionContext && m_selectionWasCaret == isCaret)
+ return;
+#if ENABLE(SERVICE_CONTROLS)
+ // Clear the current rects and create a notifier for the new rects we are about to gather.
+ // The Notifier updates the Editor when it goes out of scope and is destroyed.
+ auto rectNotifier = m_selectionRectGatherer.clearAndCreateNotifier();
+#endif
+ m_selectionWasCaret = isCaret;
+ apply(selection, blockRepaintMode);
+}
+
+void SelectionRangeData::clear()
+{
+ m_renderView.layer()->repaintBlockSelectionGaps();
+ set({nullptr, nullptr, std::nullopt, std::nullopt}, SelectionRangeData::RepaintMode::NewMinusOld);
+}
+
+void SelectionRangeData::repaint() const
+{
+ HashSet<RenderBlock*> processedBlocks;
+ RenderObject* end = nullptr;
+ if (m_selectionContext.end)
+ end = rendererAfterPosition(*m_selectionContext.end, m_selectionContext.endPosition.value());
+ SelectionIterator selectionIterator(m_selectionContext.start);
+ for (auto* renderer = selectionIterator.current(); renderer && renderer != end; renderer = selectionIterator.next()) {
+ if (!renderer->canBeSelectionLeaf() && renderer != m_selectionContext.start && renderer != m_selectionContext.end)
+ continue;
+ if (renderer->selectionState() == RenderObject::SelectionNone)
+ continue;
+ RenderSelectionInfo(*renderer, true).repaint();
+ // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
+ for (auto* block = containingBlockBelowView(*renderer); block; block = containingBlockBelowView(*block)) {
+ if (!processedBlocks.add(block).isNewEntry)
+ break;
+ RenderSelectionInfo(*block, true).repaint();
+ }
+ }
+}
+
+IntRect SelectionRangeData::collectBounds(ClipToVisibleContent clipToVisibleContent) const
+{
+ SelectionData::RendererMap renderers;
+ RenderObject* start = m_selectionContext.start;
+ RenderObject* stop = nullptr;
+ if (m_selectionContext.end)
+ stop = rendererAfterPosition(*m_selectionContext.end, m_selectionContext.endPosition.value());
+ SelectionIterator selectionIterator(start);
+ while (start && start != stop) {
+ if ((start->canBeSelectionLeaf() || start == m_selectionContext.start || start == m_selectionContext.end)
+ && start->selectionState() != RenderObject::SelectionNone) {
+ // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
+ renderers.set(start, std::make_unique<RenderSelectionInfo>(*start, clipToVisibleContent == ClipToVisibleContent::Yes));
+ auto* block = start->containingBlock();
+ while (block && !is<RenderView>(*block)) {
+ std::unique_ptr<RenderSelectionInfo>& blockInfo = renderers.add(block, nullptr).iterator->value;
+ if (blockInfo)
+ break;
+ blockInfo = std::make_unique<RenderSelectionInfo>(*block, clipToVisibleContent == ClipToVisibleContent::Yes);
+ block = block->containingBlock();
+ }
+ }
+ start = selectionIterator.next();
+ }
+
+ // Now create a single bounding box rect that encloses the whole selection.
+ LayoutRect selectionRect;
+ for (auto& info : renderers.values()) {
+ // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
+ LayoutRect currentRect = info->rect();
+ if (auto* repaintContainer = info->repaintContainer()) {
+ FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currentRect));
+ currentRect = absQuad.enclosingBoundingBox();
+ }
+ selectionRect.unite(currentRect);
+ }
+ return snappedIntRect(selectionRect);
+}
+
+void SelectionRangeData::apply(const Context& newSelection, RepaintMode blockRepaintMode)
+{
+ auto oldSelectionData = collect(m_selectionContext, blockRepaintMode == RepaintMode::NewXOROld);
+ // Remove current selection.
+ for (auto* renderer : oldSelectionData.renderers.keys())
+ renderer->setSelectionStateIfNeeded(RenderObject::SelectionNone);
+ m_selectionContext = newSelection;
+ // Update the selection status of all objects between selectionStart and selectionEnd
+ if (m_selectionContext.start && m_selectionContext.start == m_selectionContext.end)
+ m_selectionContext.start->setSelectionStateIfNeeded(RenderObject::SelectionBoth);
+ else {
+ if (m_selectionContext.start)
+ m_selectionContext.start->setSelectionStateIfNeeded(RenderObject::SelectionStart);
+ if (m_selectionContext.end)
+ m_selectionContext.end->setSelectionStateIfNeeded(RenderObject::SelectionEnd);
+ }
+
+ auto* selectionStart = m_selectionContext.start;
+ auto* selectionDataEnd = m_selectionContext.end;
+ RenderObject* selectionEnd = nullptr;
+ if (selectionDataEnd)
+ selectionEnd = rendererAfterPosition(*selectionDataEnd, m_selectionContext.endPosition.value());
+ SelectionIterator selectionIterator(selectionStart);
+ for (auto* currentRenderer = selectionStart; currentRenderer && currentRenderer != selectionEnd; currentRenderer = selectionIterator.next()) {
+ if (currentRenderer == m_selectionContext.start || currentRenderer == m_selectionContext.end)
+ continue;
+ if (!currentRenderer->canBeSelectionLeaf())
+ continue;
+ currentRenderer->setSelectionStateIfNeeded(RenderObject::SelectionInside);
+ }
+
+ if (blockRepaintMode != RepaintMode::Nothing)
+ m_renderView.layer()->clearBlockSelectionGapsBounds();
+
+ // Now that the selection state has been updated for the new objects, walk them again and
+ // put them in the new objects list.
+ SelectionData::RendererMap newSelectedRenderers;
+ SelectionData::RenderBlockMap newSelectedBlocks;
+ selectionIterator = SelectionIterator(selectionStart);
+ for (auto* currentRenderer = selectionStart; currentRenderer && currentRenderer != selectionEnd; currentRenderer = selectionIterator.next()) {
+ if (isValidRendererForSelection(*currentRenderer, m_selectionContext)) {
+ std::unique_ptr<RenderSelectionInfo> selectionInfo = std::make_unique<RenderSelectionInfo>(*currentRenderer, true);
+#if ENABLE(SERVICE_CONTROLS)
+ for (auto& rect : selectionInfo->collectedSelectionRects())
+ m_selectionRectGatherer.addRect(selectionInfo->repaintContainer(), rect);
+ if (!currentRenderer->isTextOrLineBreak())
+ m_selectionRectGatherer.setTextOnly(false);
+#endif
+ newSelectedRenderers.set(currentRenderer, WTFMove(selectionInfo));
+ auto* containingBlock = currentRenderer->containingBlock();
+ while (containingBlock && !is<RenderView>(*containingBlock)) {
+ std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(containingBlock, nullptr).iterator->value;
+ if (blockInfo)
+ break;
+ blockInfo = std::make_unique<RenderBlockSelectionInfo>(*containingBlock);
+ containingBlock = containingBlock->containingBlock();
+#if ENABLE(SERVICE_CONTROLS)
+ m_selectionRectGatherer.addGapRects(blockInfo->repaintContainer(), blockInfo->rects());
+#endif
+ }
+ }
+ }
+
+ if (blockRepaintMode == RepaintMode::Nothing)
+ return;
+
+ // Have any of the old selected objects changed compared to the new selection?
+ for (auto& selectedRendererInfo : oldSelectionData.renderers) {
+ auto* renderer = selectedRendererInfo.key;
+ auto* newInfo = newSelectedRenderers.get(renderer);
+ auto* oldInfo = selectedRendererInfo.value.get();
+ if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state()
+ || (m_selectionContext.start == renderer && oldSelectionData.startPosition != m_selectionContext.startPosition)
+ || (m_selectionContext.end == renderer && oldSelectionData.endPosition != m_selectionContext.endPosition)) {
+ oldInfo->repaint();
+ if (newInfo) {
+ newInfo->repaint();
+ newSelectedRenderers.remove(renderer);
+ }
+ }
+ }
+
+ // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
+ for (auto& selectedRendererInfo : newSelectedRenderers)
+ selectedRendererInfo.value->repaint();
+
+ // Have any of the old blocks changed?
+ for (auto& selectedBlockInfo : oldSelectionData.blocks) {
+ auto* block = selectedBlockInfo.key;
+ auto* newInfo = newSelectedBlocks.get(block);
+ auto* oldInfo = selectedBlockInfo.value.get();
+ if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
+ oldInfo->repaint();
+ if (newInfo) {
+ newInfo->repaint();
+ newSelectedBlocks.remove(block);
+ }
+ }
+ }
+
+ // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
+ for (auto& selectedBlockInfo : newSelectedBlocks)
+ selectedBlockInfo.value->repaint();
+}
+
+} // namespace WebCore
Added: trunk/Source/WebCore/rendering/SelectionRangeData.h (0 => 222697)
--- trunk/Source/WebCore/rendering/SelectionRangeData.h (rev 0)
+++ trunk/Source/WebCore/rendering/SelectionRangeData.h 2017-10-02 04:46:32 UTC (rev 222697)
@@ -0,0 +1,86 @@
+ /*
+ * Copyright (C) 2014 Igalia S.L.
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "RenderSelectionInfo.h"
+
+#if ENABLE(SERVICE_CONTROLS)
+#include "SelectionRectGatherer.h"
+#endif
+
+namespace WebCore {
+
+struct OldSelectionData;
+
+class SelectionRangeData {
+public:
+ SelectionRangeData(RenderView&);
+
+ struct Context {
+ RenderObject* start { nullptr };
+ RenderObject* end { nullptr };
+ std::optional<unsigned> startPosition;
+ std::optional<unsigned> endPosition;
+
+ bool operator==(const Context& other) const
+ {
+ return start == other.start && end == other.end && startPosition == other.startPosition && endPosition == other.endPosition;
+ }
+ };
+
+ enum class RepaintMode { NewXOROld, NewMinusOld, Nothing };
+ void set(const Context&, RepaintMode = RepaintMode::NewXOROld);
+ const Context& get() const { return m_selectionContext; }
+
+ RenderObject* start() const { return m_selectionContext.start; }
+ RenderObject* end() const { return m_selectionContext.end; }
+ unsigned startPosition() const { ASSERT(m_selectionContext.startPosition); return m_selectionContext.startPosition.value(); }
+ unsigned endPosition() const { ASSERT(m_selectionContext.endPosition); return m_selectionContext.endPosition.value(); }
+
+ void clear();
+ IntRect bounds() const { return collectBounds(ClipToVisibleContent::No); }
+ IntRect boundsClippedToVisibleContent() const { return collectBounds(ClipToVisibleContent::Yes); }
+ void repaint() const;
+
+private:
+ enum class ClipToVisibleContent { Yes, No };
+ IntRect collectBounds(ClipToVisibleContent) const;
+ void apply(const Context&, RepaintMode);
+
+ const RenderView& m_renderView;
+#if ENABLE(SERVICE_CONTROLS)
+ SelectionRectGatherer m_selectionRectGatherer;
+#endif
+ Context m_selectionContext;
+ bool m_selectionWasCaret { false };
+};
+
+} // namespace WebCore
Deleted: trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp (222696 => 222697)
--- trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp 2017-10-02 04:46:32 UTC (rev 222697)
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2014 Igalia S.L.
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * 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"
-
-#include "Document.h"
-#include "Position.h"
-#include "Range.h"
-#include "VisibleSelection.h"
-
-namespace WebCore {
-
-SelectionSubtreeRoot::SelectionSubtreeRoot()
-{
-}
-
-} // namespace WebCore
Deleted: trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h (222696 => 222697)
--- trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h 2017-10-02 03:33:49 UTC (rev 222696)
+++ trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h 2017-10-02 04:46:32 UTC (rev 222697)
@@ -1,103 +0,0 @@
- /*
- * 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.
- */
-
-#pragma once
-
-#include "RenderObject.h"
-#include "RenderSelectionInfo.h"
-
-namespace WebCore {
-
-class Document;
-
-class SelectionSubtreeRoot {
-public:
-
- typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> SelectedObjectMap;
- typedef HashMap<const RenderBlock*, std::unique_ptr<RenderBlockSelectionInfo>> SelectedBlockMap;
-
- struct OldSelectionData {
- OldSelectionData()
- {
- }
-
- std::optional<unsigned> selectionStartPos;
- std::optional<unsigned> selectionEndPos;
- SelectedObjectMap selectedObjects;
- SelectedBlockMap selectedBlocks;
- };
-
- class SelectionSubtreeData {
- public:
- SelectionSubtreeData() = default;
-
- SelectionSubtreeData(RenderObject* selectionStart, std::optional<unsigned> selectionStartPos, RenderObject* selectionEnd, std::optional<unsigned> selectionEndPos)
- : m_selectionStart(selectionStart)
- , m_selectionEnd(selectionEnd)
- , m_selectionStartPos(selectionStartPos)
- , m_selectionEndPos(selectionEndPos)
- {
- }
-
- RenderObject* selectionStart() const { return m_selectionStart; }
- std::optional<unsigned> selectionStartPos() const { return m_selectionStartPos; }
- RenderObject* selectionEnd() const { return m_selectionEnd; }
- std::optional<unsigned> selectionEndPos() const { return m_selectionEndPos; }
- void selectionStartEndPositions(unsigned& startPos, unsigned& endPos) const
- {
- startPos = m_selectionStartPos.value();
- endPos = m_selectionEndPos.value();
- }
- void clearSelection()
- {
- m_selectionStart = nullptr;
- m_selectionStartPos = std::nullopt;
- m_selectionEnd = nullptr;
- m_selectionEndPos = std::nullopt;
- }
-
- private:
- RenderObject* m_selectionStart { nullptr };
- RenderObject* m_selectionEnd { nullptr };
- std::optional<unsigned> m_selectionStartPos;
- std::optional<unsigned> m_selectionEndPos;
- };
-
- SelectionSubtreeRoot();
-
- SelectionSubtreeData& selectionData() { return m_selectionSubtreeData; }
- const SelectionSubtreeData& selectionData() const { return m_selectionSubtreeData; }
-
- void setSelectionData(const SelectionSubtreeData& selectionSubtreeData) { m_selectionSubtreeData = selectionSubtreeData; }
-
-private:
- SelectionSubtreeData m_selectionSubtreeData;
-};
-
-} // namespace WebCore