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

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

Issue 1219553003: Clean up SelectionController with namespace instead of static (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 6 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 , m_mouseDownWasSingleClickInSelection(false) 57 , m_mouseDownWasSingleClickInSelection(false)
58 , m_selectionState(SelectionState::HaveNotStartedSelection) 58 , m_selectionState(SelectionState::HaveNotStartedSelection)
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 static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelecti on& newSelection) 67 namespace {
68
69 void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelection& new Selection)
68 { 70 {
69 if (VisibleSelection::InDOMTree::equalSelections(selection.selection(), newS election)) 71 if (VisibleSelection::InDOMTree::equalSelections(selection.selection(), newS election))
70 return; 72 return;
71 selection.setSelection(newSelection); 73 selection.setSelection(newSelection);
72 } 74 }
73 75
74 static inline bool dispatchSelectStart(Node* node) 76 bool dispatchSelectStart(Node* node)
75 { 77 {
76 if (!node || !node->layoutObject()) 78 if (!node || !node->layoutObject())
77 return true; 79 return true;
78 80
79 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel ectstart)); 81 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel ectstart));
80 } 82 }
81 83
82 template <typename Strategy> 84 template <typename Strategy>
83 VisibleSelection expandSelectionToRespectUserSelectAllAlgorithm(Node* targetNode , const VisibleSelection& selection) 85 VisibleSelection expandSelectionToRespectUserSelectAllAlgorithm(Node* targetNode , const VisibleSelection& selection)
84 { 86 {
85 using PositionType = typename Strategy::PositionType; 87 using PositionType = typename Strategy::PositionType;
86 88
87 Node* rootUserSelectAll = PositionType::rootUserSelectAllForNode(targetNode) ; 89 Node* rootUserSelectAll = PositionType::rootUserSelectAllForNode(targetNode) ;
88 if (!rootUserSelectAll) 90 if (!rootUserSelectAll)
89 return selection; 91 return selection;
90 92
91 VisibleSelection newSelection(selection); 93 VisibleSelection newSelection(selection);
92 newSelection.setBase(PositionType::beforeNode(rootUserSelectAll).upstream(Ca nCrossEditingBoundary)); 94 newSelection.setBase(PositionType::beforeNode(rootUserSelectAll).upstream(Ca nCrossEditingBoundary));
93 newSelection.setExtent(PositionType::afterNode(rootUserSelectAll).downstream (CanCrossEditingBoundary)); 95 newSelection.setExtent(PositionType::afterNode(rootUserSelectAll).downstream (CanCrossEditingBoundary));
94 96
95 return newSelection; 97 return newSelection;
96 } 98 }
97 99
98 static VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode, const VisibleSelection& selection) 100 VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode, const V isibleSelection& selection)
99 { 101 {
100 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) 102 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
101 return expandSelectionToRespectUserSelectAllAlgorithm<VisibleSelection:: InComposedTree>(targetNode, selection); 103 return expandSelectionToRespectUserSelectAllAlgorithm<VisibleSelection:: InComposedTree>(targetNode, selection);
102 return expandSelectionToRespectUserSelectAllAlgorithm<VisibleSelection::InDO MTree>(targetNode, selection); 104 return expandSelectionToRespectUserSelectAllAlgorithm<VisibleSelection::InDO MTree>(targetNode, selection);
103 } 105 }
104 106
105 static bool expandSelectionUsingGranularity(VisibleSelection& selection, TextGra nularity granularity) 107 bool expandSelectionUsingGranularity(VisibleSelection& selection, TextGranularit y granularity)
106 { 108 {
107 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) 109 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
108 return selection.expandUsingGranularityInComposedTree(granularity); 110 return selection.expandUsingGranularityInComposedTree(granularity);
109 return selection.expandUsingGranularity(granularity); 111 return selection.expandUsingGranularity(granularity);
110 } 112 }
111 113
114 template <typename PositionType>
115 int textDistance(const PositionType& start, const PositionType& end)
116 {
117 return TextIteratorAlgorithm<typename PositionType::StrategyType>::rangeLeng th(start, end, true);
118 }
119
120 bool canMouseDownStartSelect(Node* node)
121 {
122 if (!node || !node->layoutObject())
123 return true;
124
125 if (!node->canStartSelection())
126 return false;
127
128 return true;
129 }
130
131 } // namespace
132
133 template <typename Strategy>
134 bool SelectionController::handleMousePressEventSingleClickAlgorithm(const MouseE ventWithHitTestResults& event)
135 {
136 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventSingleClick ");
137 using PositionType = typename Strategy::PositionType;
138
139 m_frame->document()->updateLayoutIgnorePendingStylesheets();
140 Node* innerNode = event.innerNode();
141 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect))
142 return false;
143
144 // Extend the selection if the Shift key is down, unless the click is in a l ink.
145 bool extendSelection = event.event().shiftKey() && !event.isOverLink();
146
147 // Don't restart the selection when the mouse is pressed on an
148 // existing selection so we can allow for text dragging.
149 if (FrameView* view = m_frame->view()) {
150 LayoutPoint vPoint = view->rootFrameToContents(event.event().position()) ;
151 if (!extendSelection && selection().contains(vPoint)) {
152 m_mouseDownWasSingleClickInSelection = true;
153 return false;
154 }
155 }
156
157 PositionWithAffinity eventPos = innerNode->layoutObject()->positionForPoint( event.localPoint());
158 VisiblePosition visiblePos(Strategy::toPositionType(eventPos.position()), ev entPos.affinity());
159 if (visiblePos.isNull())
160 visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOW NSTREAM);
161 PositionType pos = Strategy::toPositionType(visiblePos.deepEquivalent());
162
163 VisibleSelection newSelection = selection().selection();
164 TextGranularity granularity = CharacterGranularity;
165
166 if (extendSelection && newSelection.isCaretOrRange()) {
167 VisibleSelection selectionInUserSelectAll(expandSelectionToRespectUserSe lectAll(innerNode, VisibleSelection(VisiblePosition(pos))));
168 if (selectionInUserSelectAll.isRange()) {
169 if (Strategy::selectionStart(selectionInUserSelectAll).compareTo(Str ategy::selectionStart(newSelection)) < 0)
170 pos = Strategy::selectionStart(selectionInUserSelectAll);
171 else if (Strategy::selectionEnd(newSelection).compareTo(Strategy::se lectionEnd(selectionInUserSelectAll)) < 0)
172 pos = Strategy::selectionEnd(selectionInUserSelectAll);
173 }
174
175 if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() ) {
176 if (pos.isNotNull()) {
177 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click d eselects when selection
178 // was created right-to-left
179 PositionType start = Strategy::selectionStart(newSelection);
180 PositionType end = Strategy::selectionEnd(newSelection);
181 int distanceToStart = textDistance(start, pos);
182 int distanceToEnd = textDistance(pos, end);
183 if (distanceToStart <= distanceToEnd)
184 newSelection = VisibleSelection(end, pos);
185 else
186 newSelection = VisibleSelection(start, pos);
187 }
188 } else {
189 newSelection.setExtent(pos);
190 }
191
192 if (selection().granularity() != CharacterGranularity) {
193 granularity = selection().granularity();
194 expandSelectionUsingGranularity(newSelection, selection().granularit y());
195 }
196 } else {
197 newSelection = expandSelectionToRespectUserSelectAll(innerNode, VisibleS election(visiblePos));
198 }
199
200 // Updating the selection is considered side-effect of the event and so it d oesn't impact the handled state.
201 updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, g ranularity);
202 return false;
203 }
204
205 template <typename Strategy>
206 void SelectionController::updateSelectionForMouseDragAlgorithm(const HitTestResu lt& hitTestResult, Node* mousePressNode, const LayoutPoint& dragStartPos, const IntPoint& lastKnownMousePosition)
207 {
208 using PositionType = typename Strategy::PositionType;
209
210 if (!m_mouseDownMayStartSelect)
211 return;
212
213 Node* target = hitTestResult.innerNode();
214 if (!target)
215 return;
216
217 PositionWithAffinity rawTargetPosition = selection().selection().positionRes pectingEditingBoundary(hitTestResult.localPoint(), target);
218 VisiblePosition targetPosition = VisiblePosition(Strategy::toPositionType(ra wTargetPosition.position()), rawTargetPosition.affinity());
219 // Don't modify the selection if we're not on a node.
220 if (targetPosition.isNull())
221 return;
222
223 // Restart the selection if this is the first mouse move. This work is usual ly
224 // done in handleMousePressEvent, but not if the mouse press was on an exist ing selection.
225 VisibleSelection newSelection = selection().selection();
226
227 // Special case to limit selection to the containing block for SVG text.
228 // FIXME: Isn't there a better non-SVG-specific way to do this?
229 if (Node* selectionBaseNode = Strategy::selectionBase(newSelection).deprecat edNode()) {
230 if (LayoutObject* selectionBaseLayoutObject = selectionBaseNode->layoutO bject()) {
231 if (selectionBaseLayoutObject->isSVGText()) {
232 if (target->layoutObject()->containingBlock() != selectionBaseLa youtObject->containingBlock())
233 return;
234 }
235 }
236 }
237
238 if (m_selectionState == SelectionState::HaveNotStartedSelection && !dispatch SelectStart(target))
239 return;
240
241 if (m_selectionState != SelectionState::ExtendedSelection) {
242 // Always extend selection here because it's caused by a mouse drag
243 m_selectionState = SelectionState::ExtendedSelection;
244 newSelection = VisibleSelection(targetPosition);
245 }
246
247 if (RuntimeEnabledFeatures::userSelectAllEnabled()) {
248 Node* rootUserSelectAllForMousePressNode = Position::rootUserSelectAllFo rNode(mousePressNode);
249 if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePress Node == Position::rootUserSelectAllForNode(target)) {
250 newSelection.setBase(PositionType::beforeNode(rootUserSelectAllForMo usePressNode).upstream(CanCrossEditingBoundary));
251 newSelection.setExtent(PositionType::afterNode(rootUserSelectAllForM ousePressNode).downstream(CanCrossEditingBoundary));
252 } else {
253 // Reset base for user select all when base is inside user-select-al l area and extent < base.
254 if (rootUserSelectAllForMousePressNode) {
255 PositionType eventPosition = Strategy::toPositionType(target->la youtObject()->positionForPoint(hitTestResult.localPoint()).position());
256 PositionType dragStartPosition = Strategy::toPositionType(mouseP ressNode->layoutObject()->positionForPoint(dragStartPos).position());
257 if (eventPosition.compareTo(dragStartPosition) < 0)
258 newSelection.setBase(PositionType::afterNode(rootUserSelectA llForMousePressNode).downstream(CanCrossEditingBoundary));
259 }
260
261 Node* rootUserSelectAllForTarget = Position::rootUserSelectAllForNod e(target);
262 if (rootUserSelectAllForTarget && mousePressNode->layoutObject() && Strategy::toPositionType(target->layoutObject()->positionForPoint(hitTestResult. localPoint()).position()).compareTo(Strategy::toPositionType(mousePressNode->lay outObject()->positionForPoint(dragStartPos).position())) < 0)
263 newSelection.setExtent(PositionType::beforeNode(rootUserSelectAl lForTarget).upstream(CanCrossEditingBoundary));
264 else if (rootUserSelectAllForTarget && mousePressNode->layoutObject( ))
265 newSelection.setExtent(PositionType::afterNode(rootUserSelectAll ForTarget).downstream(CanCrossEditingBoundary));
266 else
267 newSelection.setExtent(targetPosition);
268 }
269 } else {
270 newSelection.setExtent(targetPosition);
271 }
272
273 if (selection().granularity() != CharacterGranularity)
274 expandSelectionUsingGranularity(newSelection, selection().granularity()) ;
275
276 selection().setNonDirectionalSelectionIfNeeded(newSelection, selection().gra nularity(),
277 FrameSelection::AdjustEndpointsAtBidiBoundary);
278 }
279
112 bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart(Node * targetNode, const VisibleSelection& selection, TextGranularity granularity) 280 bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart(Node * targetNode, const VisibleSelection& selection, TextGranularity granularity)
113 { 281 {
114 if (Position::nodeIsUserSelectNone(targetNode)) 282 if (Position::nodeIsUserSelectNone(targetNode))
115 return false; 283 return false;
116 284
117 if (!dispatchSelectStart(targetNode)) 285 if (!dispatchSelectStart(targetNode))
118 return false; 286 return false;
119 287
120 if (selection.isRange()) { 288 if (selection.isRange()) {
121 m_selectionState = SelectionState::ExtendedSelection; 289 m_selectionState = SelectionState::ExtendedSelection;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 VisibleSelection newSelection; 415 VisibleSelection newSelection;
248 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(event.localP oint())); 416 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(event.localP oint()));
249 if (pos.isNotNull()) { 417 if (pos.isNotNull()) {
250 newSelection = VisibleSelection(pos); 418 newSelection = VisibleSelection(pos);
251 expandSelectionUsingGranularity(newSelection, ParagraphGranularity); 419 expandSelectionUsingGranularity(newSelection, ParagraphGranularity);
252 } 420 }
253 421
254 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSe lectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity); 422 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSe lectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity);
255 } 423 }
256 424
257 template <typename PositionType>
258 static int textDistance(const PositionType& start, const PositionType& end)
259 {
260 return TextIteratorAlgorithm<typename PositionType::StrategyType>::rangeLeng th(start, end, true);
261 }
262
263 bool SelectionController::handleMousePressEventSingleClick(const MouseEventWithH itTestResults& event) 425 bool SelectionController::handleMousePressEventSingleClick(const MouseEventWithH itTestResults& event)
264 { 426 {
265 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) 427 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
266 return handleMousePressEventSingleClickAlgorithm<VisibleSelection::InCom posedTree>(event); 428 return handleMousePressEventSingleClickAlgorithm<VisibleSelection::InCom posedTree>(event);
267 return handleMousePressEventSingleClickAlgorithm<VisibleSelection::InDOMTree >(event); 429 return handleMousePressEventSingleClickAlgorithm<VisibleSelection::InDOMTree >(event);
268 } 430 }
269 431
270 template <typename Strategy>
271 bool SelectionController::handleMousePressEventSingleClickAlgorithm(const MouseE ventWithHitTestResults& event)
272 {
273 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventSingleClick ");
274 using PositionType = typename Strategy::PositionType;
275
276 m_frame->document()->updateLayoutIgnorePendingStylesheets();
277 Node* innerNode = event.innerNode();
278 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect))
279 return false;
280
281 // Extend the selection if the Shift key is down, unless the click is in a l ink.
282 bool extendSelection = event.event().shiftKey() && !event.isOverLink();
283
284 // Don't restart the selection when the mouse is pressed on an
285 // existing selection so we can allow for text dragging.
286 if (FrameView* view = m_frame->view()) {
287 LayoutPoint vPoint = view->rootFrameToContents(event.event().position()) ;
288 if (!extendSelection && selection().contains(vPoint)) {
289 m_mouseDownWasSingleClickInSelection = true;
290 return false;
291 }
292 }
293
294 PositionWithAffinity eventPos = innerNode->layoutObject()->positionForPoint( event.localPoint());
295 VisiblePosition visiblePos(Strategy::toPositionType(eventPos.position()), ev entPos.affinity());
296 if (visiblePos.isNull())
297 visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOW NSTREAM);
298 PositionType pos = Strategy::toPositionType(visiblePos.deepEquivalent());
299
300 VisibleSelection newSelection = selection().selection();
301 TextGranularity granularity = CharacterGranularity;
302
303 if (extendSelection && newSelection.isCaretOrRange()) {
304 VisibleSelection selectionInUserSelectAll(expandSelectionToRespectUserSe lectAll(innerNode, VisibleSelection(VisiblePosition(pos))));
305 if (selectionInUserSelectAll.isRange()) {
306 if (Strategy::selectionStart(selectionInUserSelectAll).compareTo(Str ategy::selectionStart(newSelection)) < 0)
307 pos = Strategy::selectionStart(selectionInUserSelectAll);
308 else if (Strategy::selectionEnd(newSelection).compareTo(Strategy::se lectionEnd(selectionInUserSelectAll)) < 0)
309 pos = Strategy::selectionEnd(selectionInUserSelectAll);
310 }
311
312 if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() ) {
313 if (pos.isNotNull()) {
314 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click d eselects when selection
315 // was created right-to-left
316 PositionType start = Strategy::selectionStart(newSelection);
317 PositionType end = Strategy::selectionEnd(newSelection);
318 int distanceToStart = textDistance(start, pos);
319 int distanceToEnd = textDistance(pos, end);
320 if (distanceToStart <= distanceToEnd)
321 newSelection = VisibleSelection(end, pos);
322 else
323 newSelection = VisibleSelection(start, pos);
324 }
325 } else {
326 newSelection.setExtent(pos);
327 }
328
329 if (selection().granularity() != CharacterGranularity) {
330 granularity = selection().granularity();
331 expandSelectionUsingGranularity(newSelection, selection().granularit y());
332 }
333 } else {
334 newSelection = expandSelectionToRespectUserSelectAll(innerNode, VisibleS election(visiblePos));
335 }
336
337 // Updating the selection is considered side-effect of the event and so it d oesn't impact the handled state.
338 updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, g ranularity);
339 return false;
340 }
341
342 static inline bool canMouseDownStartSelect(Node* node)
343 {
344 if (!node || !node->layoutObject())
345 return true;
346
347 if (!node->canStartSelection())
348 return false;
349
350 return true;
351 }
352
353 void SelectionController::handleMousePressEvent(const MouseEventWithHitTestResul ts& event) 432 void SelectionController::handleMousePressEvent(const MouseEventWithHitTestResul ts& event)
354 { 433 {
355 // If we got the event back, that must mean it wasn't prevented, 434 // If we got the event back, that must mean it wasn't prevented,
356 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. 435 // so it's allowed to start a drag or selection if it wasn't in a scrollbar.
357 m_mouseDownMayStartSelect = canMouseDownStartSelect(event.innerNode()) && !e vent.scrollbar(); 436 m_mouseDownMayStartSelect = canMouseDownStartSelect(event.innerNode()) && !e vent.scrollbar();
358 m_mouseDownWasSingleClickInSelection = false; 437 m_mouseDownWasSingleClickInSelection = false;
359 } 438 }
360 439
361 void SelectionController::handleMouseDraggedEvent(const MouseEventWithHitTestRes ults& event, const IntPoint& mouseDownPos, const LayoutPoint& dragStartPos, Node * mousePressNode, const IntPoint& lastKnownMousePosition) 440 void SelectionController::handleMouseDraggedEvent(const MouseEventWithHitTestRes ults& event, const IntPoint& mouseDownPos, const LayoutPoint& dragStartPos, Node * mousePressNode, const IntPoint& lastKnownMousePosition)
362 { 441 {
(...skipping 22 matching lines...) Expand all
385 updateSelectionForMouseDrag(result, mousePressNode, dragStartPos, lastKnownM ousePosition); 464 updateSelectionForMouseDrag(result, mousePressNode, dragStartPos, lastKnownM ousePosition);
386 } 465 }
387 466
388 void SelectionController::updateSelectionForMouseDrag(const HitTestResult& hitTe stResult, Node* mousePressNode, const LayoutPoint& dragStartPos, const IntPoint& lastKnownMousePosition) 467 void SelectionController::updateSelectionForMouseDrag(const HitTestResult& hitTe stResult, Node* mousePressNode, const LayoutPoint& dragStartPos, const IntPoint& lastKnownMousePosition)
389 { 468 {
390 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) 469 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
391 return updateSelectionForMouseDragAlgorithm<VisibleSelection::InComposed Tree>(hitTestResult, mousePressNode, dragStartPos, lastKnownMousePosition); 470 return updateSelectionForMouseDragAlgorithm<VisibleSelection::InComposed Tree>(hitTestResult, mousePressNode, dragStartPos, lastKnownMousePosition);
392 updateSelectionForMouseDragAlgorithm<VisibleSelection::InDOMTree>(hitTestRes ult, mousePressNode, dragStartPos, lastKnownMousePosition); 471 updateSelectionForMouseDragAlgorithm<VisibleSelection::InDOMTree>(hitTestRes ult, mousePressNode, dragStartPos, lastKnownMousePosition);
393 } 472 }
394 473
395 template <typename Strategy>
396 void SelectionController::updateSelectionForMouseDragAlgorithm(const HitTestResu lt& hitTestResult, Node* mousePressNode, const LayoutPoint& dragStartPos, const IntPoint& lastKnownMousePosition)
397 {
398 using PositionType = typename Strategy::PositionType;
399
400 if (!m_mouseDownMayStartSelect)
401 return;
402
403 Node* target = hitTestResult.innerNode();
404 if (!target)
405 return;
406
407 PositionWithAffinity rawTargetPosition = selection().selection().positionRes pectingEditingBoundary(hitTestResult.localPoint(), target);
408 VisiblePosition targetPosition = VisiblePosition(Strategy::toPositionType(ra wTargetPosition.position()), rawTargetPosition.affinity());
409 // Don't modify the selection if we're not on a node.
410 if (targetPosition.isNull())
411 return;
412
413 // Restart the selection if this is the first mouse move. This work is usual ly
414 // done in handleMousePressEvent, but not if the mouse press was on an exist ing selection.
415 VisibleSelection newSelection = selection().selection();
416
417 // Special case to limit selection to the containing block for SVG text.
418 // FIXME: Isn't there a better non-SVG-specific way to do this?
419 if (Node* selectionBaseNode = Strategy::selectionBase(newSelection).deprecat edNode()) {
420 if (LayoutObject* selectionBaseLayoutObject = selectionBaseNode->layoutO bject()) {
421 if (selectionBaseLayoutObject->isSVGText()) {
422 if (target->layoutObject()->containingBlock() != selectionBaseLa youtObject->containingBlock())
423 return;
424 }
425 }
426 }
427
428 if (m_selectionState == SelectionState::HaveNotStartedSelection && !dispatch SelectStart(target))
429 return;
430
431 if (m_selectionState != SelectionState::ExtendedSelection) {
432 // Always extend selection here because it's caused by a mouse drag
433 m_selectionState = SelectionState::ExtendedSelection;
434 newSelection = VisibleSelection(targetPosition);
435 }
436
437 if (RuntimeEnabledFeatures::userSelectAllEnabled()) {
438 Node* rootUserSelectAllForMousePressNode = Position::rootUserSelectAllFo rNode(mousePressNode);
439 if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePress Node == Position::rootUserSelectAllForNode(target)) {
440 newSelection.setBase(PositionType::beforeNode(rootUserSelectAllForMo usePressNode).upstream(CanCrossEditingBoundary));
441 newSelection.setExtent(PositionType::afterNode(rootUserSelectAllForM ousePressNode).downstream(CanCrossEditingBoundary));
442 } else {
443 // Reset base for user select all when base is inside user-select-al l area and extent < base.
444 if (rootUserSelectAllForMousePressNode) {
445 PositionType eventPosition = Strategy::toPositionType(target->la youtObject()->positionForPoint(hitTestResult.localPoint()).position());
446 PositionType dragStartPosition = Strategy::toPositionType(mouseP ressNode->layoutObject()->positionForPoint(dragStartPos).position());
447 if (eventPosition.compareTo(dragStartPosition) < 0)
448 newSelection.setBase(PositionType::afterNode(rootUserSelectA llForMousePressNode).downstream(CanCrossEditingBoundary));
449 }
450
451 Node* rootUserSelectAllForTarget = Position::rootUserSelectAllForNod e(target);
452 if (rootUserSelectAllForTarget && mousePressNode->layoutObject() && Strategy::toPositionType(target->layoutObject()->positionForPoint(hitTestResult. localPoint()).position()).compareTo(Strategy::toPositionType(mousePressNode->lay outObject()->positionForPoint(dragStartPos).position())) < 0)
453 newSelection.setExtent(PositionType::beforeNode(rootUserSelectAl lForTarget).upstream(CanCrossEditingBoundary));
454 else if (rootUserSelectAllForTarget && mousePressNode->layoutObject( ))
455 newSelection.setExtent(PositionType::afterNode(rootUserSelectAll ForTarget).downstream(CanCrossEditingBoundary));
456 else
457 newSelection.setExtent(targetPosition);
458 }
459 } else {
460 newSelection.setExtent(targetPosition);
461 }
462
463 if (selection().granularity() != CharacterGranularity)
464 expandSelectionUsingGranularity(newSelection, selection().granularity()) ;
465
466 selection().setNonDirectionalSelectionIfNeeded(newSelection, selection().gra nularity(),
467 FrameSelection::AdjustEndpointsAtBidiBoundary);
468 }
469
470 bool SelectionController::handleMouseReleaseEvent(const MouseEventWithHitTestRes ults& event, const LayoutPoint& dragStartPos) 474 bool SelectionController::handleMouseReleaseEvent(const MouseEventWithHitTestRes ults& event, const LayoutPoint& dragStartPos)
471 { 475 {
472 bool handled = false; 476 bool handled = false;
473 m_mouseDownMayStartSelect = false; 477 m_mouseDownMayStartSelect = false;
474 // Clear the selection if the mouse didn't move after the last mouse 478 // Clear the selection if the mouse didn't move after the last mouse
475 // press and it's not a context menu click. We do this so when clicking 479 // press and it's not a context menu click. We do this so when clicking
476 // on the selection, the selection goes away. However, if we are 480 // on the selection, the selection goes away. However, if we are
477 // editing, place the caret. 481 // editing, place the caret.
478 if (m_mouseDownWasSingleClickInSelection && m_selectionState != SelectionSta te::ExtendedSelection 482 if (m_mouseDownWasSingleClickInSelection && m_selectionState != SelectionSta te::ExtendedSelection
479 && dragStartPos == event.event().position() 483 && dragStartPos == event.event().position()
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 { 617 {
614 return m_mouseDownWasSingleClickInSelection; 618 return m_mouseDownWasSingleClickInSelection;
615 } 619 }
616 620
617 FrameSelection& SelectionController::selection() const 621 FrameSelection& SelectionController::selection() const
618 { 622 {
619 return m_frame->selection(); 623 return m_frame->selection();
620 } 624 }
621 625
622 } // namespace blink 626 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698