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

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

Issue 1371003002: Utilize VisibleSelectionTemplate template class in SelectionController (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 2015-09-28T14:31:05 Created 5 years, 2 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) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed. 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed.
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies)
5 * Copyright (C) 2015 Google Inc. All rights reserved. 5 * Copyright (C) 2015 Google Inc. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 { 59 {
60 } 60 }
61 61
62 DEFINE_TRACE(SelectionController) 62 DEFINE_TRACE(SelectionController)
63 { 63 {
64 visitor->trace(m_frame); 64 visitor->trace(m_frame);
65 } 65 }
66 66
67 namespace { 67 namespace {
68 68
69 void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelection& new Selection) 69 template <typename Strategy>
70 void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelectionTempl ate<Strategy>& newSelection)
70 { 71 {
71 if (equalSelectionsInDOMTree(selection.selection(), newSelection)) 72 if (selection.visibleSelection<Strategy>() == newSelection)
72 return; 73 return;
73 selection.setSelection(newSelection); 74 selection.setSelection(newSelection);
74 } 75 }
75 76
76 bool dispatchSelectStart(Node* node) 77 bool dispatchSelectStart(Node* node)
77 { 78 {
78 if (!node || !node->layoutObject()) 79 if (!node || !node->layoutObject())
79 return true; 80 return true;
80 81
81 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel ectstart)); 82 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel ectstart));
82 } 83 }
83 84
84 template <typename Strategy> 85 template <typename Strategy>
85 VisibleSelectionTemplate<Strategy> expandSelectionToRespectUserSelectAll(Node* t argetNode, const VisibleSelectionTemplate<Strategy>& selection) 86 VisibleSelectionTemplate<Strategy> expandSelectionToRespectUserSelectAll(Node* t argetNode, const VisibleSelectionTemplate<Strategy>& selection)
86 { 87 {
87 Node* rootUserSelectAll = Strategy::rootUserSelectAllForNode(targetNode); 88 Node* rootUserSelectAll = Strategy::rootUserSelectAllForNode(targetNode);
88 if (!rootUserSelectAll) 89 if (!rootUserSelectAll)
89 return selection; 90 return selection;
90 91
91 VisibleSelectionTemplate<Strategy> newSelection(selection); 92 VisibleSelectionTemplate<Strategy> newSelection(selection);
92 newSelection.setBase(mostBackwardCaretPosition(PositionAlgorithm<Strategy>:: beforeNode(rootUserSelectAll), CanCrossEditingBoundary)); 93 newSelection.setBase(mostBackwardCaretPosition(PositionAlgorithm<Strategy>:: beforeNode(rootUserSelectAll), CanCrossEditingBoundary));
93 newSelection.setExtent(mostForwardCaretPosition(PositionAlgorithm<Strategy>: :afterNode(rootUserSelectAll), CanCrossEditingBoundary)); 94 newSelection.setExtent(mostForwardCaretPosition(PositionAlgorithm<Strategy>: :afterNode(rootUserSelectAll), CanCrossEditingBoundary));
94 95
95 return newSelection; 96 return newSelection;
96 } 97 }
97 98
98 // TODO(yosin) |expandSelectionToRespectUserSelectAll()| with |VisibleSelection|
99 // should be removed once we have full version of |VisibleSelectionTemplate|.
100 static VisibleSelectionTemplate<EditingStrategy> expandSelectionToRespectUserSel ectAll(Node* targetNode, const VisibleSelection& selection)
101 {
102 return expandSelectionToRespectUserSelectAll(targetNode, VisibleSelectionTem plate<EditingStrategy>(selection));
103 }
104
105 bool expandSelectionUsingGranularity(VisibleSelection& selection, TextGranularit y granularity)
106 {
107 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
108 return selection.expandUsingGranularityInComposedTree(granularity);
109 return selection.expandUsingGranularity(granularity);
110 }
111
112 template <typename Strategy> 99 template <typename Strategy>
113 static int textDistance(const PositionAlgorithm<Strategy>& start, const Position Algorithm<Strategy>& end) 100 static int textDistance(const PositionAlgorithm<Strategy>& start, const Position Algorithm<Strategy>& end)
114 { 101 {
115 return TextIteratorAlgorithm<Strategy>::rangeLength(start, end, true); 102 return TextIteratorAlgorithm<Strategy>::rangeLength(start, end, true);
116 } 103 }
117 104
118 bool canMouseDownStartSelect(Node* node) 105 bool canMouseDownStartSelect(Node* node)
119 { 106 {
120 if (!node || !node->layoutObject()) 107 if (!node || !node->layoutObject())
121 return true; 108 return true;
(...skipping 23 matching lines...) Expand all
145 // existing selection so we can allow for text dragging. 132 // existing selection so we can allow for text dragging.
146 if (FrameView* view = m_frame->view()) { 133 if (FrameView* view = m_frame->view()) {
147 LayoutPoint vPoint = view->rootFrameToContents(event.event().position()) ; 134 LayoutPoint vPoint = view->rootFrameToContents(event.event().position()) ;
148 if (!extendSelection && selection().contains(vPoint)) { 135 if (!extendSelection && selection().contains(vPoint)) {
149 m_mouseDownWasSingleClickInSelection = true; 136 m_mouseDownWasSingleClickInSelection = true;
150 return false; 137 return false;
151 } 138 }
152 } 139 }
153 140
154 const PositionWithAffinity eventPos = innerNode->layoutObject()->positionFor Point(event.localPoint()); 141 const PositionWithAffinity eventPos = innerNode->layoutObject()->positionFor Point(event.localPoint());
155 VisiblePositionTemplate<Strategy> visiblePos = createVisiblePosition(fromPos itionInDOMTree<Strategy>(eventPos.position()), eventPos.affinity()); 142 VisiblePositionTemplate<Strategy> visiblePos = createVisiblePosition(fromPos itionInDOMTree<Strategy>(eventPos));
156 if (visiblePos.isNull()) 143 if (visiblePos.isNull())
157 visiblePos = createVisiblePosition(PositionAlgorithm<Strategy>::firstPos itionInOrBeforeNode(innerNode)); 144 visiblePos = createVisiblePosition(PositionAlgorithm<Strategy>::firstPos itionInOrBeforeNode(innerNode));
158 PositionAlgorithm<Strategy> pos = visiblePos.deepEquivalent(); 145 PositionAlgorithm<Strategy> pos = visiblePos.deepEquivalent();
159 146
160 VisibleSelectionTemplate<Strategy> newSelection(selection().selection()); 147 VisibleSelectionTemplate<Strategy> newSelection = selection().visibleSelecti on<Strategy>();
161 TextGranularity granularity = CharacterGranularity; 148 TextGranularity granularity = CharacterGranularity;
162 149
163 if (extendSelection && newSelection.isCaretOrRange()) { 150 if (extendSelection && newSelection.isCaretOrRange()) {
164 const VisibleSelectionTemplate<Strategy> selectionInUserSelectAll(expand SelectionToRespectUserSelectAll(innerNode, VisibleSelectionTemplate<Strategy>(cr eateVisiblePosition(pos)))); 151 const VisibleSelectionTemplate<Strategy> selectionInUserSelectAll(expand SelectionToRespectUserSelectAll(innerNode, VisibleSelectionTemplate<Strategy>(cr eateVisiblePosition(pos))));
165 if (selectionInUserSelectAll.isRange()) { 152 if (selectionInUserSelectAll.isRange()) {
166 if (selectionInUserSelectAll.start().compareTo(newSelection.start()) < 0) 153 if (selectionInUserSelectAll.start().compareTo(newSelection.start()) < 0)
167 pos = selectionInUserSelectAll.start(); 154 pos = selectionInUserSelectAll.start();
168 else if (newSelection.end().compareTo(selectionInUserSelectAll.end() ) < 0) 155 else if (newSelection.end().compareTo(selectionInUserSelectAll.end() ) < 0)
169 pos = selectionInUserSelectAll.end(); 156 pos = selectionInUserSelectAll.end();
170 } 157 }
171 158
172 if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() ) { 159 if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() ) {
173 if (pos.isNotNull()) { 160 if (pos.isNotNull()) {
174 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click d eselects when selection 161 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click
175 // was created right-to-left 162 // deselects when selection was created right-to-left
176 const PositionAlgorithm<Strategy> start = newSelection.start(); 163 const PositionAlgorithm<Strategy> start = newSelection.start();
177 const PositionAlgorithm<Strategy> end = newSelection.end(); 164 const PositionAlgorithm<Strategy> end = newSelection.end();
178 int distanceToStart = textDistance(start, pos); 165 int distanceToStart = textDistance(start, pos);
179 int distanceToEnd = textDistance(pos, end); 166 int distanceToEnd = textDistance(pos, end);
180 if (distanceToStart <= distanceToEnd) 167 if (distanceToStart <= distanceToEnd)
181 newSelection = VisibleSelectionTemplate<Strategy>(end, pos); 168 newSelection = VisibleSelectionTemplate<Strategy>(end, pos);
182 else 169 else
183 newSelection = VisibleSelectionTemplate<Strategy>(start, pos ); 170 newSelection = VisibleSelectionTemplate<Strategy>(start, pos );
184 } 171 }
185 } else { 172 } else {
(...skipping 16 matching lines...) Expand all
202 template <typename Strategy> 189 template <typename Strategy>
203 void SelectionController::updateSelectionForMouseDragAlgorithm(const HitTestResu lt& hitTestResult, Node* mousePressNode, const LayoutPoint& dragStartPos, const IntPoint& lastKnownMousePosition) 190 void SelectionController::updateSelectionForMouseDragAlgorithm(const HitTestResu lt& hitTestResult, Node* mousePressNode, const LayoutPoint& dragStartPos, const IntPoint& lastKnownMousePosition)
204 { 191 {
205 if (!m_mouseDownMayStartSelect) 192 if (!m_mouseDownMayStartSelect)
206 return; 193 return;
207 194
208 Node* target = hitTestResult.innerNode(); 195 Node* target = hitTestResult.innerNode();
209 if (!target) 196 if (!target)
210 return; 197 return;
211 198
212 const PositionWithAffinity rawTargetPosition = selection().selection().posit ionRespectingEditingBoundary(hitTestResult.localPoint(), target); 199 PositionWithAffinity rawTargetPosition = selection().selection().positionRes pectingEditingBoundary(hitTestResult.localPoint(), target);
213 const VisiblePositionTemplate<Strategy> targetPosition = createVisiblePositi on(fromPositionInDOMTree<Strategy>(rawTargetPosition.position()), rawTargetPosit ion.affinity()); 200 VisiblePositionTemplate<Strategy> targetPosition = createVisiblePosition(fro mPositionInDOMTree<Strategy>(rawTargetPosition));
214 // Don't modify the selection if we're not on a node. 201 // Don't modify the selection if we're not on a node.
215 if (targetPosition.isNull()) 202 if (targetPosition.isNull())
216 return; 203 return;
217 204
218 // Restart the selection if this is the first mouse move. This work is usual ly 205 // Restart the selection if this is the first mouse move. This work is usual ly
219 // done in handleMousePressEvent, but not if the mouse press was on an exist ing selection. 206 // done in handleMousePressEvent, but not if the mouse press was on an exist ing selection.
220 VisibleSelectionTemplate<Strategy> newSelection(selection().selection()); 207 VisibleSelectionTemplate<Strategy> newSelection = selection().visibleSelecti on<Strategy>();
221 208
222 // Special case to limit selection to the containing block for SVG text. 209 // Special case to limit selection to the containing block for SVG text.
223 // FIXME: Isn't there a better non-SVG-specific way to do this? 210 // FIXME: Isn't there a better non-SVG-specific way to do this?
224 if (Node* selectionBaseNode = newSelection.base().anchorNode()) { 211 if (Node* selectionBaseNode = newSelection.base().anchorNode()) {
225 if (LayoutObject* selectionBaseLayoutObject = selectionBaseNode->layoutO bject()) { 212 if (LayoutObject* selectionBaseLayoutObject = selectionBaseNode->layoutO bject()) {
226 if (selectionBaseLayoutObject->isSVGText()) { 213 if (selectionBaseLayoutObject->isSVGText()) {
227 if (target->layoutObject()->containingBlock() != selectionBaseLa youtObject->containingBlock()) 214 if (target->layoutObject()->containingBlock() != selectionBaseLa youtObject->containingBlock())
228 return; 215 return;
229 } 216 }
230 } 217 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 } else { 281 } else {
295 granularity = CharacterGranularity; 282 granularity = CharacterGranularity;
296 m_selectionState = SelectionState::PlacedCaret; 283 m_selectionState = SelectionState::PlacedCaret;
297 } 284 }
298 285
299 this->selection().setNonDirectionalSelectionIfNeeded(selection, granularity) ; 286 this->selection().setNonDirectionalSelectionIfNeeded(selection, granularity) ;
300 287
301 return true; 288 return true;
302 } 289 }
303 290
291 template <typename Strategy>
304 void SelectionController::selectClosestWordFromHitTestResult(const HitTestResult & result, AppendTrailingWhitespace appendTrailingWhitespace) 292 void SelectionController::selectClosestWordFromHitTestResult(const HitTestResult & result, AppendTrailingWhitespace appendTrailingWhitespace)
305 { 293 {
306 Node* innerNode = result.innerNode(); 294 Node* innerNode = result.innerNode();
307 VisibleSelection newSelection; 295 VisibleSelectionTemplate<Strategy> newSelection;
308 296
309 if (!innerNode || !innerNode->layoutObject()) 297 if (!innerNode || !innerNode->layoutObject())
310 return; 298 return;
311 299
312 VisiblePosition pos = createVisiblePosition(innerNode->layoutObject()->posit ionForPoint(result.localPoint())); 300 const VisiblePositionTemplate<Strategy> pos = createVisiblePosition(fromPosi tionInDOMTree<Strategy>(innerNode->layoutObject()->positionForPoint(result.local Point())));
313 if (pos.isNotNull()) { 301 if (pos.isNotNull()) {
314 newSelection = VisibleSelection(pos); 302 newSelection = VisibleSelectionTemplate<Strategy>(pos);
315 expandSelectionUsingGranularity(newSelection, WordGranularity); 303 newSelection.expandUsingGranularity(WordGranularity);
316 } 304 }
317 305
318 #if OS(ANDROID) 306 #if OS(ANDROID)
319 // If node is not editable and doesn't have text except space, tab or 307 // If node is not editable and doesn't have text except space, tab or
320 // line break, do not select that 'empty' area. 308 // line break, do not select that 'empty' area.
321 if (!innerNode->hasEditableStyle()) { 309 if (!innerNode->hasEditableStyle()) {
322 const EphemeralRangeInComposedTree range = EphemeralRangeInComposedTree( newSelection.startInComposedTree(), newSelection.endInComposedTree()); 310 EphemeralRangeTemplate<Strategy> range = EphemeralRangeTemplate<Strategy >(newSelection.start(), newSelection.end());
323 String str = plainText(range, TextIteratorDefaultBehavior); 311 String str = plainText(range, TextIteratorDefaultBehavior);
324 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace()) 312 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace())
325 return; 313 return;
326 } 314 }
327 #endif 315 #endif
328 316
329 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend && ne wSelection.isRange()) 317 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend && ne wSelection.isRange())
330 newSelection.appendTrailingWhitespace(); 318 newSelection.appendTrailingWhitespace();
331 319
332 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); 320 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
333 } 321 }
334 322
323 template <typename Strategy>
335 void SelectionController::selectClosestMisspellingFromHitTestResult(const HitTes tResult& result, AppendTrailingWhitespace appendTrailingWhitespace) 324 void SelectionController::selectClosestMisspellingFromHitTestResult(const HitTes tResult& result, AppendTrailingWhitespace appendTrailingWhitespace)
336 { 325 {
337 Node* innerNode = result.innerNode(); 326 Node* innerNode = result.innerNode();
338 VisibleSelection newSelection; 327 VisibleSelectionTemplate<Strategy> newSelection;
339 328
340 if (!innerNode || !innerNode->layoutObject()) 329 if (!innerNode || !innerNode->layoutObject())
341 return; 330 return;
342 331
343 VisiblePosition pos = createVisiblePosition(innerNode->layoutObject()->posit ionForPoint(result.localPoint())); 332 VisiblePositionTemplate<Strategy> pos = createVisiblePosition(fromPositionIn DOMTree<Strategy>(innerNode->layoutObject()->positionForPoint(result.localPoint( ))));
344 if (pos.isNotNull()) { 333 if (pos.isNotNull()) {
345 const Position markerPosition = pos.deepEquivalent().parentAnchoredEquiv alent(); 334 const PositionAlgorithm<Strategy> markerPosition = pos.deepEquivalent(). parentAnchoredEquivalent();
346 DocumentMarkerVector markers = innerNode->document().markers().markersIn Range(EphemeralRange(markerPosition), DocumentMarker::MisspellingMarkers()); 335 DocumentMarkerVector markers = innerNode->document().markers().markersIn Range(EphemeralRange(toPositionInDOMTree(markerPosition)), DocumentMarker::Missp ellingMarkers());
347 if (markers.size() == 1) { 336 if (markers.size() == 1) {
348 Node* containerNode = markerPosition.computeContainerNode(); 337 Node* containerNode = markerPosition.computeContainerNode();
349 const Position start(containerNode, markers[0]->startOffset()); 338 const PositionAlgorithm<Strategy> start(containerNode, markers[0]->s tartOffset());
350 const Position end(containerNode, markers[0]->endOffset()); 339 const PositionAlgorithm<Strategy> end(containerNode, markers[0]->end Offset());
351 newSelection = VisibleSelection(start, end); 340 newSelection = VisibleSelectionTemplate<Strategy>(start, end);
352 } 341 }
353 } 342 }
354 343
355 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend && ne wSelection.isRange()) 344 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend && ne wSelection.isRange())
356 newSelection.appendTrailingWhitespace(); 345 newSelection.appendTrailingWhitespace();
357 346
358 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); 347 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
359 } 348 }
360 349
361 void SelectionController::selectClosestWordFromMouseEvent(const MouseEventWithHi tTestResults& result) 350 void SelectionController::selectClosestWordFromMouseEvent(const MouseEventWithHi tTestResults& result)
362 { 351 {
363 if (!m_mouseDownMayStartSelect) 352 if (!m_mouseDownMayStartSelect)
364 return; 353 return;
365 354
366 selectClosestWordFromHitTestResult(result.hitTestResult(), 355 AppendTrailingWhitespace appendTrailingWhitespace = (result.event().clickCou nt() == 2 && m_frame->editor().isSelectTrailingWhitespaceEnabled()) ? AppendTrai lingWhitespace::ShouldAppend : AppendTrailingWhitespace::DontAppend;
367 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingW hitespaceEnabled()) ? AppendTrailingWhitespace::ShouldAppend : AppendTrailingWhi tespace::DontAppend); 356
357 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
358 return selectClosestWordFromHitTestResult<EditingInComposedTreeStrategy> (result.hitTestResult(), appendTrailingWhitespace);
359 selectClosestWordFromHitTestResult<EditingStrategy>(result.hitTestResult(), appendTrailingWhitespace);
368 } 360 }
369 361
362 template <typename Strategy>
370 void SelectionController::selectClosestMisspellingFromMouseEvent(const MouseEven tWithHitTestResults& result) 363 void SelectionController::selectClosestMisspellingFromMouseEvent(const MouseEven tWithHitTestResults& result)
371 { 364 {
372 if (!m_mouseDownMayStartSelect) 365 if (!m_mouseDownMayStartSelect)
373 return; 366 return;
374 367
375 selectClosestMisspellingFromHitTestResult(result.hitTestResult(), 368 selectClosestMisspellingFromHitTestResult<Strategy>(result.hitTestResult(),
376 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingW hitespaceEnabled()) ? AppendTrailingWhitespace::ShouldAppend : AppendTrailingWhi tespace::DontAppend); 369 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingW hitespaceEnabled()) ? AppendTrailingWhitespace::ShouldAppend : AppendTrailingWhi tespace::DontAppend);
377 370
378 } 371 }
379 372
373 template <typename Strategy>
380 void SelectionController::selectClosestWordOrLinkFromMouseEvent(const MouseEvent WithHitTestResults& result) 374 void SelectionController::selectClosestWordOrLinkFromMouseEvent(const MouseEvent WithHitTestResults& result)
381 { 375 {
382 if (!result.hitTestResult().isLiveLink()) 376 if (!result.hitTestResult().isLiveLink())
383 return selectClosestWordFromMouseEvent(result); 377 return selectClosestWordFromMouseEvent(result);
384 378
385 Node* innerNode = result.innerNode(); 379 Node* innerNode = result.innerNode();
386 380
387 if (!innerNode || !innerNode->layoutObject() || !m_mouseDownMayStartSelect) 381 if (!innerNode || !innerNode->layoutObject() || !m_mouseDownMayStartSelect)
388 return; 382 return;
389 383
390 VisibleSelection newSelection; 384 VisibleSelectionTemplate<Strategy> newSelection;
391 Element* URLElement = result.hitTestResult().URLElement(); 385 Element* URLElement = result.hitTestResult().URLElement();
392 VisiblePosition pos = createVisiblePosition(innerNode->layoutObject()->posit ionForPoint(result.localPoint())); 386 const VisiblePositionTemplate<Strategy> pos = createVisiblePosition(fromPosi tionInDOMTree<Strategy>(innerNode->layoutObject()->positionForPoint(result.local Point())));
393 if (pos.isNotNull() && pos.deepEquivalent().anchorNode()->isDescendantOf(URL Element)) 387 if (pos.isNotNull() && pos.deepEquivalent().anchorNode()->isDescendantOf(URL Element))
394 newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement) ; 388 newSelection = VisibleSelectionTemplate<Strategy>::selectionFromContents OfNode(URLElement);
395 389
396 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); 390 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
397 } 391 }
398 392
399 bool SelectionController::handleMousePressEventDoubleClick(const MouseEventWithH itTestResults& event) 393 bool SelectionController::handleMousePressEventDoubleClick(const MouseEventWithH itTestResults& event)
400 { 394 {
401 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventDoubleClick "); 395 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventDoubleClick ");
402 396
403 if (event.event().button() != LeftButton) 397 if (event.event().button() != LeftButton)
404 return false; 398 return false;
405 399
406 if (selection().isRange()) { 400 if (selection().isRange()) {
407 // A double-click when range is already selected 401 // A double-click when range is already selected
408 // should not change the selection. So, do not call 402 // should not change the selection. So, do not call
409 // selectClosestWordFromMouseEvent, but do set 403 // selectClosestWordFromMouseEvent, but do set
410 // m_beganSelectingText to prevent handleMouseReleaseEvent 404 // m_beganSelectingText to prevent handleMouseReleaseEvent
411 // from setting caret selection. 405 // from setting caret selection.
412 m_selectionState = SelectionState::ExtendedSelection; 406 m_selectionState = SelectionState::ExtendedSelection;
413 } else { 407 } else {
414 selectClosestWordFromMouseEvent(event); 408 selectClosestWordFromMouseEvent(event);
415 } 409 }
416 return true; 410 return true;
417 } 411 }
418 412
419 bool SelectionController::handleMousePressEventTripleClick(const MouseEventWithH itTestResults& event) 413 template <typename Strategy>
414 bool SelectionController::handleMousePressEventTripleClickAlgorithm(const MouseE ventWithHitTestResults& event)
420 { 415 {
421 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventTripleClick "); 416 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventTripleClick ");
422 417
423 if (event.event().button() != LeftButton) 418 if (event.event().button() != LeftButton)
424 return false; 419 return false;
425 420
426 Node* innerNode = event.innerNode(); 421 Node* innerNode = event.innerNode();
427 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) 422 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect))
428 return false; 423 return false;
429 424
430 VisibleSelection newSelection; 425 VisibleSelectionTemplate<Strategy> newSelection;
431 VisiblePosition pos = createVisiblePosition(innerNode->layoutObject()->posit ionForPoint(event.localPoint())); 426 const VisiblePositionTemplate<Strategy> pos = createVisiblePosition(fromPosi tionInDOMTree<Strategy>(innerNode->layoutObject()->positionForPoint(event.localP oint())));
432 if (pos.isNotNull()) { 427 if (pos.isNotNull()) {
433 newSelection = VisibleSelection(pos); 428 newSelection = VisibleSelectionTemplate<Strategy>(pos);
434 expandSelectionUsingGranularity(newSelection, ParagraphGranularity); 429 newSelection.expandUsingGranularity(ParagraphGranularity);
435 } 430 }
436 431
437 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSe lectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity); 432 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSe lectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity);
438 } 433 }
439 434
435 bool SelectionController::handleMousePressEventTripleClick(const MouseEventWithH itTestResults& event)
436 {
437 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
438 return handleMousePressEventTripleClickAlgorithm<EditingInComposedTreeSt rategy>(event);
439 return handleMousePressEventTripleClickAlgorithm<EditingStrategy>(event);
440 }
441
440 bool SelectionController::handleMousePressEventSingleClick(const MouseEventWithH itTestResults& event) 442 bool SelectionController::handleMousePressEventSingleClick(const MouseEventWithH itTestResults& event)
441 { 443 {
442 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) 444 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
443 return handleMousePressEventSingleClickAlgorithm<EditingInComposedTreeSt rategy>(event); 445 return handleMousePressEventSingleClickAlgorithm<EditingInComposedTreeSt rategy>(event);
444 return handleMousePressEventSingleClickAlgorithm<EditingStrategy>(event); 446 return handleMousePressEventSingleClickAlgorithm<EditingStrategy>(event);
445 } 447 }
446 448
447 void SelectionController::handleMousePressEvent(const MouseEventWithHitTestResul ts& event) 449 void SelectionController::handleMousePressEvent(const MouseEventWithHitTestResul ts& event)
448 { 450 {
449 // If we got the event back, that must mean it wasn't prevented, 451 // If we got the event back, that must mean it wasn't prevented,
(...skipping 29 matching lines...) Expand all
479 updateSelectionForMouseDrag(result, mousePressNode, dragStartPos, lastKnownM ousePosition); 481 updateSelectionForMouseDrag(result, mousePressNode, dragStartPos, lastKnownM ousePosition);
480 } 482 }
481 483
482 void SelectionController::updateSelectionForMouseDrag(const HitTestResult& hitTe stResult, Node* mousePressNode, const LayoutPoint& dragStartPos, const IntPoint& lastKnownMousePosition) 484 void SelectionController::updateSelectionForMouseDrag(const HitTestResult& hitTe stResult, Node* mousePressNode, const LayoutPoint& dragStartPos, const IntPoint& lastKnownMousePosition)
483 { 485 {
484 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) 486 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
485 return updateSelectionForMouseDragAlgorithm<EditingInComposedTreeStrateg y>(hitTestResult, mousePressNode, dragStartPos, lastKnownMousePosition); 487 return updateSelectionForMouseDragAlgorithm<EditingInComposedTreeStrateg y>(hitTestResult, mousePressNode, dragStartPos, lastKnownMousePosition);
486 updateSelectionForMouseDragAlgorithm<EditingStrategy>(hitTestResult, mousePr essNode, dragStartPos, lastKnownMousePosition); 488 updateSelectionForMouseDragAlgorithm<EditingStrategy>(hitTestResult, mousePr essNode, dragStartPos, lastKnownMousePosition);
487 } 489 }
488 490
489 bool SelectionController::handleMouseReleaseEvent(const MouseEventWithHitTestRes ults& event, const LayoutPoint& dragStartPos) 491 template <typename Strategy>
492 bool SelectionController::handleMouseReleaseEventAlgorithm(const MouseEventWithH itTestResults& event, const LayoutPoint& dragStartPos)
490 { 493 {
491 bool handled = false; 494 bool handled = false;
492 m_mouseDownMayStartSelect = false; 495 m_mouseDownMayStartSelect = false;
493 // Clear the selection if the mouse didn't move after the last mouse 496 // Clear the selection if the mouse didn't move after the last mouse
494 // press and it's not a context menu click. We do this so when clicking 497 // press and it's not a context menu click. We do this so when clicking
495 // on the selection, the selection goes away. However, if we are 498 // on the selection, the selection goes away. However, if we are
496 // editing, place the caret. 499 // editing, place the caret.
497 if (m_mouseDownWasSingleClickInSelection && m_selectionState != SelectionSta te::ExtendedSelection 500 if (m_mouseDownWasSingleClickInSelection && m_selectionState != SelectionSta te::ExtendedSelection
498 && dragStartPos == event.event().position() 501 && dragStartPos == event.event().position()
499 && selection().isRange() 502 && selection().isRange()
500 && event.event().button() != RightButton) { 503 && event.event().button() != RightButton) {
501 VisibleSelection newSelection; 504 VisibleSelectionTemplate<Strategy> newSelection;
502 Node* node = event.innerNode(); 505 Node* node = event.innerNode();
503 bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBr owsingEnabled(); 506 bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBr owsingEnabled();
504 if (node && node->layoutObject() && (caretBrowsing || node->hasEditableS tyle())) { 507 if (node && node->layoutObject() && (caretBrowsing || node->hasEditableS tyle())) {
505 VisiblePosition pos = createVisiblePosition(node->layoutObject()->po sitionForPoint(event.localPoint())); 508 const VisiblePositionTemplate<Strategy> pos = createVisiblePosition( fromPositionInDOMTree<Strategy>(node->layoutObject()->positionForPoint(event.loc alPoint())));
506 newSelection = VisibleSelection(pos); 509 newSelection = VisibleSelectionTemplate<Strategy>(pos);
507 } 510 }
508 511
509 setSelectionIfNeeded(selection(), newSelection); 512 setSelectionIfNeeded(selection(), newSelection);
510 513
511 handled = true; 514 handled = true;
512 } 515 }
513 516
514 selection().notifyLayoutObjectOfSelectionChange(UserTriggered); 517 selection().notifyLayoutObjectOfSelectionChange(UserTriggered);
515 518
516 selection().selectFrameElementInParentIfFullySelected(); 519 selection().selectFrameElementInParentIfFullySelected();
517 520
518 if (event.event().button() == MiddleButton && !event.isOverLink()) { 521 if (event.event().button() == MiddleButton && !event.isOverLink()) {
519 // Ignore handled, since we want to paste to where the caret was placed anyway. 522 // Ignore handled, since we want to paste to where the caret was placed anyway.
520 handled = handlePasteGlobalSelection(event.event()) || handled; 523 handled = handlePasteGlobalSelection(event.event()) || handled;
521 } 524 }
522 525
523 return handled; 526 return handled;
524 } 527 }
525 528
529 bool SelectionController::handleMouseReleaseEvent(const MouseEventWithHitTestRes ults& event, const LayoutPoint& dragStartPos)
530 {
531 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
532 return handleMouseReleaseEventAlgorithm<EditingInComposedTreeStrategy>(e vent, dragStartPos);
533 return handleMouseReleaseEventAlgorithm<EditingStrategy>(event, dragStartPos );
534 }
526 535
527 bool SelectionController::handlePasteGlobalSelection(const PlatformMouseEvent& m ouseEvent) 536 bool SelectionController::handlePasteGlobalSelection(const PlatformMouseEvent& m ouseEvent)
528 { 537 {
529 // If the event was a middle click, attempt to copy global selection in afte r 538 // If the event was a middle click, attempt to copy global selection in afte r
530 // the newly set caret position. 539 // the newly set caret position.
531 // 540 //
532 // This code is called from either the mouse up or mouse down handling. Ther e 541 // This code is called from either the mouse up or mouse down handling. Ther e
533 // is some debate about when the global selection is pasted: 542 // is some debate about when the global selection is pasted:
534 // xterm: pastes on up. 543 // xterm: pastes on up.
535 // GTK: pastes on down. 544 // GTK: pastes on down.
(...skipping 12 matching lines...) Expand all
548 if (!m_frame->page()) 557 if (!m_frame->page())
549 return false; 558 return false;
550 Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame(); 559 Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame();
551 // Do not paste here if the focus was moved somewhere else. 560 // Do not paste here if the focus was moved somewhere else.
552 if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSele ction()) 561 if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSele ction())
553 return m_frame->editor().command("PasteGlobalSelection").execute(); 562 return m_frame->editor().command("PasteGlobalSelection").execute();
554 563
555 return false; 564 return false;
556 } 565 }
557 566
558 bool SelectionController::handleGestureLongPress(const PlatformGestureEvent& ges tureEvent, const HitTestResult& hitTestResult) 567 template <typename Strategy>
568 bool SelectionController::handleGestureLongPressAlgorithm(const PlatformGestureE vent& gestureEvent, const HitTestResult& hitTestResult)
559 { 569 {
560 if (hitTestResult.isLiveLink()) 570 if (hitTestResult.isLiveLink())
561 return false; 571 return false;
562 572
563 #if OS(ANDROID) 573 #if OS(ANDROID)
564 bool shouldLongPressSelectWord = true; 574 bool shouldLongPressSelectWord = true;
565 #else 575 #else
566 bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()- >touchEditingEnabled(); 576 bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()- >touchEditingEnabled();
567 #endif 577 #endif
568 if (!shouldLongPressSelectWord) 578 if (!shouldLongPressSelectWord)
569 return false; 579 return false;
570 580
571 Node* innerNode = hitTestResult.innerNode(); 581 Node* innerNode = hitTestResult.innerNode();
572 #if OS(ANDROID) 582 #if OS(ANDROID)
573 bool innerNodeIsSelectable = innerNode && (innerNode->isContentEditable() || innerNode->isTextNode() || innerNode->canStartSelection()); 583 bool innerNodeIsSelectable = innerNode && (innerNode->isContentEditable() || innerNode->isTextNode() || innerNode->canStartSelection());
574 #else 584 #else
575 bool innerNodeIsSelectable = innerNode && (innerNode->isContentEditable() || innerNode->isTextNode()); 585 bool innerNodeIsSelectable = innerNode && (innerNode->isContentEditable() || innerNode->isTextNode());
576 #endif 586 #endif
577 if (!innerNodeIsSelectable) 587 if (!innerNodeIsSelectable)
578 return false; 588 return false;
579 589
580 selectClosestWordFromHitTestResult(hitTestResult, AppendTrailingWhitespace:: DontAppend); 590 selectClosestWordFromHitTestResult<Strategy>(hitTestResult, AppendTrailingWh itespace::DontAppend);
581 if (!selection().isRange()) 591 return selection().isRange();
582 return false; 592 }
583 return true; 593
594 bool SelectionController::handleGestureLongPress(const PlatformGestureEvent& ges tureEvent, const HitTestResult& hitTestResult)
595 {
596 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
597 return handleGestureLongPressAlgorithm<EditingInComposedTreeStrategy>(ge stureEvent, hitTestResult);
598 return handleGestureLongPressAlgorithm<EditingStrategy>(gestureEvent, hitTes tResult);
584 } 599 }
585 600
586 void SelectionController::sendContextMenuEvent(const MouseEventWithHitTestResult s& mev, const LayoutPoint& position) 601 void SelectionController::sendContextMenuEvent(const MouseEventWithHitTestResult s& mev, const LayoutPoint& position)
587 { 602 {
588 if (selection().contains(position) 603 if (selection().contains(position)
589 || mev.scrollbar() 604 || mev.scrollbar()
590 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse. 605 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
591 // If the selection is non-editable, we do word selection to make it eas ier to use the contextual menu items 606 // If the selection is non-editable, we do word selection to make it eas ier to use the contextual menu items
592 // available for text selections. But only if we're above text. 607 // available for text selections. But only if we're above text.
593 || !(selection().isContentEditable() || (mev.innerNode() && mev.innerNod e()->isTextNode()))) 608 || !(selection().isContentEditable() || (mev.innerNode() && mev.innerNod e()->isTextNode())))
594 return; 609 return;
595 610
596 m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection 611 m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
597 612
598 if (mev.hitTestResult().isMisspelled()) 613 if (mev.hitTestResult().isMisspelled()) {
599 selectClosestMisspellingFromMouseEvent(mev); 614 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
600 else if (m_frame->editor().behavior().shouldSelectOnContextualMenuClick()) 615 return selectClosestMisspellingFromMouseEvent<EditingInComposedTreeS trategy>(mev);
601 selectClosestWordOrLinkFromMouseEvent(mev); 616 return selectClosestMisspellingFromMouseEvent<EditingStrategy>(mev);
617 }
618
619 if (!m_frame->editor().behavior().shouldSelectOnContextualMenuClick())
620 return;
621
622 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
623 return selectClosestWordOrLinkFromMouseEvent<EditingInComposedTreeStrate gy>(mev);
624 selectClosestWordOrLinkFromMouseEvent<EditingStrategy>(mev);
602 } 625 }
603 626
604 void SelectionController::passMousePressEventToSubframe(const MouseEventWithHitT estResults& mev) 627 template <typename Strategy>
628 void SelectionController::passMousePressEventToSubframeAlgorithm(const MouseEven tWithHitTestResults& mev)
605 { 629 {
606 // If we're clicking into a frame that is selected, the frame will appear 630 // If we're clicking into a frame that is selected, the frame will appear
607 // greyed out even though we're clicking on the selection. This looks 631 // greyed out even though we're clicking on the selection. This looks
608 // really strange (having the whole frame be greyed out), so we deselect the 632 // really strange (having the whole frame be greyed out), so we deselect the
609 // selection. 633 // selection.
610 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); 634 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position());
611 if (!selection().contains(p)) 635 if (!selection().contains(p))
612 return; 636 return;
613 637
614 VisiblePosition visiblePos = createVisiblePosition( 638 const VisiblePositionTemplate<Strategy> visiblePos = createVisiblePosition(
615 mev.innerNode()->layoutObject()->positionForPoint(mev.localPoint())); 639 fromPositionInDOMTree<Strategy>(mev.innerNode()->layoutObject()->positio nForPoint(mev.localPoint())));
616 VisibleSelection newSelection(visiblePos); 640 VisibleSelectionTemplate<Strategy> newSelection(visiblePos);
617 selection().setSelection(newSelection); 641 selection().setSelection(newSelection);
618 } 642 }
619 643
644 void SelectionController::passMousePressEventToSubframe(const MouseEventWithHitT estResults& mev)
645 {
646 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
647 return passMousePressEventToSubframeAlgorithm<EditingInComposedTreeStrat egy>(mev);
648 passMousePressEventToSubframeAlgorithm<EditingStrategy>(mev);
649 }
650
620 void SelectionController::initializeSelectionState() 651 void SelectionController::initializeSelectionState()
621 { 652 {
622 m_selectionState = SelectionState::HaveNotStartedSelection; 653 m_selectionState = SelectionState::HaveNotStartedSelection;
623 } 654 }
624 655
625 void SelectionController::setMouseDownMayStartSelect(bool mayStartSelect) 656 void SelectionController::setMouseDownMayStartSelect(bool mayStartSelect)
626 { 657 {
627 m_mouseDownMayStartSelect = mayStartSelect; 658 m_mouseDownMayStartSelect = mayStartSelect;
628 } 659 }
629 660
(...skipping 16 matching lines...) Expand all
646 else 677 else
647 m_selectionState = SelectionState::HaveNotStartedSelection; 678 m_selectionState = SelectionState::HaveNotStartedSelection;
648 } 679 }
649 680
650 FrameSelection& SelectionController::selection() const 681 FrameSelection& SelectionController::selection() const
651 { 682 {
652 return m_frame->selection(); 683 return m_frame->selection();
653 } 684 }
654 685
655 } // namespace blink 686 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698