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

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

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