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

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

Issue 2694823002: Revert of Make FrameSelection to hold non-canonicalized positions (Closed)
Patch Set: Merge branch 'master' of https://chromium.googlesource.com/chromium/src into patch_revert 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 Document& FrameSelection::document() const { 113 const Document& FrameSelection::document() const {
114 DCHECK(lifecycleContext()); 114 DCHECK(lifecycleContext());
115 return *lifecycleContext(); 115 return *lifecycleContext();
116 } 116 }
117 117
118 bool FrameSelection::isHandleVisible() const { 118 Document& FrameSelection::document() {
119 return selectionInDOMTree().isHandleVisible(); 119 DCHECK(lifecycleContext());
120 return *lifecycleContext();
120 } 121 }
121 122
122 // TODO(yosin): We should replace |visibleSelection<EditingStrategy>()| to
123 // |computeVisibleSelectionInDOMTree()|.
124 // TODO(yosin): To avoid undefined symbols in clang, we explicitly 123 // TODO(yosin): To avoid undefined symbols in clang, we explicitly
125 // have specialized version of |FrameSelection::visibleSelection<Strategy>| 124 // have specialized version of |FrameSelection::visibleSelection<Strategy>|
126 // before |FrameSelection::selection()| which refers this. 125 // before |FrameSelection::selection()| which refers this.
127 template <> 126 template <>
128 const VisibleSelection& FrameSelection::visibleSelection<EditingStrategy>() 127 const VisibleSelection& FrameSelection::visibleSelection<EditingStrategy>()
129 const { 128 const {
130 return m_selectionEditor->visibleSelection<EditingStrategy>(); 129 return m_selectionEditor->visibleSelection<EditingStrategy>();
131 } 130 }
132 131
133 // TODO(yosin): We should replace
134 // |visibleSelection<EditingInFlatTreeStrategy>()| with
135 // |computeVisibleSelectionInFlatTree()|.
136 template <> 132 template <>
137 const VisibleSelectionInFlatTree& 133 const VisibleSelectionInFlatTree&
138 FrameSelection::visibleSelection<EditingInFlatTreeStrategy>() const { 134 FrameSelection::visibleSelection<EditingInFlatTreeStrategy>() const {
139 return m_selectionEditor->visibleSelection<EditingInFlatTreeStrategy>(); 135 return m_selectionEditor->visibleSelection<EditingInFlatTreeStrategy>();
140 } 136 }
141 137
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
156 Element* FrameSelection::rootEditableElementOrDocumentElement() const { 138 Element* FrameSelection::rootEditableElementOrDocumentElement() const {
157 Element* selectionRoot = selection().rootEditableElement(); 139 Element* selectionRoot = selection().rootEditableElement();
158 return selectionRoot ? selectionRoot : document().documentElement(); 140 return selectionRoot ? selectionRoot : document().documentElement();
159 } 141 }
160 142
161 ContainerNode* FrameSelection::rootEditableElementOrTreeScopeRootNode() const { 143 ContainerNode* FrameSelection::rootEditableElementOrTreeScopeRootNode() const {
162 Element* selectionRoot = selection().rootEditableElement(); 144 Element* selectionRoot = selection().rootEditableElement();
163 if (selectionRoot) 145 if (selectionRoot)
164 return selectionRoot; 146 return selectionRoot;
165 147
166 Node* node = selection().base().computeContainerNode(); 148 Node* node = selection().base().computeContainerNode();
167 return node ? &node->treeScope().rootNode() : 0; 149 return node ? &node->treeScope().rootNode() : 0;
168 } 150 }
169 151
170 // TODO(yosin): We should rename |FrameSelection::selection()| to
171 // |selectionDeprecated()|.
172 const VisibleSelection& FrameSelection::selection() const { 152 const VisibleSelection& FrameSelection::selection() const {
173 // TODO(yosin): We should hoist updateStyleAndLayoutIgnorePendingStylesheets 153 return visibleSelection<EditingStrategy>();
174 // to caller. See http://crbug.com/590369 for more details.
175 document().updateStyleAndLayoutIgnorePendingStylesheets();
176 return computeVisibleSelectionInDOMTree();
177 } 154 }
178 155
179 const VisibleSelectionInFlatTree& FrameSelection::selectionInFlatTree() const { 156 const VisibleSelectionInFlatTree& FrameSelection::selectionInFlatTree() const {
180 return visibleSelection<EditingInFlatTreeStrategy>(); 157 return visibleSelection<EditingInFlatTreeStrategy>();
181 } 158 }
182 159
183 void FrameSelection::moveCaretSelection(const IntPoint& point) { 160 void FrameSelection::moveCaretSelection(const IntPoint& point) {
184 DCHECK(!document().needsLayoutTreeUpdate()); 161 DCHECK(!document().needsLayoutTreeUpdate());
185 162
186 Element* const editable = rootEditableElement(); 163 Element* const editable = rootEditableElement();
187 if (!editable) 164 if (!editable)
188 return; 165 return;
189 166
190 const VisiblePosition position = 167 const VisiblePosition position =
191 visiblePositionForContentsPoint(point, frame()); 168 visiblePositionForContentsPoint(point, frame());
192 SelectionInDOMTree::Builder builder; 169 SelectionInDOMTree::Builder builder;
193 builder.setIsDirectional(selection().isDirectional()); 170 builder.setIsDirectional(selection().isDirectional());
194 builder.setIsHandleVisible(true); 171 builder.setIsHandleVisible(true);
195 if (position.isNotNull()) 172 if (position.isNotNull())
196 builder.collapse(position.toPositionWithAffinity()); 173 builder.collapse(position.toPositionWithAffinity());
197 setSelection(builder.build(), CloseTyping | ClearTypingStyle | UserTriggered); 174 setSelection(builder.build(), CloseTyping | ClearTypingStyle | UserTriggered);
198 } 175 }
199 176
200 void FrameSelection::setSelection(const SelectionInDOMTree& passedSelection, 177 template <typename Strategy>
201 SetSelectionOptions options, 178 void FrameSelection::setSelectionAlgorithm(
202 CursorAlignOnScroll align, 179 const VisibleSelectionTemplate<Strategy>& newSelection,
203 TextGranularity granularity) { 180 HandleVisibility handleVisibility,
181 SetSelectionOptions options,
182 CursorAlignOnScroll align,
183 TextGranularity granularity) {
204 DCHECK(isAvailable()); 184 DCHECK(isAvailable());
205 passedSelection.assertValidFor(document()); 185 DCHECK(newSelection.isValidFor(document()));
206 186 const Document& currentDocument = document();
207 SelectionInDOMTree::Builder builder(passedSelection);
208 if (shouldAlwaysUseDirectionalSelection(m_frame))
209 builder.setIsDirectional(true);
210 SelectionInDOMTree newSelection = builder.build();
211 if (m_granularityStrategy && 187 if (m_granularityStrategy &&
212 (options & FrameSelection::DoNotClearStrategy) == 0) 188 (options & FrameSelection::DoNotClearStrategy) == 0)
213 m_granularityStrategy->Clear(); 189 m_granularityStrategy->Clear();
214 bool closeTyping = options & CloseTyping; 190 bool closeTyping = options & CloseTyping;
215 bool shouldClearTypingStyle = options & ClearTypingStyle; 191 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
216 m_granularity = granularity; 200 m_granularity = granularity;
217 201
218 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to 202 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
219 // |Editor| class. 203 // |Editor| class.
220 if (closeTyping) 204 if (closeTyping)
221 TypingCommand::closeTyping(m_frame); 205 TypingCommand::closeTyping(m_frame);
222 206
223 if (shouldClearTypingStyle) 207 if (shouldClearTypingStyle)
224 m_frame->editor().clearTypingStyle(); 208 m_frame->editor().clearTypingStyle();
225 209
226 const SelectionInDOMTree oldSelectionInDOMTree = 210 if (m_selectionEditor->visibleSelection<Strategy>() == s &&
227 m_selectionEditor->selectionInDOMTree(); 211 m_handleVisibility == handleVisibility) {
228 if (oldSelectionInDOMTree == newSelection) 212 // Even if selection was not changed, selection offsets may have been
213 // changed.
214 notifyLayoutObjectOfSelectionChange(userTriggered);
229 return; 215 return;
230 m_selectionEditor->setSelection(newSelection); 216 }
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);
231 scheduleVisualUpdateForPaintInvalidationIfNeeded(); 224 scheduleVisualUpdateForPaintInvalidationIfNeeded();
232 225
233 // TODO(yosin): The use of updateStyleAndLayoutIgnorePendingStylesheets 226 if (!s.isNone() && !(options & DoNotSetFocus)) {
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 (!computeVisibleSelectionInDOMTree().isNone() &&
247 !(options & DoNotSetFocus)) {
248 setFocusedNodeIfNeeded(); 227 setFocusedNodeIfNeeded();
249 // |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and 228 // |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and
250 // "FocusIn", |m_frame| may associate to another document. 229 // "FocusIn", |m_frame| may associate to another document.
251 if (!isAvailable() || document() != currentDocument) { 230 if (!isAvailable() || document() != currentDocument) {
252 // Once we get test case to reach here, we should change this 231 // Once we get test case to reach here, we should change this
253 // if-statement to |DCHECK()|. 232 // if-statement to |DCHECK()|.
254 NOTREACHED(); 233 NOTREACHED();
255 return; 234 return;
256 } 235 }
257 } 236 }
258 237
259 if (!(options & DoNotUpdateAppearance)) { 238 if (!(options & DoNotUpdateAppearance)) {
260 m_frameCaret->stopCaretBlinkTimer(); 239 m_frameCaret->stopCaretBlinkTimer();
261 updateAppearance(); 240 updateAppearance();
262 } 241 }
263 242
264 // Always clear the x position used for vertical arrow navigation. 243 // Always clear the x position used for vertical arrow navigation.
265 // It will be restored by the vertical arrow navigation code if necessary. 244 // It will be restored by the vertical arrow navigation code if necessary.
266 m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation(); 245 m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
267 // TODO(yosin): Can we move this to at end of this function?
268 // This may dispatch a synchronous focus-related events. 246 // This may dispatch a synchronous focus-related events.
269 selectFrameElementInParentIfFullySelected(); 247 selectFrameElementInParentIfFullySelected();
270 if (!isAvailable() || document() != currentDocument) { 248 if (!isAvailable() || document() != currentDocument) {
271 // editing/selection/selectallchildren-crash.html and 249 // editing/selection/selectallchildren-crash.html and
272 // editing/selection/longpress-selection-in-iframe-removed-crash.html 250 // editing/selection/longpress-selection-in-iframe-removed-crash.html
273 // reach here. 251 // reach here.
274 return; 252 return;
275 } 253 }
276 EUserTriggered userTriggered = selectionOptionsToUserTriggered(options);
277 notifyLayoutObjectOfSelectionChange(userTriggered); 254 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);
278 if (userTriggered == UserTriggered) { 264 if (userTriggered == UserTriggered) {
279 ScrollAlignment alignment; 265 ScrollAlignment alignment;
280 266
281 if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed()) 267 if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed())
282 alignment = (align == CursorAlignOnScroll::Always) 268 alignment = (align == CursorAlignOnScroll::Always)
283 ? ScrollAlignment::alignCenterAlways 269 ? ScrollAlignment::alignCenterAlways
284 : ScrollAlignment::alignCenterIfNeeded; 270 : ScrollAlignment::alignCenterIfNeeded;
285 else 271 else
286 alignment = (align == CursorAlignOnScroll::Always) 272 alignment = (align == CursorAlignOnScroll::Always)
287 ? ScrollAlignment::alignTopAlways 273 ? ScrollAlignment::alignTopAlways
288 : ScrollAlignment::alignToEdgeIfNeeded; 274 : ScrollAlignment::alignToEdgeIfNeeded;
289 275
290 // TODO(editing-dev): The use of
291 // updateStyleAndLayoutIgnorePendingStylesheets
292 // needs to be audited. See http://crbug.com/590369 for more details.
293 document().updateStyleAndLayoutIgnorePendingStylesheets();
294
295 revealSelection(alignment, RevealExtent); 276 revealSelection(alignment, RevealExtent);
296 } 277 }
297 278
298 notifyAccessibilityForSelectionChange(); 279 notifyAccessibilityForSelectionChange();
299 notifyCompositorForSelectionChange(); 280 notifyCompositorForSelectionChange();
300 notifyEventHandlerForSelectionChange(); 281 notifyEventHandlerForSelectionChange();
301 m_frame->domWindow()->enqueueDocumentEvent( 282 m_frame->domWindow()->enqueueDocumentEvent(
302 Event::create(EventTypeNames::selectionchange)); 283 Event::create(EventTypeNames::selectionchange));
303 } 284 }
304 285
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.
305 void FrameSelection::setSelection(const SelectionInFlatTree& newSelection, 308 void FrameSelection::setSelection(const SelectionInFlatTree& newSelection,
306 SetSelectionOptions options, 309 SetSelectionOptions options,
307 CursorAlignOnScroll align, 310 CursorAlignOnScroll align,
308 TextGranularity granularity) { 311 TextGranularity granularity) {
309 newSelection.assertValidFor(document()); 312 if (!newSelection.isNone()) {
310 SelectionInDOMTree::Builder builder; 313 // TODO(editing-dev): The use of
311 builder.setAffinity(newSelection.affinity()) 314 // updateStyleAndLayoutIgnorePendingStylesheets
312 .setBaseAndExtent(toPositionInDOMTree(newSelection.base()), 315 // needs to be audited. See http://crbug.com/590369 for more details.
313 toPositionInDOMTree(newSelection.extent())) 316 newSelection.base()
314 .setGranularity(newSelection.granularity()) 317 .document()
315 .setIsDirectional(newSelection.isDirectional()) 318 ->updateStyleAndLayoutIgnorePendingStylesheets();
316 .setIsHandleVisible(newSelection.isHandleVisible()) 319 }
317 .setHasTrailingWhitespace(newSelection.hasTrailingWhitespace()); 320 setSelection(createVisibleSelection(newSelection),
318 return setSelection(builder.build(), options, align, granularity); 321 newSelection.isHandleVisible() ? HandleVisibility::Visible
322 : HandleVisibility::NotVisible,
323 options, align, granularity);
319 } 324 }
320 325
321 void FrameSelection::setSelection(const VisibleSelection& newSelection, 326 void FrameSelection::setSelection(const VisibleSelection& newSelection,
322 HandleVisibility handleVisibility, 327 HandleVisibility handleVisibility,
323 SetSelectionOptions options, 328 SetSelectionOptions options,
324 CursorAlignOnScroll align, 329 CursorAlignOnScroll align,
325 TextGranularity granularity) { 330 TextGranularity granularity) {
326 setSelection( 331 setSelectionAlgorithm<EditingStrategy>(newSelection, handleVisibility,
327 SelectionInDOMTree::Builder(newSelection.asSelection()) 332 options, align, granularity);
328 .setIsHandleVisible(handleVisibility == HandleVisibility::Visible)
329 .build(),
330 options, align, granularity);
331 } 333 }
332 334
333 void FrameSelection::setSelection(const VisibleSelection& newSelection, 335 void FrameSelection::setSelection(const VisibleSelection& newSelection,
334 SetSelectionOptions options) { 336 SetSelectionOptions options) {
335 setSelection(newSelection.asSelection(), options); 337 setSelection(newSelection, HandleVisibility::NotVisible, options);
336 } 338 }
337 339
338 void FrameSelection::setSelection( 340 void FrameSelection::setSelection(
339 const VisibleSelectionInFlatTree& newSelection, 341 const VisibleSelectionInFlatTree& newSelection,
340 HandleVisibility handleVisibility, 342 HandleVisibility handleVisibility,
341 SetSelectionOptions options, 343 SetSelectionOptions options,
342 CursorAlignOnScroll align, 344 CursorAlignOnScroll align,
343 TextGranularity granularity) { 345 TextGranularity granularity) {
344 setSelection( 346 setSelectionAlgorithm<EditingInFlatTreeStrategy>(
345 SelectionInFlatTree::Builder(newSelection.asSelection()) 347 newSelection, handleVisibility, options, align, granularity);
346 .setIsHandleVisible(handleVisibility == HandleVisibility::Visible)
347 .build(),
348 options, align, granularity);
349 } 348 }
350 349
351 void FrameSelection::setSelection( 350 void FrameSelection::setSelection(
352 const VisibleSelectionInFlatTree& newSelection, 351 const VisibleSelectionInFlatTree& newSelection,
353 SetSelectionOptions options) { 352 SetSelectionOptions options) {
354 setSelection(newSelection.asSelection(), options); 353 setSelection(newSelection, HandleVisibility::NotVisible, options);
355 } 354 }
356 355
357 // TODO(yosin): We should move |computePositionForChildrenRemoval()| to 356 static bool removingNodeRemovesPosition(Node& node, const Position& position) {
358 // "SelectionEditor.cpp" since it used only in 357 if (!position.anchorNode())
359 // |SelectionEditor::nodeChildrenWillBeRemoved()|. 358 return false;
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
360 static Position computePositionForChildrenRemoval(const Position& position, 370 static Position computePositionForChildrenRemoval(const Position& position,
361 ContainerNode& container) { 371 ContainerNode& container) {
362 Node* node = position.computeContainerNode(); 372 Node* node = position.computeContainerNode();
363 if (container.containsIncludingHostElements(*node)) 373 if (container.containsIncludingHostElements(*node))
364 return Position::firstPositionInNode(&container); 374 return Position::firstPositionInNode(&container);
365 return position; 375 return position;
366 } 376 }
367 377
368 void FrameSelection::nodeChildrenWillBeRemoved(ContainerNode& container) { 378 void FrameSelection::nodeChildrenWillBeRemoved(ContainerNode& container) {
369 if (!container.inActiveDocument()) 379 if (isNone() || !container.inActiveDocument())
370 return; 380 return;
381 const Position& oldStart = selection().start();
382 const Position& newStart =
383 computePositionForChildrenRemoval(oldStart, container);
384 const Position& oldEnd = selection().end();
385 const Position& newEnd = computePositionForChildrenRemoval(oldEnd, container);
386 const Position& oldBase = selection().base();
387 const Position& newBase =
388 computePositionForChildrenRemoval(oldBase, container);
389 const Position& oldExtent = selection().extent();
390 const Position& newExtent =
391 computePositionForChildrenRemoval(oldExtent, container);
392 if (newStart == oldStart && newEnd == oldEnd && newBase == oldBase &&
393 newExtent == oldExtent)
394 return;
395 if (selection().isBaseFirst())
396 m_selectionEditor->setWithoutValidation(newStart, newEnd);
397 else
398 m_selectionEditor->setWithoutValidation(newEnd, newStart);
399 if (document().isRunningExecCommand())
400 return;
401 TypingCommand::closeTyping(m_frame);
402 }
403
404 void FrameSelection::nodeWillBeRemoved(Node& node) {
405 // 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
407 // needs no adjustment.
408 if (isNone() || !node.inActiveDocument())
409 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
371 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to 479 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
372 // |Editor| class. 480 // |Editor| class.
373 if (!document().isRunningExecCommand()) 481 if (!document().isRunningExecCommand())
374 TypingCommand::closeTyping(m_frame); 482 TypingCommand::closeTyping(m_frame);
375 } 483 }
376 484
377 // TODO(yosin): We should move |SelectionEditor::nodeChildrenWillBeRemoved()|
378 // to "SelectionEditor.cpp".
379 void SelectionEditor::nodeChildrenWillBeRemoved(ContainerNode& container) {
380 if (m_selection.isNone())
381 return;
382 const Position oldBase = m_selection.m_base;
383 const Position oldExtent = m_selection.m_extent;
384 const Position& newBase =
385 computePositionForChildrenRemoval(oldBase, container);
386 const Position& newExtent =
387 computePositionForChildrenRemoval(oldExtent, container);
388 if (newBase == oldBase && newExtent == oldExtent)
389 return;
390 m_selection = SelectionInDOMTree::Builder()
391 .setBaseAndExtent(newBase, newExtent)
392 .build();
393 markCacheDirty();
394 }
395
396 // TODO(yosin): We should move |computePositionForChildrenRemoval()| with
397 // |nodeWillBeRemoved()| to "SelectionEditor.cpp".
398 static Position computePositionForNodeRemoval(const Position& position,
399 Node& nodeToBeRemoved) {
400 Position result = position;
401 // TODO(yosin): We should rename |updatePositionForNodeRemoval()|
402 // to |computePositionForNodeRemoval()| to avoid using output parameter.
403 updatePositionForNodeRemoval(result, nodeToBeRemoved);
404 return result;
405 }
406
407 // TODO(yosin): We should move |nodeWillBeRemoved()| to
408 // "SelectionEditor.cpp".
409 void SelectionEditor::nodeWillBeRemoved(Node& nodeToBeRemoved) {
410 if (m_selection.isNone())
411 return;
412 const Position oldBase = m_selection.m_base;
413 const Position oldExtent = m_selection.m_extent;
414 const Position& newBase =
415 computePositionForNodeRemoval(oldBase, nodeToBeRemoved);
416 const Position& newExtent =
417 computePositionForNodeRemoval(oldExtent, nodeToBeRemoved);
418 if (newBase == oldBase && newExtent == oldExtent)
419 return;
420 m_selection = SelectionInDOMTree::Builder()
421 .setBaseAndExtent(newBase, newExtent)
422 .build();
423 markCacheDirty();
424 }
425
426 void FrameSelection::nodeWillBeRemoved(Node& node) {
427 // There can't be a selection inside a fragment, so if a fragment's node is
428 // being removed, the selection in the document that created the fragment
429 // needs no adjustment.
430 if (!node.inActiveDocument())
431 return;
432 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
433 // |Editor| class.
434 if (!document().isRunningExecCommand())
435 TypingCommand::closeTyping(m_frame);
436 }
437
438 // TODO(yosin): We should move |updatePositionAfterAdoptingTextReplacement()|
439 // to "SelectionEditor.cpp" since it used only in
440 // |SelectionEditor::didUpdateCharacterData()|.
441 static Position updatePositionAfterAdoptingTextReplacement( 485 static Position updatePositionAfterAdoptingTextReplacement(
442 const Position& position, 486 const Position& position,
443 CharacterData* node, 487 CharacterData* node,
444 unsigned offset, 488 unsigned offset,
445 unsigned oldLength, 489 unsigned oldLength,
446 unsigned newLength) { 490 unsigned newLength) {
447 if (position.anchorNode() != node) 491 if (!position.anchorNode() || position.anchorNode() != node ||
492 !position.isOffsetInAnchor())
448 return position; 493 return position;
449 494
450 if (position.isBeforeAnchor()) {
451 return updatePositionAfterAdoptingTextReplacement(
452 Position(node, 0), node, offset, oldLength, newLength);
453 }
454 if (position.isAfterAnchor()) {
455 return updatePositionAfterAdoptingTextReplacement(
456 Position(node, oldLength), node, offset, oldLength, newLength);
457 }
458
459 // See: 495 // See:
460 // http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range- Mutation 496 // http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range- Mutation
461 DCHECK_GE(position.offsetInContainerNode(), 0); 497 DCHECK_GE(position.offsetInContainerNode(), 0);
462 unsigned positionOffset = 498 unsigned positionOffset =
463 static_cast<unsigned>(position.offsetInContainerNode()); 499 static_cast<unsigned>(position.offsetInContainerNode());
464 // Replacing text can be viewed as a deletion followed by insertion. 500 // Replacing text can be viewed as a deletion followed by insertion.
465 if (positionOffset >= offset && positionOffset <= offset + oldLength) 501 if (positionOffset >= offset && positionOffset <= offset + oldLength)
466 positionOffset = offset; 502 positionOffset = offset;
467 503
468 // Adjust the offset if the position is after the end of the deleted contents 504 // Adjust the offset if the position is after the end of the deleted contents
469 // (positionOffset > offset + oldLength) to avoid having a stale offset. 505 // (positionOffset > offset + oldLength) to avoid having a stale offset.
470 if (positionOffset > offset + oldLength) 506 if (positionOffset > offset + oldLength)
471 positionOffset = positionOffset - oldLength + newLength; 507 positionOffset = positionOffset - oldLength + newLength;
472 508
473 // Due to case folding 509 // Due to case folding
474 // (http://unicode.org/Public/UCD/latest/ucd/CaseFolding.txt), LayoutText 510 // (http://unicode.org/Public/UCD/latest/ucd/CaseFolding.txt), LayoutText
475 // length may be different from Text length. A correct implementation would 511 // length may be different from Text length. A correct implementation would
476 // translate the LayoutText offset to a Text offset; this is just a safety 512 // translate the LayoutText offset to a Text offset; this is just a safety
477 // precaution to avoid offset values that run off the end of the Text. 513 // precaution to avoid offset values that run off the end of the Text.
478 if (positionOffset > node->length()) 514 if (positionOffset > node->length())
479 positionOffset = node->length(); 515 positionOffset = node->length();
480 516
481 return Position(node, positionOffset); 517 // CharacterNode in VisibleSelection must be Text node, because Comment
518 // and ProcessingInstruction node aren't visible.
519 return Position(toText(node), positionOffset);
482 } 520 }
483 521
484 // TODO(yosin): We should move |didUpdateCharacterData()| to 522 void FrameSelection::didUpdateCharacterData(CharacterData* node,
485 // "SelectionEditor.cpp". 523 unsigned offset,
486 void SelectionEditor::didUpdateCharacterData(CharacterData* node, 524 unsigned oldLength,
487 unsigned offset, 525 unsigned newLength) {
488 unsigned oldLength,
489 unsigned newLength) {
490 // The fragment check is a performance optimization. See 526 // The fragment check is a performance optimization. See
491 // http://trac.webkit.org/changeset/30062. 527 // http://trac.webkit.org/changeset/30062.
492 if (m_selection.isNone() || !node || !node->isConnected()) { 528 if (isNone() || !node || !node->isConnected())
493 didFinishDOMMutation();
494 return; 529 return;
495 } 530
496 const Position& newBase = updatePositionAfterAdoptingTextReplacement( 531 Position base = updatePositionAfterAdoptingTextReplacement(
497 m_selection.m_base, node, offset, oldLength, newLength); 532 selection().base(), node, offset, oldLength, newLength);
498 const Position& newExtent = updatePositionAfterAdoptingTextReplacement( 533 Position extent = updatePositionAfterAdoptingTextReplacement(
499 m_selection.m_extent, node, offset, oldLength, newLength); 534 selection().extent(), node, offset, oldLength, newLength);
500 didFinishTextChange(newBase, newExtent); 535 Position start = updatePositionAfterAdoptingTextReplacement(
536 selection().start(), node, offset, oldLength, newLength);
537 Position end = updatePositionAfterAdoptingTextReplacement(
538 selection().end(), node, offset, oldLength, newLength);
539 updateSelectionIfNeeded(base, extent, start, end);
501 } 540 }
502 541
503 // TODO(yosin): We should move |updatePostionAfterAdoptingTextNodesMerged()|
504 // to "SelectionEditor.cpp" since it used only in
505 // |SelectionEditor::didMergeTextNodes()|.
506 // TODO(yosin): We should introduce |Position(const Text&, int)| to avoid
507 // |const_cast<Text*>|.
508 static Position updatePostionAfterAdoptingTextNodesMerged( 542 static Position updatePostionAfterAdoptingTextNodesMerged(
509 const Position& position, 543 const Position& position,
510 const Text& mergedNode, 544 const Text& oldNode,
511 const NodeWithIndex& nodeToBeRemovedWithIndex, 545 unsigned offset) {
512 unsigned oldLength) { 546 if (!position.anchorNode() || !position.isOffsetInAnchor())
513 Node* const anchorNode = position.anchorNode(); 547 return position;
514 const Node& nodeToBeRemoved = nodeToBeRemovedWithIndex.node(); 548
515 switch (position.anchorType()) { 549 DCHECK_GE(position.offsetInContainerNode(), 0);
516 case PositionAnchorType::BeforeChildren: 550 unsigned positionOffset =
517 case PositionAnchorType::AfterChildren: 551 static_cast<unsigned>(position.offsetInContainerNode());
518 return position; 552
519 case PositionAnchorType::BeforeAnchor: 553 if (position.anchorNode() == &oldNode)
520 if (anchorNode == nodeToBeRemoved) 554 return Position(toText(oldNode.previousSibling()), positionOffset + offset);
521 return Position(const_cast<Text*>(&mergedNode), mergedNode.length()); 555
522 return position; 556 if (position.anchorNode() == oldNode.parentNode() && positionOffset == offset)
523 case PositionAnchorType::AfterAnchor: 557 return Position(toText(oldNode.previousSibling()), offset);
524 if (anchorNode == nodeToBeRemoved) 558
525 return Position(const_cast<Text*>(&mergedNode), mergedNode.length());
526 if (anchorNode == mergedNode)
527 return Position(const_cast<Text*>(&mergedNode), oldLength);
528 return position;
529 case PositionAnchorType::OffsetInAnchor: {
530 const int offset = position.offsetInContainerNode();
531 if (anchorNode == nodeToBeRemoved)
532 return Position(const_cast<Text*>(&mergedNode), oldLength + offset);
533 if (anchorNode == nodeToBeRemoved.parentNode() &&
534 offset == nodeToBeRemovedWithIndex.index()) {
535 return Position(const_cast<Text*>(&mergedNode), oldLength);
536 }
537 return position;
538 }
539 }
540 NOTREACHED() << position;
541 return position; 559 return position;
542 } 560 }
543 561
544 // TODO(yosin): We should move |SelectionEditor::didMergeTextNodes()| to 562 void FrameSelection::didMergeTextNodes(
545 // "SelectionEditor.cpp".
546 void SelectionEditor::didMergeTextNodes(
547 const Text& mergedNode, 563 const Text& mergedNode,
548 const NodeWithIndex& nodeToBeRemovedWithIndex, 564 const NodeWithIndex& nodeToBeRemovedWithIndex,
549 unsigned oldLength) { 565 unsigned offset) {
550 if (m_selection.isNone()) { 566 const Text& oldNode = toText(nodeToBeRemovedWithIndex.node());
551 didFinishDOMMutation(); 567 if (isNone() || !oldNode.isConnected())
552 return; 568 return;
553 } 569 Position base = updatePostionAfterAdoptingTextNodesMerged(selection().base(),
554 const Position& newBase = updatePostionAfterAdoptingTextNodesMerged( 570 oldNode, offset);
555 m_selection.m_base, mergedNode, nodeToBeRemovedWithIndex, oldLength); 571 Position extent = updatePostionAfterAdoptingTextNodesMerged(
556 const Position& newExtent = updatePostionAfterAdoptingTextNodesMerged( 572 selection().extent(), oldNode, offset);
557 m_selection.m_extent, mergedNode, nodeToBeRemovedWithIndex, oldLength); 573 Position start = updatePostionAfterAdoptingTextNodesMerged(
558 didFinishTextChange(newBase, newExtent); 574 selection().start(), oldNode, offset);
575 Position end = updatePostionAfterAdoptingTextNodesMerged(selection().end(),
576 oldNode, offset);
577 updateSelectionIfNeeded(base, extent, start, end);
559 } 578 }
560 579
561 // TODO(yosin): We should move |updatePostionAfterAdoptingTextNodeSplit()|
562 // to "SelectionEditor.cpp" since it used only in
563 // |SelectionEditor::didSplitTextNode()|.
564 static Position updatePostionAfterAdoptingTextNodeSplit( 580 static Position updatePostionAfterAdoptingTextNodeSplit(
565 const Position& position, 581 const Position& position,
566 const Text& oldNode) { 582 const Text& oldNode) {
567 if (!position.anchorNode() || position.anchorNode() != &oldNode || 583 if (!position.anchorNode() || position.anchorNode() != &oldNode ||
568 !position.isOffsetInAnchor()) 584 !position.isOffsetInAnchor())
569 return position; 585 return position;
570 // See: 586 // See:
571 // http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range- Mutation 587 // http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range- Mutation
572 DCHECK_GE(position.offsetInContainerNode(), 0); 588 DCHECK_GE(position.offsetInContainerNode(), 0);
573 unsigned positionOffset = 589 unsigned positionOffset =
574 static_cast<unsigned>(position.offsetInContainerNode()); 590 static_cast<unsigned>(position.offsetInContainerNode());
575 unsigned oldLength = oldNode.length(); 591 unsigned oldLength = oldNode.length();
576 if (positionOffset <= oldLength) 592 if (positionOffset <= oldLength)
577 return position; 593 return position;
578 return Position(toText(oldNode.nextSibling()), positionOffset - oldLength); 594 return Position(toText(oldNode.nextSibling()), positionOffset - oldLength);
579 } 595 }
580 596
581 // TODO(yosin): We should move |SelectionEditor::didSplitTextNode()| to 597 void FrameSelection::didSplitTextNode(const Text& oldNode) {
582 // "SelectionEditor.cpp". 598 if (isNone() || !oldNode.isConnected())
583 void SelectionEditor::didSplitTextNode(const Text& oldNode) {
584 if (m_selection.isNone() || !oldNode.isConnected()) {
585 didFinishDOMMutation();
586 return; 599 return;
587 } 600 Position base =
588 const Position& newBase = 601 updatePostionAfterAdoptingTextNodeSplit(selection().base(), oldNode);
589 updatePostionAfterAdoptingTextNodeSplit(m_selection.m_base, oldNode); 602 Position extent =
590 const Position& newExtent = 603 updatePostionAfterAdoptingTextNodeSplit(selection().extent(), oldNode);
591 updatePostionAfterAdoptingTextNodeSplit(m_selection.m_extent, oldNode); 604 Position start =
592 didFinishTextChange(newBase, newExtent); 605 updatePostionAfterAdoptingTextNodeSplit(selection().start(), oldNode);
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);
593 } 628 }
594 629
595 void FrameSelection::didChangeFocus() { 630 void FrameSelection::didChangeFocus() {
596 // Hits in 631 // Hits in
597 // virtual/gpu/compositedscrolling/scrollbars/scrollbar-miss-mousemove-disable d.html 632 // virtual/gpu/compositedscrolling/scrollbars/scrollbar-miss-mousemove-disable d.html
598 DisableCompositingQueryAsserts disabler; 633 DisableCompositingQueryAsserts disabler;
599 updateAppearance(); 634 updateAppearance();
600 } 635 }
601 636
602 static DispatchEventResult dispatchSelectStart( 637 static DispatchEventResult dispatchSelectStart(
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 } 724 }
690 725
691 void FrameSelection::contextDestroyed(Document* document) { 726 void FrameSelection::contextDestroyed(Document* document) {
692 m_granularity = CharacterGranularity; 727 m_granularity = CharacterGranularity;
693 728
694 LayoutViewItem view = m_frame->contentLayoutItem(); 729 LayoutViewItem view = m_frame->contentLayoutItem();
695 if (!view.isNull()) 730 if (!view.isNull())
696 view.clearSelection(); 731 view.clearSelection();
697 732
698 m_frame->editor().clearTypingStyle(); 733 m_frame->editor().clearTypingStyle();
734 m_selectionEditor->documentDetached(*document);
699 } 735 }
700 736
701 void FrameSelection::clearPreviousCaretVisualRect(const LayoutBlock& block) { 737 void FrameSelection::clearPreviousCaretVisualRect(const LayoutBlock& block) {
702 m_frameCaret->clearPreviousVisualRect(block); 738 m_frameCaret->clearPreviousVisualRect(block);
703 } 739 }
704 740
705 void FrameSelection::layoutBlockWillBeDestroyed(const LayoutBlock& block) { 741 void FrameSelection::layoutBlockWillBeDestroyed(const LayoutBlock& block) {
706 m_frameCaret->layoutBlockWillBeDestroyed(block); 742 m_frameCaret->layoutBlockWillBeDestroyed(block);
707 } 743 }
708 744
709 void FrameSelection::updateStyleAndLayoutIfNeeded() { 745 void FrameSelection::updateStyleAndLayoutIfNeeded() {
710 m_frameCaret->updateStyleAndLayoutIfNeeded(); 746 m_frameCaret->updateStyleAndLayoutIfNeeded();
711 } 747 }
712 748
713 void FrameSelection::invalidatePaintIfNeeded( 749 void FrameSelection::invalidatePaintIfNeeded(
714 const LayoutBlock& block, 750 const LayoutBlock& block,
715 const PaintInvalidatorContext& context, 751 const PaintInvalidatorContext& context,
716 PaintInvalidationReason reason) { 752 PaintInvalidationReason reason) {
717 m_frameCaret->invalidatePaintIfNeeded(block, context, reason); 753 m_frameCaret->invalidatePaintIfNeeded(block, context, reason);
718 } 754 }
719 755
720 bool FrameSelection::shouldPaintCaret(const LayoutBlock& block) const { 756 bool FrameSelection::shouldPaintCaret(const LayoutBlock& block) const {
721 DCHECK_GE(document().lifecycle().state(), DocumentLifecycle::LayoutClean); 757 DCHECK(selection().isValidFor(document()));
758
722 bool result = m_frameCaret->shouldPaintCaret(block); 759 bool result = m_frameCaret->shouldPaintCaret(block);
723 DCHECK(!result || (isCaret() && hasEditableStyle())); 760 DCHECK(!result || (isCaret() && hasEditableStyle()));
724 return result; 761 return result;
725 } 762 }
726 763
727 IntRect FrameSelection::absoluteCaretBounds() { 764 IntRect FrameSelection::absoluteCaretBounds() {
728 DCHECK(selection().isValidFor(*m_frame->document())); 765 DCHECK(selection().isValidFor(*m_frame->document()));
729 return m_frameCaret->absoluteCaretBounds(); 766 return m_frameCaret->absoluteCaretBounds();
730 } 767 }
731 768
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 1068
1032 void FrameSelection::commitAppearanceIfNeeded(LayoutView& layoutView) { 1069 void FrameSelection::commitAppearanceIfNeeded(LayoutView& layoutView) {
1033 return m_pendingSelection->commit(layoutView); 1070 return m_pendingSelection->commit(layoutView);
1034 } 1071 }
1035 1072
1036 void FrameSelection::didLayout() { 1073 void FrameSelection::didLayout() {
1037 updateAppearance(); 1074 updateAppearance();
1038 } 1075 }
1039 1076
1040 void FrameSelection::updateAppearance() { 1077 void FrameSelection::updateAppearance() {
1041 DCHECK(!m_frame->contentLayoutItem().isNull()); 1078 m_frameCaret->updateAppearance();
1042 m_frameCaret->scheduleVisualUpdateForPaintInvalidationIfNeeded(); 1079
1080 if (m_frame->contentLayoutItem().isNull())
1081 return;
1043 m_pendingSelection->setHasPendingSelection(); 1082 m_pendingSelection->setHasPendingSelection();
1044 } 1083 }
1045 1084
1046 void FrameSelection::notifyLayoutObjectOfSelectionChange( 1085 void FrameSelection::notifyLayoutObjectOfSelectionChange(
1047 EUserTriggered userTriggered) { 1086 EUserTriggered userTriggered) {
1048 if (TextControlElement* textControl = enclosingTextControl(start())) 1087 if (TextControlElement* textControl = enclosingTextControl(start()))
1049 textControl->selectionChanged(userTriggered == UserTriggered); 1088 textControl->selectionChanged(userTriggered == UserTriggered);
1050 } 1089 }
1051 1090
1052 // Helper function that tells whether a particular node is an element that has 1091 // 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
1235 1274
1236 Document* document = m_frame->document(); 1275 Document* document = m_frame->document();
1237 if (!isNone() || !(blink::hasEditableStyle(*document))) 1276 if (!isNone() || !(blink::hasEditableStyle(*document)))
1238 return; 1277 return;
1239 1278
1240 Element* documentElement = document->documentElement(); 1279 Element* documentElement = document->documentElement();
1241 if (!documentElement) 1280 if (!documentElement)
1242 return; 1281 return;
1243 if (HTMLBodyElement* body = 1282 if (HTMLBodyElement* body =
1244 Traversal<HTMLBodyElement>::firstChild(*documentElement)) { 1283 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
1245 setSelection(SelectionInDOMTree::Builder() 1288 setSelection(SelectionInDOMTree::Builder()
1246 .collapse(firstPositionInOrBeforeNode(body)) 1289 .collapse(firstPositionInOrBeforeNode(body))
1247 .build()); 1290 .build());
1248 } 1291 }
1249 } 1292 }
1250 1293
1251 // TODO(yoichio): We should have LocalFrame having FrameCaret, 1294 // TODO(yoichio): We should have LocalFrame having FrameCaret,
1252 // Editor and PendingSelection using FrameCaret directly 1295 // Editor and PendingSelection using FrameCaret directly
1253 // and get rid of this. 1296 // and get rid of this.
1254 bool FrameSelection::shouldShowBlockCursor() const { 1297 bool FrameSelection::shouldShowBlockCursor() const {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1345 FrameSelection::DoNotClearStrategy | UserTriggered, 1388 FrameSelection::DoNotClearStrategy | UserTriggered,
1346 CursorAlignOnScroll::IfNeeded, CharacterGranularity); 1389 CursorAlignOnScroll::IfNeeded, CharacterGranularity);
1347 } 1390 }
1348 1391
1349 // TODO(yosin): We should make |FrameSelection::moveRangeSelection()| to take 1392 // TODO(yosin): We should make |FrameSelection::moveRangeSelection()| to take
1350 // two |IntPoint| instead of two |VisiblePosition| like 1393 // two |IntPoint| instead of two |VisiblePosition| like
1351 // |moveRangeSelectionExtent()|. 1394 // |moveRangeSelectionExtent()|.
1352 void FrameSelection::moveRangeSelection(const VisiblePosition& basePosition, 1395 void FrameSelection::moveRangeSelection(const VisiblePosition& basePosition,
1353 const VisiblePosition& extentPosition, 1396 const VisiblePosition& extentPosition,
1354 TextGranularity granularity) { 1397 TextGranularity granularity) {
1355 SelectionInDOMTree newSelection = 1398 VisibleSelection newSelection = createVisibleSelection(
1356 SelectionInDOMTree::Builder() 1399 SelectionInDOMTree::Builder()
1357 .setBaseAndExtentDeprecated(basePosition.deepEquivalent(), 1400 .setBaseAndExtentDeprecated(basePosition.deepEquivalent(),
1358 extentPosition.deepEquivalent()) 1401 extentPosition.deepEquivalent())
1359 .setAffinity(basePosition.affinity()) 1402 .setAffinity(basePosition.affinity())
1360 .setGranularity(granularity) 1403 .setGranularity(granularity)
1361 .setIsHandleVisible(isHandleVisible()) 1404 .build());
1362 .build();
1363 1405
1364 if (newSelection.isNone()) 1406 if (newSelection.isNone())
1365 return; 1407 return;
1366 1408
1367 setSelection(newSelection, CloseTyping | ClearTypingStyle, 1409 setSelection(newSelection, m_handleVisibility, CloseTyping | ClearTypingStyle,
1368 CursorAlignOnScroll::IfNeeded, granularity); 1410 CursorAlignOnScroll::IfNeeded, granularity);
1369 } 1411 }
1370 1412
1371 void FrameSelection::updateIfNeeded() { 1413 void FrameSelection::updateIfNeeded() {
1372 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); 1414 DCHECK(!m_frame->document()->needsLayoutTreeUpdate());
1373 m_selectionEditor->updateIfNeeded(); 1415 m_selectionEditor->updateIfNeeded();
1374 } 1416 }
1375 1417
1376 void FrameSelection::setCaretVisible(bool caretIsVisible) { 1418 void FrameSelection::setCaretVisible(bool caretIsVisible) {
1377 m_frameCaret->setCaretVisibility(caretIsVisible ? CaretVisibility::Visible 1419 m_frameCaret->setCaretVisibility(caretIsVisible ? CaretVisibility::Visible
(...skipping 29 matching lines...) Expand all
1407 } 1449 }
1408 1450
1409 void showTree(const blink::FrameSelection* sel) { 1451 void showTree(const blink::FrameSelection* sel) {
1410 if (sel) 1452 if (sel)
1411 sel->showTreeForThis(); 1453 sel->showTreeForThis();
1412 else 1454 else
1413 LOG(INFO) << "Cannot showTree for <null> FrameSelection."; 1455 LOG(INFO) << "Cannot showTree for <null> FrameSelection.";
1414 } 1456 }
1415 1457
1416 #endif 1458 #endif
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/FrameSelection.h ('k') | third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698