Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: third_party/WebKit/Source/core/dom/Range.cpp

Issue 2687273002: Selection API: Mutating a Range object after adding it to Selection should update Selection attribu… (Closed)
Patch Set: . Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * (C) 1999 Lars Knoll (knoll@kde.org) 2 * (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
5 * (C) 2001 Peter Kelly (pmk@post.com) 5 * (C) 2001 Peter Kelly (pmk@post.com)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
7 * rights reserved. 7 * rights reserved.
8 * Copyright (C) 2011 Motorola Mobility. All rights reserved. 8 * Copyright (C) 2011 Motorola Mobility. All rights reserved.
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 18 matching lines...) Expand all
29 #include "core/dom/ClientRect.h" 29 #include "core/dom/ClientRect.h"
30 #include "core/dom/ClientRectList.h" 30 #include "core/dom/ClientRectList.h"
31 #include "core/dom/DocumentFragment.h" 31 #include "core/dom/DocumentFragment.h"
32 #include "core/dom/ExceptionCode.h" 32 #include "core/dom/ExceptionCode.h"
33 #include "core/dom/Node.h" 33 #include "core/dom/Node.h"
34 #include "core/dom/NodeTraversal.h" 34 #include "core/dom/NodeTraversal.h"
35 #include "core/dom/NodeWithIndex.h" 35 #include "core/dom/NodeWithIndex.h"
36 #include "core/dom/ProcessingInstruction.h" 36 #include "core/dom/ProcessingInstruction.h"
37 #include "core/dom/Text.h" 37 #include "core/dom/Text.h"
38 #include "core/editing/EditingUtilities.h" 38 #include "core/editing/EditingUtilities.h"
39 #include "core/editing/EphemeralRange.h"
40 #include "core/editing/FrameSelection.h"
39 #include "core/editing/VisiblePosition.h" 41 #include "core/editing/VisiblePosition.h"
40 #include "core/editing/VisibleUnits.h" 42 #include "core/editing/VisibleUnits.h"
41 #include "core/editing/iterators/TextIterator.h" 43 #include "core/editing/iterators/TextIterator.h"
42 #include "core/editing/serializers/Serialization.h" 44 #include "core/editing/serializers/Serialization.h"
43 #include "core/events/ScopedEventQueue.h" 45 #include "core/events/ScopedEventQueue.h"
44 #include "core/html/HTMLBodyElement.h" 46 #include "core/html/HTMLBodyElement.h"
45 #include "core/html/HTMLElement.h" 47 #include "core/html/HTMLElement.h"
46 #include "core/layout/LayoutObject.h" 48 #include "core/layout/LayoutObject.h"
47 #include "core/layout/LayoutText.h" 49 #include "core/layout/LayoutText.h"
48 #include "core/svg/SVGSVGElement.h" 50 #include "core/svg/SVGSVGElement.h"
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 setDocument(refNode->document()); 177 setDocument(refNode->document());
176 didMoveDocument = true; 178 didMoveDocument = true;
177 } 179 }
178 180
179 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState); 181 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState);
180 if (exceptionState.hadException()) 182 if (exceptionState.hadException())
181 return; 183 return;
182 184
183 m_start.set(refNode, offset, childNode); 185 m_start.set(refNode, offset, childNode);
184 186
185 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) 187 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end))
yosin_UTC9 2017/02/10 10:26:27 nit: Can we use early-return style? if (didMoveDo
tkent 2017/02/13 04:04:13 Good point. I'll investigate Firefox/Edge behavio
tkent 2017/02/13 05:45:29 Both of Firefox and Edge keep Selection.getRangeAt
tkent 2017/02/13 07:31:40 We discussed offline, and agreed that we should un
186 collapse(true); 188 collapse(true);
189 else
190 updateSelectionIfAddedToSelection();
187 } 191 }
188 192
189 void Range::setEnd(Node* refNode, int offset, ExceptionState& exceptionState) { 193 void Range::setEnd(Node* refNode, int offset, ExceptionState& exceptionState) {
190 if (!refNode) { 194 if (!refNode) {
191 // FIXME: Generated bindings code never calls with null, and neither should 195 // FIXME: Generated bindings code never calls with null, and neither should
192 // other callers! 196 // other callers!
193 exceptionState.throwTypeError("The node provided is null."); 197 exceptionState.throwTypeError("The node provided is null.");
194 return; 198 return;
195 } 199 }
196 200
197 bool didMoveDocument = false; 201 bool didMoveDocument = false;
198 if (refNode->document() != m_ownerDocument) { 202 if (refNode->document() != m_ownerDocument) {
199 setDocument(refNode->document()); 203 setDocument(refNode->document());
200 didMoveDocument = true; 204 didMoveDocument = true;
201 } 205 }
202 206
203 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState); 207 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState);
204 if (exceptionState.hadException()) 208 if (exceptionState.hadException())
205 return; 209 return;
206 210
207 m_end.set(refNode, offset, childNode); 211 m_end.set(refNode, offset, childNode);
208 212
209 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) 213 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end))
yosin_UTC9 2017/02/10 10:26:27 Similar to L187 in Range::setStart()
tkent 2017/02/13 07:31:40 Done.
210 collapse(false); 214 collapse(false);
215 else
216 updateSelectionIfAddedToSelection();
211 } 217 }
212 218
213 void Range::setStart(const Position& start, ExceptionState& exceptionState) { 219 void Range::setStart(const Position& start, ExceptionState& exceptionState) {
214 Position parentAnchored = start.parentAnchoredEquivalent(); 220 Position parentAnchored = start.parentAnchoredEquivalent();
215 setStart(parentAnchored.computeContainerNode(), 221 setStart(parentAnchored.computeContainerNode(),
216 parentAnchored.offsetInContainerNode(), exceptionState); 222 parentAnchored.offsetInContainerNode(), exceptionState);
217 } 223 }
218 224
219 void Range::setEnd(const Position& end, ExceptionState& exceptionState) { 225 void Range::setEnd(const Position& end, ExceptionState& exceptionState) {
220 Position parentAnchored = end.parentAnchoredEquivalent(); 226 Position parentAnchored = end.parentAnchoredEquivalent();
221 setEnd(parentAnchored.computeContainerNode(), 227 setEnd(parentAnchored.computeContainerNode(),
222 parentAnchored.offsetInContainerNode(), exceptionState); 228 parentAnchored.offsetInContainerNode(), exceptionState);
223 } 229 }
224 230
225 void Range::collapse(bool toStart) { 231 void Range::collapse(bool toStart) {
226 if (toStart) 232 if (toStart)
227 m_end = m_start; 233 m_end = m_start;
228 else 234 else
229 m_start = m_end; 235 m_start = m_end;
236 updateSelectionIfAddedToSelection();
230 } 237 }
231 238
232 bool Range::isNodeFullyContained(Node& node) const { 239 bool Range::isNodeFullyContained(Node& node) const {
233 ContainerNode* parentNode = node.parentNode(); 240 ContainerNode* parentNode = node.parentNode();
234 int nodeIndex = node.nodeIndex(); 241 int nodeIndex = node.nodeIndex();
235 return isPointInRange( 242 return isPointInRange(
236 parentNode, nodeIndex, 243 parentNode, nodeIndex,
237 IGNORE_EXCEPTION_FOR_TESTING) // starts in the middle of this 244 IGNORE_EXCEPTION_FOR_TESTING) // starts in the middle of this
238 // range, or on the boundary points. 245 // range, or on the boundary points.
239 && isPointInRange( 246 && isPointInRange(
(...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 "The node provided is of type '" + refNode->nodeName() + "'."); 1218 "The node provided is of type '" + refNode->nodeName() + "'.");
1212 return; 1219 return;
1213 } 1220 }
1214 } 1221 }
1215 1222
1216 if (m_ownerDocument != refNode->document()) 1223 if (m_ownerDocument != refNode->document())
1217 setDocument(refNode->document()); 1224 setDocument(refNode->document());
1218 1225
1219 m_start.setToStartOfNode(*refNode); 1226 m_start.setToStartOfNode(*refNode);
1220 m_end.setToEndOfNode(*refNode); 1227 m_end.setToEndOfNode(*refNode);
1228 updateSelectionIfAddedToSelection();
1221 } 1229 }
1222 1230
1223 bool Range::selectNodeContents(Node* refNode, Position& start, Position& end) { 1231 bool Range::selectNodeContents(Node* refNode, Position& start, Position& end) {
1224 if (!refNode) { 1232 if (!refNode) {
1225 return false; 1233 return false;
1226 } 1234 }
1227 1235
1228 for (Node* n = refNode; n; n = n->parentNode()) { 1236 for (Node* n = refNode; n; n = n->parentNode()) {
1229 switch (n->getNodeType()) { 1237 switch (n->getNodeType()) {
1230 case Node::kAttributeNode: 1238 case Node::kAttributeNode:
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
1693 for (const FloatQuad& quad : quads) 1701 for (const FloatQuad& quad : quads)
1694 result.unite(quad.boundingBox()); // Skips empty rects. 1702 result.unite(quad.boundingBox()); // Skips empty rects.
1695 1703
1696 // If all rects are empty, return the first rect. 1704 // If all rects are empty, return the first rect.
1697 if (result.isEmpty() && !quads.isEmpty()) 1705 if (result.isEmpty() && !quads.isEmpty())
1698 return quads.front().boundingBox(); 1706 return quads.front().boundingBox();
1699 1707
1700 return result; 1708 return result;
1701 } 1709 }
1702 1710
1711 void Range::updateSelectionIfAddedToSelection() {
1712 if (!ownerDocument().frame())
1713 return;
1714 FrameSelection& selection = ownerDocument().frame()->selection();
1715 if (this != selection.documentCachedRange())
1716 return;
1717 selection.setSelectedRange(EphemeralRange(this), VP_DEFAULT_AFFINITY);
1718 selection.cacheRangeOfDocument(this);
1719 }
1720
1703 DEFINE_TRACE(Range) { 1721 DEFINE_TRACE(Range) {
1704 visitor->trace(m_ownerDocument); 1722 visitor->trace(m_ownerDocument);
1705 visitor->trace(m_start); 1723 visitor->trace(m_start);
1706 visitor->trace(m_end); 1724 visitor->trace(m_end);
1707 } 1725 }
1708 1726
1709 } // namespace blink 1727 } // namespace blink
1710 1728
1711 #ifndef NDEBUG 1729 #ifndef NDEBUG
1712 1730
1713 void showTree(const blink::Range* range) { 1731 void showTree(const blink::Range* range) {
1714 if (range && range->boundaryPointsValid()) { 1732 if (range && range->boundaryPointsValid()) {
1715 LOG(INFO) << "\n" 1733 LOG(INFO) << "\n"
1716 << range->startContainer() 1734 << range->startContainer()
1717 ->toMarkedTreeString(range->startContainer(), "S", 1735 ->toMarkedTreeString(range->startContainer(), "S",
1718 range->endContainer(), "E") 1736 range->endContainer(), "E")
1719 .utf8() 1737 .utf8()
1720 .data() 1738 .data()
1721 << "start offset: " << range->startOffset() 1739 << "start offset: " << range->startOffset()
1722 << ", end offset: " << range->endOffset(); 1740 << ", end offset: " << range->endOffset();
1723 } else { 1741 } else {
1724 LOG(INFO) << "Cannot show tree if range is null, or if boundary points are " 1742 LOG(INFO) << "Cannot show tree if range is null, or if boundary points are "
1725 "invalid."; 1743 "invalid.";
1726 } 1744 }
1727 } 1745 }
1728 1746
1729 #endif 1747 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698