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

Side by Side Diff: third_party/WebKit/Source/core/editing/FrameSelection.cpp

Issue 2680943004: Make FrameSelection to hold non-canonicalized positions (Closed)
Patch Set: 2017-02-10T19:11:26 Changed for tkent@'s comments 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 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 frame.page()->focusController().focusedFrame() == frame), 103 frame.page()->focusController().focusedFrame() == frame),
104 m_frameCaret(new FrameCaret(frame, *m_selectionEditor)) {} 104 m_frameCaret(new FrameCaret(frame, *m_selectionEditor)) {}
105 105
106 FrameSelection::~FrameSelection() {} 106 FrameSelection::~FrameSelection() {}
107 107
108 const DisplayItemClient& FrameSelection::caretDisplayItemClientForTesting() 108 const DisplayItemClient& FrameSelection::caretDisplayItemClientForTesting()
109 const { 109 const {
110 return m_frameCaret->displayItemClient(); 110 return m_frameCaret->displayItemClient();
111 } 111 }
112 112
113 const Document& FrameSelection::document() const { 113 Document& FrameSelection::document() const {
114 DCHECK(lifecycleContext()); 114 DCHECK(lifecycleContext());
115 return *lifecycleContext(); 115 return *lifecycleContext();
116 } 116 }
117 117
118 Document& FrameSelection::document() { 118 bool FrameSelection::isHandleVisible() const {
119 DCHECK(lifecycleContext()); 119 return selectionInDOMTree().isHandleVisible();
120 return *lifecycleContext();
121 } 120 }
122 121
122 // TODO(yosin): We should replace |visibleSelection<EditingStrategy>()| to
123 // |computeVisibleSelectionInDOMTree()|.
123 // TODO(yosin): To avoid undefined symbols in clang, we explicitly 124 // TODO(yosin): To avoid undefined symbols in clang, we explicitly
124 // have specialized version of |FrameSelection::visibleSelection<Strategy>| 125 // have specialized version of |FrameSelection::visibleSelection<Strategy>|
125 // before |FrameSelection::selection()| which refers this. 126 // before |FrameSelection::selection()| which refers this.
126 template <> 127 template <>
127 const VisibleSelection& FrameSelection::visibleSelection<EditingStrategy>() 128 const VisibleSelection& FrameSelection::visibleSelection<EditingStrategy>()
128 const { 129 const {
129 return m_selectionEditor->visibleSelection<EditingStrategy>(); 130 return m_selectionEditor->visibleSelection<EditingStrategy>();
130 } 131 }
131 132
133 // TODO(yosin): We should replace
134 // |visibleSelection<EditingInFlatTreeStrategy>()| with
135 // |computeVisibleSelectionInFlatTree()|.
132 template <> 136 template <>
133 const VisibleSelectionInFlatTree& 137 const VisibleSelectionInFlatTree&
134 FrameSelection::visibleSelection<EditingInFlatTreeStrategy>() const { 138 FrameSelection::visibleSelection<EditingInFlatTreeStrategy>() const {
135 return m_selectionEditor->visibleSelection<EditingInFlatTreeStrategy>(); 139 return m_selectionEditor->visibleSelection<EditingInFlatTreeStrategy>();
136 } 140 }
137 141
142 const VisibleSelection& FrameSelection::computeVisibleSelectionInDOMTree()
143 const {
144 return m_selectionEditor->computeVisibleSelectionInDOMTree();
145 }
146
147 const VisibleSelectionInFlatTree&
148 FrameSelection::computeVisibleSelectionInFlatTree() const {
149 return m_selectionEditor->computeVisibleSelectionInFlatTree();
150 }
151
152 const SelectionInDOMTree& FrameSelection::selectionInDOMTree() const {
153 return m_selectionEditor->selectionInDOMTree();
154 }
155
138 Element* FrameSelection::rootEditableElementOrDocumentElement() const { 156 Element* FrameSelection::rootEditableElementOrDocumentElement() const {
139 Element* selectionRoot = selection().rootEditableElement(); 157 Element* selectionRoot = selection().rootEditableElement();
140 return selectionRoot ? selectionRoot : document().documentElement(); 158 return selectionRoot ? selectionRoot : document().documentElement();
141 } 159 }
142 160
143 ContainerNode* FrameSelection::rootEditableElementOrTreeScopeRootNode() const { 161 ContainerNode* FrameSelection::rootEditableElementOrTreeScopeRootNode() const {
144 Element* selectionRoot = selection().rootEditableElement(); 162 Element* selectionRoot = selection().rootEditableElement();
145 if (selectionRoot) 163 if (selectionRoot)
146 return selectionRoot; 164 return selectionRoot;
147 165
148 Node* node = selection().base().computeContainerNode(); 166 Node* node = selection().base().computeContainerNode();
149 return node ? &node->treeScope().rootNode() : 0; 167 return node ? &node->treeScope().rootNode() : 0;
150 } 168 }
151 169
170 // TODO(yosin): We should rename |FrameSelection::selection()| to
171 // |selectionDeprecated()|.
152 const VisibleSelection& FrameSelection::selection() const { 172 const VisibleSelection& FrameSelection::selection() const {
153 return visibleSelection<EditingStrategy>(); 173 // TODO(yosin): We should hoist updateStyleAndLayoutIgnorePendingStylesheets
174 // to caller. See http://crbug.com/590369 for more details.
175 document().updateStyleAndLayoutIgnorePendingStylesheets();
176 return computeVisibleSelectionInDOMTree();
154 } 177 }
155 178
156 const VisibleSelectionInFlatTree& FrameSelection::selectionInFlatTree() const { 179 const VisibleSelectionInFlatTree& FrameSelection::selectionInFlatTree() const {
157 return visibleSelection<EditingInFlatTreeStrategy>(); 180 return visibleSelection<EditingInFlatTreeStrategy>();
158 } 181 }
159 182
160 void FrameSelection::moveCaretSelection(const IntPoint& point) { 183 void FrameSelection::moveCaretSelection(const IntPoint& point) {
161 DCHECK(!document().needsLayoutTreeUpdate()); 184 DCHECK(!document().needsLayoutTreeUpdate());
162 185
163 Element* const editable = rootEditableElement(); 186 Element* const editable = rootEditableElement();
164 if (!editable) 187 if (!editable)
165 return; 188 return;
166 189
167 const VisiblePosition position = 190 const VisiblePosition position =
168 visiblePositionForContentsPoint(point, frame()); 191 visiblePositionForContentsPoint(point, frame());
169 SelectionInDOMTree::Builder builder; 192 SelectionInDOMTree::Builder builder;
170 builder.setIsDirectional(selection().isDirectional()); 193 builder.setIsDirectional(selection().isDirectional());
171 builder.setIsHandleVisible(true); 194 builder.setIsHandleVisible(true);
172 if (position.isNotNull()) 195 if (position.isNotNull())
173 builder.collapse(position.toPositionWithAffinity()); 196 builder.collapse(position.toPositionWithAffinity());
174 setSelection(builder.build(), CloseTyping | ClearTypingStyle | UserTriggered); 197 setSelection(builder.build(), CloseTyping | ClearTypingStyle | UserTriggered);
175 } 198 }
176 199
177 template <typename Strategy> 200 void FrameSelection::setSelection(const SelectionInDOMTree& passedSelection,
178 void FrameSelection::setSelectionAlgorithm( 201 SetSelectionOptions options,
179 const VisibleSelectionTemplate<Strategy>& newSelection, 202 CursorAlignOnScroll align,
180 HandleVisibility handleVisibility, 203 TextGranularity granularity) {
181 SetSelectionOptions options,
182 CursorAlignOnScroll align,
183 TextGranularity granularity) {
184 DCHECK(isAvailable()); 204 DCHECK(isAvailable());
185 DCHECK(newSelection.isValidFor(document())); 205 passedSelection.assertValidFor(document());
186 const Document& currentDocument = document(); 206
207 SelectionInDOMTree::Builder builder(passedSelection);
208 if (shouldAlwaysUseDirectionalSelection(m_frame))
209 builder.setIsDirectional(true);
210 SelectionInDOMTree newSelection = builder.build();
187 if (m_granularityStrategy && 211 if (m_granularityStrategy &&
188 (options & FrameSelection::DoNotClearStrategy) == 0) 212 (options & FrameSelection::DoNotClearStrategy) == 0)
189 m_granularityStrategy->Clear(); 213 m_granularityStrategy->Clear();
190 bool closeTyping = options & CloseTyping; 214 bool closeTyping = options & CloseTyping;
191 bool shouldClearTypingStyle = options & ClearTypingStyle; 215 bool shouldClearTypingStyle = options & ClearTypingStyle;
192 EUserTriggered userTriggered = selectionOptionsToUserTriggered(options);
193
194 // TODO(editing-dev): We should rename variable |s| to another name to avoid
195 // using one letter variable name.
196 VisibleSelectionTemplate<Strategy> s = newSelection;
197 if (shouldAlwaysUseDirectionalSelection(m_frame))
198 s.setIsDirectional(true);
199
200 m_granularity = granularity; 216 m_granularity = granularity;
201 217
202 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to 218 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
203 // |Editor| class. 219 // |Editor| class.
204 if (closeTyping) 220 if (closeTyping)
205 TypingCommand::closeTyping(m_frame); 221 TypingCommand::closeTyping(m_frame);
206 222
207 if (shouldClearTypingStyle) 223 if (shouldClearTypingStyle)
208 m_frame->editor().clearTypingStyle(); 224 m_frame->editor().clearTypingStyle();
209 225
210 if (m_selectionEditor->visibleSelection<Strategy>() == s && 226 const SelectionInDOMTree oldSelectionInDOMTree =
211 m_handleVisibility == handleVisibility) { 227 m_selectionEditor->selectionInDOMTree();
212 // Even if selection was not changed, selection offsets may have been 228 if (oldSelectionInDOMTree == newSelection)
213 // changed.
214 notifyLayoutObjectOfSelectionChange(userTriggered);
215 return; 229 return;
216 } 230 m_selectionEditor->setSelection(newSelection);
217
218 const VisibleSelectionTemplate<Strategy> oldSelection =
219 visibleSelection<Strategy>();
220 const Position& oldSelectionStart = selection().start();
221
222 m_handleVisibility = handleVisibility;
223 m_selectionEditor->setVisibleSelection(s, options);
224 scheduleVisualUpdateForPaintInvalidationIfNeeded(); 231 scheduleVisualUpdateForPaintInvalidationIfNeeded();
225 232
226 if (!s.isNone() && !(options & DoNotSetFocus)) { 233 // TODO(yosin): The use of updateStyleAndLayoutIgnorePendingStylesheets
234 // needs to be audited. see http://crbug.com/590369 for more details.
235 document().updateStyleAndLayoutIgnorePendingStylesheets();
236
237 const Document& currentDocument = document();
238 // TODO(yosin): We should get rid of unsued |options| for
239 // |Editor::respondToChangedSelection()|.
240 // Note: Since, setting focus can modify DOM tree, we should use
241 // |oldSelection| before setting focus
242 m_frame->editor().respondToChangedSelection(
243 createVisibleSelection(oldSelectionInDOMTree).start(), options);
244 DCHECK_EQ(currentDocument, document());
245
246 if (!selection().isNone() && !(options & DoNotSetFocus)) {
yoichio 2017/02/13 06:37:42 I prefer m_selectionEditor->computeVisibleSelectio
yosin_UTC9 2017/02/13 07:28:40 Done. BTW, I expect to change later to minimize s
227 setFocusedNodeIfNeeded(); 247 setFocusedNodeIfNeeded();
228 // |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and 248 // |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and
229 // "FocusIn", |m_frame| may associate to another document. 249 // "FocusIn", |m_frame| may associate to another document.
230 if (!isAvailable() || document() != currentDocument) { 250 if (!isAvailable() || document() != currentDocument) {
231 // Once we get test case to reach here, we should change this 251 // Once we get test case to reach here, we should change this
232 // if-statement to |DCHECK()|. 252 // if-statement to |DCHECK()|.
233 NOTREACHED(); 253 NOTREACHED();
234 return; 254 return;
235 } 255 }
236 } 256 }
237 257
238 if (!(options & DoNotUpdateAppearance)) { 258 if (!(options & DoNotUpdateAppearance)) {
239 m_frameCaret->stopCaretBlinkTimer(); 259 m_frameCaret->stopCaretBlinkTimer();
240 updateAppearance(); 260 updateAppearance();
241 } 261 }
242 262
243 // Always clear the x position used for vertical arrow navigation. 263 // Always clear the x position used for vertical arrow navigation.
244 // It will be restored by the vertical arrow navigation code if necessary. 264 // It will be restored by the vertical arrow navigation code if necessary.
245 m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation(); 265 m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
266 // TODO(yosin): Can we move this to at end of this function?
246 // This may dispatch a synchronous focus-related events. 267 // This may dispatch a synchronous focus-related events.
247 selectFrameElementInParentIfFullySelected(); 268 selectFrameElementInParentIfFullySelected();
248 if (!isAvailable() || document() != currentDocument) { 269 if (!isAvailable() || document() != currentDocument) {
249 // editing/selection/selectallchildren-crash.html and 270 // editing/selection/selectallchildren-crash.html and
250 // editing/selection/longpress-selection-in-iframe-removed-crash.html 271 // editing/selection/longpress-selection-in-iframe-removed-crash.html
251 // reach here. 272 // reach here.
252 return; 273 return;
253 } 274 }
275 EUserTriggered userTriggered = selectionOptionsToUserTriggered(options);
254 notifyLayoutObjectOfSelectionChange(userTriggered); 276 notifyLayoutObjectOfSelectionChange(userTriggered);
255 // If the selections are same in the DOM tree but not in the flat tree,
256 // don't fire events. For example, if the selection crosses shadow tree
257 // boundary, selection for the DOM tree is shrunk while that for the
258 // flat tree is not. Additionally, this case occurs in some edge cases.
259 // See also: editing/pasteboard/4076267-3.html
260 if (oldSelection == m_selectionEditor->visibleSelection<Strategy>())
261 return;
262
263 m_frame->editor().respondToChangedSelection(oldSelectionStart, options);
264 if (userTriggered == UserTriggered) { 277 if (userTriggered == UserTriggered) {
265 ScrollAlignment alignment; 278 ScrollAlignment alignment;
266 279
267 if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed()) 280 if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed())
268 alignment = (align == CursorAlignOnScroll::Always) 281 alignment = (align == CursorAlignOnScroll::Always)
269 ? ScrollAlignment::alignCenterAlways 282 ? ScrollAlignment::alignCenterAlways
270 : ScrollAlignment::alignCenterIfNeeded; 283 : ScrollAlignment::alignCenterIfNeeded;
271 else 284 else
272 alignment = (align == CursorAlignOnScroll::Always) 285 alignment = (align == CursorAlignOnScroll::Always)
273 ? ScrollAlignment::alignTopAlways 286 ? ScrollAlignment::alignTopAlways
274 : ScrollAlignment::alignToEdgeIfNeeded; 287 : ScrollAlignment::alignToEdgeIfNeeded;
275 288
289 // TODO(editing-dev): The use of
290 // updateStyleAndLayoutIgnorePendingStylesheets
291 // needs to be audited. See http://crbug.com/590369 for more details.
292 document().updateStyleAndLayoutIgnorePendingStylesheets();
293
276 revealSelection(alignment, RevealExtent); 294 revealSelection(alignment, RevealExtent);
277 } 295 }
278 296
279 notifyAccessibilityForSelectionChange(); 297 notifyAccessibilityForSelectionChange();
280 notifyCompositorForSelectionChange(); 298 notifyCompositorForSelectionChange();
281 notifyEventHandlerForSelectionChange(); 299 notifyEventHandlerForSelectionChange();
282 m_frame->domWindow()->enqueueDocumentEvent( 300 m_frame->domWindow()->enqueueDocumentEvent(
283 Event::create(EventTypeNames::selectionchange)); 301 Event::create(EventTypeNames::selectionchange));
284 } 302 }
285 303
286 // TODO(yosin): We will make |selectionInDOMTree| version of |SetSelection()|
287 // as primary function instead of wrapper.
288 void FrameSelection::setSelection(const SelectionInDOMTree& newSelection,
289 SetSelectionOptions options,
290 CursorAlignOnScroll align,
291 TextGranularity granularity) {
292 if (!newSelection.isNone()) {
293 // TODO(editing-dev): The use of
294 // updateStyleAndLayoutIgnorePendingStylesheets
295 // needs to be audited. See http://crbug.com/590369 for more details.
296 newSelection.base()
297 .document()
298 ->updateStyleAndLayoutIgnorePendingStylesheets();
299 }
300 setSelection(createVisibleSelection(newSelection),
301 newSelection.isHandleVisible() ? HandleVisibility::Visible
302 : HandleVisibility::NotVisible,
303 options, align, granularity);
304 }
305
306 // TODO(yosin): We will make |selectionInFlatTree| version of |SetSelection()|
307 // as primary function instead of wrapper.
308 void FrameSelection::setSelection(const SelectionInFlatTree& newSelection, 304 void FrameSelection::setSelection(const SelectionInFlatTree& newSelection,
309 SetSelectionOptions options, 305 SetSelectionOptions options,
310 CursorAlignOnScroll align, 306 CursorAlignOnScroll align,
311 TextGranularity granularity) { 307 TextGranularity granularity) {
312 if (!newSelection.isNone()) { 308 newSelection.assertValidFor(document());
313 // TODO(editing-dev): The use of 309 SelectionInDOMTree::Builder builder;
314 // updateStyleAndLayoutIgnorePendingStylesheets 310 builder.setAffinity(newSelection.affinity())
315 // needs to be audited. See http://crbug.com/590369 for more details. 311 .setBaseAndExtent(toPositionInDOMTree(newSelection.base()),
316 newSelection.base() 312 toPositionInDOMTree(newSelection.extent()))
317 .document() 313 .setGranularity(newSelection.granularity())
318 ->updateStyleAndLayoutIgnorePendingStylesheets(); 314 .setIsDirectional(newSelection.isDirectional())
319 } 315 .setIsHandleVisible(newSelection.isHandleVisible())
320 setSelection(createVisibleSelection(newSelection), 316 .setHasTrailingWhitespace(newSelection.hasTrailingWhitespace());
321 newSelection.isHandleVisible() ? HandleVisibility::Visible 317 return setSelection(builder.build(), options, align, granularity);
322 : HandleVisibility::NotVisible,
323 options, align, granularity);
324 } 318 }
325 319
326 void FrameSelection::setSelection(const VisibleSelection& newSelection, 320 void FrameSelection::setSelection(const VisibleSelection& newSelection,
327 HandleVisibility handleVisibility, 321 HandleVisibility handleVisibility,
328 SetSelectionOptions options, 322 SetSelectionOptions options,
329 CursorAlignOnScroll align, 323 CursorAlignOnScroll align,
330 TextGranularity granularity) { 324 TextGranularity granularity) {
331 setSelectionAlgorithm<EditingStrategy>(newSelection, handleVisibility, 325 setSelection(
332 options, align, granularity); 326 SelectionInDOMTree::Builder(newSelection.asSelection())
327 .setIsHandleVisible(handleVisibility == HandleVisibility::Visible)
328 .build(),
329 options, align, granularity);
333 } 330 }
334 331
335 void FrameSelection::setSelection(const VisibleSelection& newSelection, 332 void FrameSelection::setSelection(const VisibleSelection& newSelection,
336 SetSelectionOptions options) { 333 SetSelectionOptions options) {
337 setSelection(newSelection, HandleVisibility::NotVisible, options); 334 setSelection(newSelection.asSelection(), options);
338 } 335 }
339 336
340 void FrameSelection::setSelection( 337 void FrameSelection::setSelection(
341 const VisibleSelectionInFlatTree& newSelection, 338 const VisibleSelectionInFlatTree& newSelection,
342 HandleVisibility handleVisibility, 339 HandleVisibility handleVisibility,
343 SetSelectionOptions options, 340 SetSelectionOptions options,
344 CursorAlignOnScroll align, 341 CursorAlignOnScroll align,
345 TextGranularity granularity) { 342 TextGranularity granularity) {
346 setSelectionAlgorithm<EditingInFlatTreeStrategy>( 343 setSelection(
347 newSelection, handleVisibility, options, align, granularity); 344 SelectionInFlatTree::Builder(newSelection.asSelection())
345 .setIsHandleVisible(handleVisibility == HandleVisibility::Visible)
346 .build(),
347 options, align, granularity);
348 } 348 }
349 349
350 void FrameSelection::setSelection( 350 void FrameSelection::setSelection(
351 const VisibleSelectionInFlatTree& newSelection, 351 const VisibleSelectionInFlatTree& newSelection,
352 SetSelectionOptions options) { 352 SetSelectionOptions options) {
353 setSelection(newSelection, HandleVisibility::NotVisible, options); 353 setSelection(newSelection.asSelection(), options);
354 } 354 }
355 355
356 static bool removingNodeRemovesPosition(Node& node, const Position& position) { 356 // TODO(yosin): We should move |computePositionForChildrenRemoval()| to
357 if (!position.anchorNode()) 357 // "SelectionEditor.cpp" since it used only in
358 return false; 358 // |SelectionEditor::nodeChildrenWillBeRemoved()|.
359
360 if (position.anchorNode() == node)
361 return true;
362
363 if (!node.isElementNode())
364 return false;
365
366 Element& element = toElement(node);
367 return element.isShadowIncludingInclusiveAncestorOf(position.anchorNode());
368 }
369
370 static Position computePositionForChildrenRemoval(const Position& position, 359 static Position computePositionForChildrenRemoval(const Position& position,
371 ContainerNode& container) { 360 ContainerNode& container) {
372 Node* node = position.computeContainerNode(); 361 Node* node = position.computeContainerNode();
373 if (container.containsIncludingHostElements(*node)) 362 if (container.containsIncludingHostElements(*node))
374 return Position::firstPositionInNode(&container); 363 return Position::firstPositionInNode(&container);
375 return position; 364 return position;
376 } 365 }
377 366
378 void FrameSelection::nodeChildrenWillBeRemoved(ContainerNode& container) { 367 void FrameSelection::nodeChildrenWillBeRemoved(ContainerNode& container) {
379 if (isNone() || !container.inActiveDocument()) 368 if (!container.inActiveDocument())
380 return; 369 return;
381 const Position& oldStart = selection().start(); 370 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
382 const Position& newStart = 371 // |Editor| class.
383 computePositionForChildrenRemoval(oldStart, container); 372 if (!document().isRunningExecCommand())
384 const Position& oldEnd = selection().end(); 373 TypingCommand::closeTyping(m_frame);
385 const Position& newEnd = computePositionForChildrenRemoval(oldEnd, container); 374 }
386 const Position& oldBase = selection().base(); 375
376 // TODO(yosin): We should move |SelectionEditor::nodeChildrenWillBeRemoved()|
377 // to "SelectionEditor.cpp".
378 void SelectionEditor::nodeChildrenWillBeRemoved(ContainerNode& container) {
379 if (m_selection.isNone())
380 return;
381 const Position oldBase = m_selection.m_base;
382 const Position oldExtent = m_selection.m_extent;
387 const Position& newBase = 383 const Position& newBase =
388 computePositionForChildrenRemoval(oldBase, container); 384 computePositionForChildrenRemoval(oldBase, container);
389 const Position& oldExtent = selection().extent();
390 const Position& newExtent = 385 const Position& newExtent =
391 computePositionForChildrenRemoval(oldExtent, container); 386 computePositionForChildrenRemoval(oldExtent, container);
392 if (newStart == oldStart && newEnd == oldEnd && newBase == oldBase && 387 if (newBase == oldBase && newExtent == oldExtent)
393 newExtent == oldExtent)
394 return; 388 return;
395 if (selection().isBaseFirst()) 389 m_selection = SelectionInDOMTree::Builder()
396 m_selectionEditor->setWithoutValidation(newStart, newEnd); 390 .setBaseAndExtent(newBase, newExtent)
397 else 391 .build();
398 m_selectionEditor->setWithoutValidation(newEnd, newStart); 392 markCacheDirty();
399 if (document().isRunningExecCommand())
400 return;
401 TypingCommand::closeTyping(m_frame);
402 } 393 }
403 394
404 void FrameSelection::nodeWillBeRemoved(Node& node) { 395 void FrameSelection::nodeWillBeRemoved(Node& node) {
405 // There can't be a selection inside a fragment, so if a fragment's node is 396 // There can't be a selection inside a fragment, so if a fragment's node is
406 // being removed, the selection in the document that created the fragment 397 // being removed, the selection in the document that created the fragment
407 // needs no adjustment. 398 // needs no adjustment.
408 if (isNone() || !node.inActiveDocument()) 399 if (!node.inActiveDocument())
409 return; 400 return;
410
411 respondToNodeModification(
412 node, removingNodeRemovesPosition(node, selection().base()),
413 removingNodeRemovesPosition(node, selection().extent()),
414 removingNodeRemovesPosition(node, selection().start()),
415 removingNodeRemovesPosition(node, selection().end()));
416 }
417
418 static SelectionState selectionStateOf(const Node& node) {
419 const LayoutObject* layoutObject = node.layoutObject();
420 if (!layoutObject)
421 return SelectionNone;
422 return layoutObject->getSelectionState();
423 }
424
425 void FrameSelection::respondToNodeModification(Node& node,
426 bool baseRemoved,
427 bool extentRemoved,
428 bool startRemoved,
429 bool endRemoved) {
430 DCHECK(node.document().isActive()) << node;
431
432 bool clearLayoutTreeSelection = false;
433 bool clearDOMTreeSelection = false;
434
435 if (startRemoved || endRemoved) {
436 Position start = selection().start();
437 Position end = selection().end();
438 if (startRemoved)
439 updatePositionForNodeRemoval(start, node);
440 if (endRemoved)
441 updatePositionForNodeRemoval(end, node);
442
443 if (Position::commonAncestorTreeScope(start, end) && start.isNotNull() &&
444 end.isNotNull()) {
445 if (selection().isBaseFirst())
446 m_selectionEditor->setWithoutValidation(start, end);
447 else
448 m_selectionEditor->setWithoutValidation(end, start);
449 } else {
450 clearDOMTreeSelection = true;
451 }
452
453 clearLayoutTreeSelection = true;
454 } else if (baseRemoved || extentRemoved) {
455 // The base and/or extent are about to be removed, but the start and end
456 // aren't. Change the base and extent to the start and end, but don't
457 // re-validate the selection, since doing so could move the start and end
458 // into the node that is about to be removed.
459 if (selection().isBaseFirst())
460 m_selectionEditor->setWithoutValidation(selection().start(),
461 selection().end());
462 else
463 m_selectionEditor->setWithoutValidation(selection().end(),
464 selection().start());
465 } else if (selectionStateOf(node) != SelectionNone) {
466 // When node to be removed is part of selection, we invalidate
467 // selection to paint again.
468 // TODO(yosin): We should paint changed area only rather than whole
469 // selected range.
470 clearLayoutTreeSelection = true;
471 }
472
473 if (clearLayoutTreeSelection)
474 selection().start().document()->layoutViewItem().clearSelection();
475
476 if (clearDOMTreeSelection)
477 setSelection(SelectionInDOMTree(), DoNotSetFocus);
478
479 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to 401 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
480 // |Editor| class. 402 // |Editor| class.
481 if (!document().isRunningExecCommand()) 403 if (!document().isRunningExecCommand())
482 TypingCommand::closeTyping(m_frame); 404 TypingCommand::closeTyping(m_frame);
483 } 405 }
484 406
407 // TODO(yosin): We should move |updatePositionAfterAdoptingTextReplacement()|
408 // to "SelectionEditor.cpp" since it used only in
409 // |SelectionEditor::didUpdateCharacterData()|.
485 static Position updatePositionAfterAdoptingTextReplacement( 410 static Position updatePositionAfterAdoptingTextReplacement(
486 const Position& position, 411 const Position& position,
487 CharacterData* node, 412 CharacterData* node,
488 unsigned offset, 413 unsigned offset,
489 unsigned oldLength, 414 unsigned oldLength,
490 unsigned newLength) { 415 unsigned newLength) {
491 if (!position.anchorNode() || position.anchorNode() != node || 416 if (position.anchorNode() != node)
492 !position.isOffsetInAnchor())
493 return position; 417 return position;
494 418
419 if (position.isBeforeAnchor()) {
420 return updatePositionAfterAdoptingTextReplacement(
421 Position(node, 0), node, offset, oldLength, newLength);
422 }
423 if (position.isAfterAnchor()) {
424 return updatePositionAfterAdoptingTextReplacement(
425 Position(node, oldLength), node, offset, oldLength, newLength);
426 }
427
495 // See: 428 // See:
496 // http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range- Mutation 429 // http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range- Mutation
497 DCHECK_GE(position.offsetInContainerNode(), 0); 430 DCHECK_GE(position.offsetInContainerNode(), 0);
498 unsigned positionOffset = 431 unsigned positionOffset =
499 static_cast<unsigned>(position.offsetInContainerNode()); 432 static_cast<unsigned>(position.offsetInContainerNode());
500 // Replacing text can be viewed as a deletion followed by insertion. 433 // Replacing text can be viewed as a deletion followed by insertion.
501 if (positionOffset >= offset && positionOffset <= offset + oldLength) 434 if (positionOffset >= offset && positionOffset <= offset + oldLength)
502 positionOffset = offset; 435 positionOffset = offset;
503 436
504 // Adjust the offset if the position is after the end of the deleted contents 437 // Adjust the offset if the position is after the end of the deleted contents
505 // (positionOffset > offset + oldLength) to avoid having a stale offset. 438 // (positionOffset > offset + oldLength) to avoid having a stale offset.
506 if (positionOffset > offset + oldLength) 439 if (positionOffset > offset + oldLength)
507 positionOffset = positionOffset - oldLength + newLength; 440 positionOffset = positionOffset - oldLength + newLength;
508 441
509 // Due to case folding 442 // Due to case folding
510 // (http://unicode.org/Public/UCD/latest/ucd/CaseFolding.txt), LayoutText 443 // (http://unicode.org/Public/UCD/latest/ucd/CaseFolding.txt), LayoutText
511 // length may be different from Text length. A correct implementation would 444 // length may be different from Text length. A correct implementation would
512 // translate the LayoutText offset to a Text offset; this is just a safety 445 // translate the LayoutText offset to a Text offset; this is just a safety
513 // precaution to avoid offset values that run off the end of the Text. 446 // precaution to avoid offset values that run off the end of the Text.
514 if (positionOffset > node->length()) 447 if (positionOffset > node->length())
515 positionOffset = node->length(); 448 positionOffset = node->length();
516 449
517 // CharacterNode in VisibleSelection must be Text node, because Comment 450 return Position(node, positionOffset);
518 // and ProcessingInstruction node aren't visible.
519 return Position(toText(node), positionOffset);
520 } 451 }
521 452
522 void FrameSelection::didUpdateCharacterData(CharacterData* node, 453 // TODO(yosin): We should move |didUpdateCharacterData()| to
523 unsigned offset, 454 // "SelectionEditor.cpp".
524 unsigned oldLength, 455 void SelectionEditor::didUpdateCharacterData(CharacterData* node,
525 unsigned newLength) { 456 unsigned offset,
457 unsigned oldLength,
458 unsigned newLength) {
526 // The fragment check is a performance optimization. See 459 // The fragment check is a performance optimization. See
527 // http://trac.webkit.org/changeset/30062. 460 // http://trac.webkit.org/changeset/30062.
528 if (isNone() || !node || !node->isConnected()) 461 if (m_selection.isNone() || !node || !node->isConnected()) {
462 didFinishDOMMutation();
529 return; 463 return;
530 464 }
531 Position base = updatePositionAfterAdoptingTextReplacement( 465 const Position& newBase = updatePositionAfterAdoptingTextReplacement(
532 selection().base(), node, offset, oldLength, newLength); 466 m_selection.m_base, node, offset, oldLength, newLength);
533 Position extent = updatePositionAfterAdoptingTextReplacement( 467 const Position& newExtent = updatePositionAfterAdoptingTextReplacement(
534 selection().extent(), node, offset, oldLength, newLength); 468 m_selection.m_extent, node, offset, oldLength, newLength);
535 Position start = updatePositionAfterAdoptingTextReplacement( 469 didFinishTextChange(newBase, newExtent);
536 selection().start(), node, offset, oldLength, newLength);
537 Position end = updatePositionAfterAdoptingTextReplacement(
538 selection().end(), node, offset, oldLength, newLength);
539 updateSelectionIfNeeded(base, extent, start, end);
540 } 470 }
541 471
472 // TODO(yosin): We should move |updatePostionAfterAdoptingTextNodesMerged()|
473 // to "SelectionEditor.cpp" since it used only in
474 // |SelectionEditor::didMergeTextNodes()|.
542 static Position updatePostionAfterAdoptingTextNodesMerged( 475 static Position updatePostionAfterAdoptingTextNodesMerged(
yoichio 2017/02/13 06:37:42 How do you change this function and why?
yosin_UTC9 2017/02/13 07:28:40 Existing function doesn't consider |PositionAnchor
yoichio 2017/02/13 08:18:03 If this change is a kind of bugfixing, could you d
yosin_UTC9 2017/02/13 09:24:14 No this is required change to pass "selection-afte
543 const Position& position, 476 const Position& position,
544 const Text& oldNode, 477 const Text& mergedNode,
yoichio 2017/02/13 06:37:42 Just |Text* mergedNode| to avoid const_cast?
yosin_UTC9 2017/02/13 07:28:40 I would like to keep this |const_cast| since |didM
yoichio 2017/02/13 08:18:03 Acknowledged.
545 unsigned offset) { 478 const NodeWithIndex& nodeToBeRemovedWithIndex,
546 if (!position.anchorNode() || !position.isOffsetInAnchor()) 479 unsigned oldLength) {
547 return position; 480 Node* const anchorNode = position.anchorNode();
548 481 const Node& nodeToBeRemoved = nodeToBeRemovedWithIndex.node();
549 DCHECK_GE(position.offsetInContainerNode(), 0); 482 switch (position.anchorType()) {
550 unsigned positionOffset = 483 case PositionAnchorType::BeforeChildren:
551 static_cast<unsigned>(position.offsetInContainerNode()); 484 case PositionAnchorType::AfterChildren:
552 485 return position;
553 if (position.anchorNode() == &oldNode) 486 case PositionAnchorType::BeforeAnchor:
554 return Position(toText(oldNode.previousSibling()), positionOffset + offset); 487 if (anchorNode == nodeToBeRemoved)
555 488 return Position(const_cast<Text*>(&mergedNode), mergedNode.length());
556 if (position.anchorNode() == oldNode.parentNode() && positionOffset == offset) 489 return position;
557 return Position(toText(oldNode.previousSibling()), offset); 490 case PositionAnchorType::AfterAnchor:
558 491 if (anchorNode == nodeToBeRemoved)
492 return Position(const_cast<Text*>(&mergedNode), mergedNode.length());
493 if (anchorNode == mergedNode)
494 return Position(const_cast<Text*>(&mergedNode), oldLength);
495 return position;
496 case PositionAnchorType::OffsetInAnchor: {
497 const int offset = position.offsetInContainerNode();
498 if (anchorNode == nodeToBeRemoved)
499 return Position(const_cast<Text*>(&mergedNode), oldLength + offset);
500 if (anchorNode == nodeToBeRemoved.parentNode() &&
501 offset == nodeToBeRemovedWithIndex.index()) {
502 return Position(const_cast<Text*>(&mergedNode), oldLength);
503 }
504 return position;
505 }
506 }
507 NOTREACHED() << position;
559 return position; 508 return position;
560 } 509 }
561 510
562 void FrameSelection::didMergeTextNodes( 511 // TODO(yosin): We should move |SelectionEditor::didMergeTextNodes()| to
512 // "SelectionEditor.cpp".
513 void SelectionEditor::didMergeTextNodes(
563 const Text& mergedNode, 514 const Text& mergedNode,
564 const NodeWithIndex& nodeToBeRemovedWithIndex, 515 const NodeWithIndex& nodeToBeRemovedWithIndex,
565 unsigned offset) { 516 unsigned oldLength) {
566 const Text& oldNode = toText(nodeToBeRemovedWithIndex.node()); 517 if (m_selection.isNone()) {
567 if (isNone() || !oldNode.isConnected()) 518 didFinishDOMMutation();
568 return; 519 return;
569 Position base = updatePostionAfterAdoptingTextNodesMerged(selection().base(), 520 }
570 oldNode, offset); 521 const Position& newBase = updatePostionAfterAdoptingTextNodesMerged(
571 Position extent = updatePostionAfterAdoptingTextNodesMerged( 522 m_selection.m_base, mergedNode, nodeToBeRemovedWithIndex, oldLength);
572 selection().extent(), oldNode, offset); 523 const Position& newExtent = updatePostionAfterAdoptingTextNodesMerged(
573 Position start = updatePostionAfterAdoptingTextNodesMerged( 524 m_selection.m_extent, mergedNode, nodeToBeRemovedWithIndex, oldLength);
574 selection().start(), oldNode, offset); 525 didFinishTextChange(newBase, newExtent);
575 Position end = updatePostionAfterAdoptingTextNodesMerged(selection().end(),
576 oldNode, offset);
577 updateSelectionIfNeeded(base, extent, start, end);
578 } 526 }
579 527
528 // TODO(yosin): We should move |updatePostionAfterAdoptingTextNodeSplit()|
529 // to "SelectionEditor.cpp" since it used only in
530 // |SelectionEditor::didSplitTextNode()|.
580 static Position updatePostionAfterAdoptingTextNodeSplit( 531 static Position updatePostionAfterAdoptingTextNodeSplit(
581 const Position& position, 532 const Position& position,
582 const Text& oldNode) { 533 const Text& oldNode) {
583 if (!position.anchorNode() || position.anchorNode() != &oldNode || 534 if (!position.anchorNode() || position.anchorNode() != &oldNode ||
584 !position.isOffsetInAnchor()) 535 !position.isOffsetInAnchor())
585 return position; 536 return position;
586 // See: 537 // See:
587 // http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range- Mutation 538 // http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range- Mutation
588 DCHECK_GE(position.offsetInContainerNode(), 0); 539 DCHECK_GE(position.offsetInContainerNode(), 0);
589 unsigned positionOffset = 540 unsigned positionOffset =
590 static_cast<unsigned>(position.offsetInContainerNode()); 541 static_cast<unsigned>(position.offsetInContainerNode());
591 unsigned oldLength = oldNode.length(); 542 unsigned oldLength = oldNode.length();
592 if (positionOffset <= oldLength) 543 if (positionOffset <= oldLength)
593 return position; 544 return position;
594 return Position(toText(oldNode.nextSibling()), positionOffset - oldLength); 545 return Position(toText(oldNode.nextSibling()), positionOffset - oldLength);
595 } 546 }
596 547
597 void FrameSelection::didSplitTextNode(const Text& oldNode) { 548 // TODO(yosin): We should move |SelectionEditor::didSplitTextNode()| to
598 if (isNone() || !oldNode.isConnected()) 549 // "SelectionEditor.cpp".
550 void SelectionEditor::didSplitTextNode(const Text& oldNode) {
551 if (m_selection.isNone() || !oldNode.isConnected()) {
552 didFinishDOMMutation();
599 return; 553 return;
600 Position base = 554 }
601 updatePostionAfterAdoptingTextNodeSplit(selection().base(), oldNode); 555 const Position& newBase =
602 Position extent = 556 updatePostionAfterAdoptingTextNodeSplit(m_selection.m_base, oldNode);
603 updatePostionAfterAdoptingTextNodeSplit(selection().extent(), oldNode); 557 const Position& newExtent =
604 Position start = 558 updatePostionAfterAdoptingTextNodeSplit(m_selection.m_extent, oldNode);
605 updatePostionAfterAdoptingTextNodeSplit(selection().start(), oldNode); 559 didFinishTextChange(newBase, newExtent);
606 Position end =
607 updatePostionAfterAdoptingTextNodeSplit(selection().end(), oldNode);
608 updateSelectionIfNeeded(base, extent, start, end);
609 }
610
611 void FrameSelection::updateSelectionIfNeeded(const Position& base,
612 const Position& extent,
613 const Position& start,
614 const Position& end) {
615 if (base == selection().base() && extent == selection().extent() &&
616 start == selection().start() && end == selection().end())
617 return;
618 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
619 // |Editor| class.
620 if (!document().isRunningExecCommand())
621 TypingCommand::closeTyping(m_frame);
622 VisibleSelection newSelection;
623 if (selection().isBaseFirst())
624 newSelection.setWithoutValidation(start, end);
625 else
626 newSelection.setWithoutValidation(end, start);
627 setSelection(newSelection, DoNotSetFocus);
628 } 560 }
629 561
630 void FrameSelection::didChangeFocus() { 562 void FrameSelection::didChangeFocus() {
631 // Hits in 563 // Hits in
632 // virtual/gpu/compositedscrolling/scrollbars/scrollbar-miss-mousemove-disable d.html 564 // virtual/gpu/compositedscrolling/scrollbars/scrollbar-miss-mousemove-disable d.html
633 DisableCompositingQueryAsserts disabler; 565 DisableCompositingQueryAsserts disabler;
634 updateAppearance(); 566 updateAppearance();
635 } 567 }
636 568
637 static DispatchEventResult dispatchSelectStart( 569 static DispatchEventResult dispatchSelectStart(
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 } 656 }
725 657
726 void FrameSelection::contextDestroyed(Document* document) { 658 void FrameSelection::contextDestroyed(Document* document) {
727 m_granularity = CharacterGranularity; 659 m_granularity = CharacterGranularity;
728 660
729 LayoutViewItem view = m_frame->contentLayoutItem(); 661 LayoutViewItem view = m_frame->contentLayoutItem();
730 if (!view.isNull()) 662 if (!view.isNull())
731 view.clearSelection(); 663 view.clearSelection();
732 664
733 m_frame->editor().clearTypingStyle(); 665 m_frame->editor().clearTypingStyle();
734 m_selectionEditor->documentDetached(*document);
735 } 666 }
736 667
737 void FrameSelection::clearPreviousCaretVisualRect(const LayoutBlock& block) { 668 void FrameSelection::clearPreviousCaretVisualRect(const LayoutBlock& block) {
738 m_frameCaret->clearPreviousVisualRect(block); 669 m_frameCaret->clearPreviousVisualRect(block);
739 } 670 }
740 671
741 void FrameSelection::layoutBlockWillBeDestroyed(const LayoutBlock& block) { 672 void FrameSelection::layoutBlockWillBeDestroyed(const LayoutBlock& block) {
742 m_frameCaret->layoutBlockWillBeDestroyed(block); 673 m_frameCaret->layoutBlockWillBeDestroyed(block);
743 } 674 }
744 675
745 void FrameSelection::updateStyleAndLayoutIfNeeded() { 676 void FrameSelection::updateStyleAndLayoutIfNeeded() {
746 m_frameCaret->updateStyleAndLayoutIfNeeded(); 677 m_frameCaret->updateStyleAndLayoutIfNeeded();
747 } 678 }
748 679
749 void FrameSelection::invalidatePaintIfNeeded( 680 void FrameSelection::invalidatePaintIfNeeded(
750 const LayoutBlock& block, 681 const LayoutBlock& block,
751 const PaintInvalidatorContext& context, 682 const PaintInvalidatorContext& context,
752 PaintInvalidationReason reason) { 683 PaintInvalidationReason reason) {
753 m_frameCaret->invalidatePaintIfNeeded(block, context, reason); 684 m_frameCaret->invalidatePaintIfNeeded(block, context, reason);
754 } 685 }
755 686
756 bool FrameSelection::shouldPaintCaret(const LayoutBlock& block) const { 687 bool FrameSelection::shouldPaintCaret(const LayoutBlock& block) const {
757 DCHECK(selection().isValidFor(document())); 688 DCHECK_GE(document().lifecycle().state(), DocumentLifecycle::LayoutClean);
758
759 bool result = m_frameCaret->shouldPaintCaret(block); 689 bool result = m_frameCaret->shouldPaintCaret(block);
760 DCHECK(!result || (isCaret() && hasEditableStyle())); 690 DCHECK(!result || (isCaret() && hasEditableStyle()));
761 return result; 691 return result;
762 } 692 }
763 693
764 IntRect FrameSelection::absoluteCaretBounds() { 694 IntRect FrameSelection::absoluteCaretBounds() {
765 DCHECK(selection().isValidFor(*m_frame->document())); 695 DCHECK(selection().isValidFor(*m_frame->document()));
766 return m_frameCaret->absoluteCaretBounds(); 696 return m_frameCaret->absoluteCaretBounds();
767 } 697 }
768 698
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 998
1069 void FrameSelection::commitAppearanceIfNeeded(LayoutView& layoutView) { 999 void FrameSelection::commitAppearanceIfNeeded(LayoutView& layoutView) {
1070 return m_pendingSelection->commit(layoutView); 1000 return m_pendingSelection->commit(layoutView);
1071 } 1001 }
1072 1002
1073 void FrameSelection::didLayout() { 1003 void FrameSelection::didLayout() {
1074 updateAppearance(); 1004 updateAppearance();
1075 } 1005 }
1076 1006
1077 void FrameSelection::updateAppearance() { 1007 void FrameSelection::updateAppearance() {
1078 m_frameCaret->updateAppearance(); 1008 DCHECK(!m_frame->contentLayoutItem().isNull());
1079 1009 m_frameCaret->scheduleVisualUpdateForPaintInvalidationIfNeeded();
1080 if (m_frame->contentLayoutItem().isNull())
1081 return;
1082 m_pendingSelection->setHasPendingSelection(); 1010 m_pendingSelection->setHasPendingSelection();
1083 } 1011 }
1084 1012
1085 void FrameSelection::notifyLayoutObjectOfSelectionChange( 1013 void FrameSelection::notifyLayoutObjectOfSelectionChange(
1086 EUserTriggered userTriggered) { 1014 EUserTriggered userTriggered) {
1087 if (TextControlElement* textControl = enclosingTextControl(start())) 1015 if (TextControlElement* textControl = enclosingTextControl(start()))
1088 textControl->selectionChanged(userTriggered == UserTriggered); 1016 textControl->selectionChanged(userTriggered == UserTriggered);
1089 } 1017 }
1090 1018
1091 // Helper function that tells whether a particular node is an element that has 1019 // Helper function that tells whether a particular node is an element that has
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 1202
1275 Document* document = m_frame->document(); 1203 Document* document = m_frame->document();
1276 if (!isNone() || !(blink::hasEditableStyle(*document))) 1204 if (!isNone() || !(blink::hasEditableStyle(*document)))
1277 return; 1205 return;
1278 1206
1279 Element* documentElement = document->documentElement(); 1207 Element* documentElement = document->documentElement();
1280 if (!documentElement) 1208 if (!documentElement)
1281 return; 1209 return;
1282 if (HTMLBodyElement* body = 1210 if (HTMLBodyElement* body =
1283 Traversal<HTMLBodyElement>::firstChild(*documentElement)) { 1211 Traversal<HTMLBodyElement>::firstChild(*documentElement)) {
1284 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
1285 // needs to be audited. See http://crbug.com/590369 for more details.
1286 document->updateStyleAndLayoutIgnorePendingStylesheets();
1287
1288 setSelection(SelectionInDOMTree::Builder() 1212 setSelection(SelectionInDOMTree::Builder()
1289 .collapse(firstPositionInOrBeforeNode(body)) 1213 .collapse(firstPositionInOrBeforeNode(body))
1290 .build()); 1214 .build());
1291 } 1215 }
1292 } 1216 }
1293 1217
1294 // TODO(yoichio): We should have LocalFrame having FrameCaret, 1218 // TODO(yoichio): We should have LocalFrame having FrameCaret,
1295 // Editor and PendingSelection using FrameCaret directly 1219 // Editor and PendingSelection using FrameCaret directly
1296 // and get rid of this. 1220 // and get rid of this.
1297 bool FrameSelection::shouldShowBlockCursor() const { 1221 bool FrameSelection::shouldShowBlockCursor() const {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1388 FrameSelection::DoNotClearStrategy | UserTriggered, 1312 FrameSelection::DoNotClearStrategy | UserTriggered,
1389 CursorAlignOnScroll::IfNeeded, CharacterGranularity); 1313 CursorAlignOnScroll::IfNeeded, CharacterGranularity);
1390 } 1314 }
1391 1315
1392 // TODO(yosin): We should make |FrameSelection::moveRangeSelection()| to take 1316 // TODO(yosin): We should make |FrameSelection::moveRangeSelection()| to take
1393 // two |IntPoint| instead of two |VisiblePosition| like 1317 // two |IntPoint| instead of two |VisiblePosition| like
1394 // |moveRangeSelectionExtent()|. 1318 // |moveRangeSelectionExtent()|.
1395 void FrameSelection::moveRangeSelection(const VisiblePosition& basePosition, 1319 void FrameSelection::moveRangeSelection(const VisiblePosition& basePosition,
1396 const VisiblePosition& extentPosition, 1320 const VisiblePosition& extentPosition,
1397 TextGranularity granularity) { 1321 TextGranularity granularity) {
1398 VisibleSelection newSelection = createVisibleSelection( 1322 SelectionInDOMTree newSelection =
1399 SelectionInDOMTree::Builder() 1323 SelectionInDOMTree::Builder()
1400 .setBaseAndExtentDeprecated(basePosition.deepEquivalent(), 1324 .setBaseAndExtentDeprecated(basePosition.deepEquivalent(),
1401 extentPosition.deepEquivalent()) 1325 extentPosition.deepEquivalent())
1402 .setAffinity(basePosition.affinity()) 1326 .setAffinity(basePosition.affinity())
1403 .setGranularity(granularity) 1327 .setGranularity(granularity)
1404 .build()); 1328 .setIsHandleVisible(isHandleVisible())
1329 .build();
1405 1330
1406 if (newSelection.isNone()) 1331 if (newSelection.isNone())
1407 return; 1332 return;
1408 1333
1409 setSelection(newSelection, m_handleVisibility, CloseTyping | ClearTypingStyle, 1334 setSelection(newSelection, CloseTyping | ClearTypingStyle,
1410 CursorAlignOnScroll::IfNeeded, granularity); 1335 CursorAlignOnScroll::IfNeeded, granularity);
1411 } 1336 }
1412 1337
1413 void FrameSelection::updateIfNeeded() { 1338 void FrameSelection::updateIfNeeded() {
1414 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); 1339 DCHECK(!m_frame->document()->needsLayoutTreeUpdate());
1415 m_selectionEditor->updateIfNeeded(); 1340 m_selectionEditor->updateIfNeeded();
1416 } 1341 }
1417 1342
1418 void FrameSelection::setCaretVisible(bool caretIsVisible) { 1343 void FrameSelection::setCaretVisible(bool caretIsVisible) {
1419 m_frameCaret->setCaretVisibility(caretIsVisible ? CaretVisibility::Visible 1344 m_frameCaret->setCaretVisibility(caretIsVisible ? CaretVisibility::Visible
(...skipping 29 matching lines...) Expand all
1449 } 1374 }
1450 1375
1451 void showTree(const blink::FrameSelection* sel) { 1376 void showTree(const blink::FrameSelection* sel) {
1452 if (sel) 1377 if (sel)
1453 sel->showTreeForThis(); 1378 sel->showTreeForThis();
1454 else 1379 else
1455 LOG(INFO) << "Cannot showTree for <null> FrameSelection."; 1380 LOG(INFO) << "Cannot showTree for <null> FrameSelection.";
1456 } 1381 }
1457 1382
1458 #endif 1383 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698