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

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

Issue 2201853002: Blink handle selection handle visibility (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed line length Created 4 years 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 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights
3 * reserved. 3 * reserved.
4 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) 4 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
5 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) 5 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies)
6 * Copyright (C) 2015 Google Inc. All rights reserved. 6 * Copyright (C) 2015 Google Inc. All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 160
161 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); 161 DCHECK(!m_frame->document()->needsLayoutTreeUpdate());
162 Node* innerNode = event.innerNode(); 162 Node* innerNode = event.innerNode();
163 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) 163 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect))
164 return false; 164 return false;
165 165
166 // Extend the selection if the Shift key is down, unless the click is in a 166 // Extend the selection if the Shift key is down, unless the click is in a
167 // link or image. 167 // link or image.
168 bool extendSelection = isExtendingSelection(event); 168 bool extendSelection = isExtendingSelection(event);
169 169
170 // Don't restart the selection when the mouse is pressed on an
171 // existing selection so we can allow for text dragging.
172 if (FrameView* view = m_frame->view()) {
173 LayoutPoint vPoint = view->rootFrameToContents(event.event().position());
174 if (!extendSelection && selection().contains(vPoint)) {
175 m_mouseDownWasSingleClickInSelection = true;
176 return false;
177 }
178 }
179
180 const VisiblePositionInFlatTree& visibleHitPos = 170 const VisiblePositionInFlatTree& visibleHitPos =
181 visiblePositionOfHitTestResult(event.hitTestResult()); 171 visiblePositionOfHitTestResult(event.hitTestResult());
182 const VisiblePositionInFlatTree& visiblePos = 172 const VisiblePositionInFlatTree& visiblePos =
183 visibleHitPos.isNull() 173 visibleHitPos.isNull()
184 ? createVisiblePosition( 174 ? createVisiblePosition(
185 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode)) 175 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode))
186 : visibleHitPos; 176 : visibleHitPos;
187 const VisibleSelectionInFlatTree& selection = 177 const VisibleSelectionInFlatTree& selection =
188 this->selection().visibleSelection<EditingInFlatTreeStrategy>(); 178 this->selection().visibleSelection<EditingInFlatTreeStrategy>();
189 179
180 // Don't restart the selection when the mouse is pressed on an
181 // existing selection so we can allow for text dragging.
182 if (!extendSelection && this->selection().contains(event.hitTestResult())) {
183 m_mouseDownWasSingleClickInSelection = true;
184 if (!event.event().fromTouch())
185 return false;
186
187 if (!this->selection().isHandleVisible()) {
188 updateSelectionForMouseDownDispatchingSelectStart(
189 innerNode, selection, CharacterGranularity,
190 HandleVisibility::Visible);
191 return false;
192 }
193 }
194
190 if (extendSelection && !selection.isNone()) { 195 if (extendSelection && !selection.isNone()) {
191 // Note: "fast/events/shift-click-user-select-none.html" makes 196 // Note: "fast/events/shift-click-user-select-none.html" makes
192 // |pos.isNull()| true. 197 // |pos.isNull()| true.
193 const PositionInFlatTree& pos = adjustPositionRespectUserSelectAll( 198 const PositionInFlatTree& pos = adjustPositionRespectUserSelectAll(
194 innerNode, selection.start(), selection.end(), 199 innerNode, selection.start(), selection.end(),
195 visiblePos.deepEquivalent()); 200 visiblePos.deepEquivalent());
196 SelectionInFlatTree::Builder builder; 201 SelectionInFlatTree::Builder builder;
197 builder.setGranularity(this->selection().granularity()); 202 builder.setGranularity(this->selection().granularity());
198 if (m_frame->editor().behavior().shouldConsiderSelectionAsDirectional()) { 203 if (m_frame->editor().behavior().shouldConsiderSelectionAsDirectional()) {
199 builder.setBaseAndExtent(selection.base(), pos); 204 builder.setBaseAndExtent(selection.base(), pos);
200 } else if (pos.isNull()) { 205 } else if (pos.isNull()) {
201 builder.setBaseAndExtent(selection.base(), selection.extent()); 206 builder.setBaseAndExtent(selection.base(), selection.extent());
202 } else { 207 } else {
203 // Shift+Click deselects when selection was created right-to-left 208 // Shift+Click deselects when selection was created right-to-left
204 const PositionInFlatTree& start = selection.start(); 209 const PositionInFlatTree& start = selection.start();
205 const PositionInFlatTree& end = selection.end(); 210 const PositionInFlatTree& end = selection.end();
206 const int distanceToStart = textDistance(start, pos); 211 const int distanceToStart = textDistance(start, pos);
207 const int distanceToEnd = textDistance(pos, end); 212 const int distanceToEnd = textDistance(pos, end);
208 builder.setBaseAndExtent(distanceToStart <= distanceToEnd ? end : start, 213 builder.setBaseAndExtent(distanceToStart <= distanceToEnd ? end : start,
209 pos); 214 pos);
210 } 215 }
211 216
212 updateSelectionForMouseDownDispatchingSelectStart( 217 updateSelectionForMouseDownDispatchingSelectStart(
213 innerNode, createVisibleSelection(builder.build()), 218 innerNode, createVisibleSelection(builder.build()),
214 this->selection().granularity()); 219 this->selection().granularity(), HandleVisibility::NotVisible);
215 return false; 220 return false;
216 } 221 }
217 222
218 if (m_selectionState == SelectionState::ExtendedSelection) { 223 if (m_selectionState == SelectionState::ExtendedSelection) {
219 updateSelectionForMouseDownDispatchingSelectStart(innerNode, selection, 224 updateSelectionForMouseDownDispatchingSelectStart(
220 CharacterGranularity); 225 innerNode, selection, CharacterGranularity,
226 HandleVisibility::NotVisible);
221 return false; 227 return false;
222 } 228 }
223 229
224 if (visiblePos.isNull()) { 230 if (visiblePos.isNull()) {
225 updateSelectionForMouseDownDispatchingSelectStart( 231 updateSelectionForMouseDownDispatchingSelectStart(
226 innerNode, VisibleSelectionInFlatTree(), CharacterGranularity); 232 innerNode, VisibleSelectionInFlatTree(), CharacterGranularity,
233 HandleVisibility::NotVisible);
227 return false; 234 return false;
228 } 235 }
229 236
237 bool isHandleVisible = false;
238 if (hasEditableStyle(*innerNode)) {
239 const bool isTextBoxEmpty =
240 createVisibleSelection(SelectionInFlatTree::Builder()
241 .selectAllChildren(*innerNode)
242 .build())
243 .isCaret();
244 const bool notLeftClick = event.event().pointerProperties().button !=
245 WebPointerProperties::Button::Left;
246 if (!isTextBoxEmpty || notLeftClick)
247 isHandleVisible = event.event().fromTouch();
248 }
249
230 updateSelectionForMouseDownDispatchingSelectStart( 250 updateSelectionForMouseDownDispatchingSelectStart(
231 innerNode, 251 innerNode,
232 expandSelectionToRespectUserSelectAll( 252 expandSelectionToRespectUserSelectAll(
233 innerNode, createVisibleSelection( 253 innerNode, createVisibleSelection(
234 SelectionInFlatTree::Builder() 254 SelectionInFlatTree::Builder()
235 .collapse(visiblePos.toPositionWithAffinity()) 255 .collapse(visiblePos.toPositionWithAffinity())
236 .build())), 256 .build())),
237 CharacterGranularity); 257 CharacterGranularity, isHandleVisible ? HandleVisibility::Visible
258 : HandleVisibility::NotVisible);
238 return false; 259 return false;
239 } 260 }
240 261
241 void SelectionController::updateSelectionForMouseDrag( 262 void SelectionController::updateSelectionForMouseDrag(
242 const HitTestResult& hitTestResult, 263 const HitTestResult& hitTestResult,
243 Node* mousePressNode, 264 Node* mousePressNode,
244 const LayoutPoint& dragStartPos, 265 const LayoutPoint& dragStartPos,
245 const IntPoint& lastKnownMousePosition) { 266 const IntPoint& lastKnownMousePosition) {
246 if (!m_mouseDownMayStartSelect) 267 if (!m_mouseDownMayStartSelect)
247 return; 268 return;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 // |newSelection|. 378 // |newSelection|.
358 if (selection().granularity() != CharacterGranularity) { 379 if (selection().granularity() != CharacterGranularity) {
359 newSelection = createVisibleSelection( 380 newSelection = createVisibleSelection(
360 SelectionInFlatTree::Builder() 381 SelectionInFlatTree::Builder()
361 .setBaseAndExtent(newSelection.base(), newSelection.extent()) 382 .setBaseAndExtent(newSelection.base(), newSelection.extent())
362 .setGranularity(selection().granularity()) 383 .setGranularity(selection().granularity())
363 .build()); 384 .build());
364 } 385 }
365 386
366 setNonDirectionalSelectionIfNeeded(newSelection, selection().granularity(), 387 setNonDirectionalSelectionIfNeeded(newSelection, selection().granularity(),
367 AdjustEndpointsAtBidiBoundary); 388 AdjustEndpointsAtBidiBoundary,
389 HandleVisibility::NotVisible);
368 } 390 }
369 391
370 bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart( 392 bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart(
371 Node* targetNode, 393 Node* targetNode,
372 const VisibleSelectionInFlatTree& selection, 394 const VisibleSelectionInFlatTree& selection,
373 TextGranularity granularity) { 395 TextGranularity granularity,
396 HandleVisibility handleVisibility) {
374 if (targetNode && targetNode->layoutObject() && 397 if (targetNode && targetNode->layoutObject() &&
375 !targetNode->layoutObject()->isSelectable()) 398 !targetNode->layoutObject()->isSelectable())
376 return false; 399 return false;
377 400
378 if (dispatchSelectStart(targetNode) != DispatchEventResult::NotCanceled) 401 if (dispatchSelectStart(targetNode) != DispatchEventResult::NotCanceled)
379 return false; 402 return false;
380 403
381 // |dispatchSelectStart()| can change document hosted by |m_frame|. 404 // |dispatchSelectStart()| can change document hosted by |m_frame|.
382 if (!this->selection().isAvailable()) 405 if (!this->selection().isAvailable())
383 return false; 406 return false;
384 407
385 if (!selection.isValidFor(this->selection().document())) 408 if (!selection.isValidFor(this->selection().document()))
386 return false; 409 return false;
387 410
388 if (selection.isRange()) { 411 if (selection.isRange()) {
389 m_selectionState = SelectionState::ExtendedSelection; 412 m_selectionState = SelectionState::ExtendedSelection;
390 } else { 413 } else {
391 granularity = CharacterGranularity; 414 granularity = CharacterGranularity;
392 m_selectionState = SelectionState::PlacedCaret; 415 m_selectionState = SelectionState::PlacedCaret;
393 } 416 }
394 417
395 setNonDirectionalSelectionIfNeeded(selection, granularity, 418 setNonDirectionalSelectionIfNeeded(selection, granularity,
396 DoNotAdjustEndpoints); 419 DoNotAdjustEndpoints, handleVisibility);
397 420
398 return true; 421 return true;
399 } 422 }
400 423
401 bool SelectionController::selectClosestWordFromHitTestResult( 424 bool SelectionController::selectClosestWordFromHitTestResult(
402 const HitTestResult& result, 425 const HitTestResult& result,
403 AppendTrailingWhitespace appendTrailingWhitespace, 426 AppendTrailingWhitespace appendTrailingWhitespace,
404 SelectInputEventType selectInputEventType) { 427 SelectInputEventType selectInputEventType) {
405 Node* innerNode = result.innerNode(); 428 Node* innerNode = result.innerNode();
406 VisibleSelectionInFlatTree newSelection; 429 VisibleSelectionInFlatTree newSelection;
(...skipping 13 matching lines...) Expand all
420 const VisiblePositionInFlatTree& pos = 443 const VisiblePositionInFlatTree& pos =
421 visiblePositionOfHitTestResult(adjustedHitTestResult); 444 visiblePositionOfHitTestResult(adjustedHitTestResult);
422 if (pos.isNotNull()) { 445 if (pos.isNotNull()) {
423 newSelection = 446 newSelection =
424 createVisibleSelection(SelectionInFlatTree::Builder() 447 createVisibleSelection(SelectionInFlatTree::Builder()
425 .collapse(pos.toPositionWithAffinity()) 448 .collapse(pos.toPositionWithAffinity())
426 .setGranularity(WordGranularity) 449 .setGranularity(WordGranularity)
427 .build()); 450 .build());
428 } 451 }
429 452
453 HandleVisibility visibility = HandleVisibility::NotVisible;
430 if (selectInputEventType == SelectInputEventType::Touch) { 454 if (selectInputEventType == SelectInputEventType::Touch) {
431 // If node doesn't have text except space, tab or line break, do not 455 // If node doesn't have text except space, tab or line break, do not
432 // select that 'empty' area. 456 // select that 'empty' area.
433 EphemeralRangeInFlatTree range(newSelection.start(), newSelection.end()); 457 EphemeralRangeInFlatTree range(newSelection.start(), newSelection.end());
434 const String& str = 458 const String& str =
435 plainText(range, hasEditableStyle(*innerNode) 459 plainText(range, hasEditableStyle(*innerNode)
436 ? TextIteratorEmitsObjectReplacementCharacter 460 ? TextIteratorEmitsObjectReplacementCharacter
437 : TextIteratorDefaultBehavior); 461 : TextIteratorDefaultBehavior);
438 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace()) 462 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace())
439 return false; 463 return false;
440 464
441 if (newSelection.rootEditableElement() && 465 if (newSelection.rootEditableElement() &&
442 pos.deepEquivalent() == 466 pos.deepEquivalent() ==
443 VisiblePositionInFlatTree::lastPositionInNode( 467 VisiblePositionInFlatTree::lastPositionInNode(
444 newSelection.rootEditableElement()) 468 newSelection.rootEditableElement())
445 .deepEquivalent()) 469 .deepEquivalent())
446 return false; 470 return false;
471
472 visibility = HandleVisibility::Visible;
447 } 473 }
448 474
449 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) 475 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend)
450 newSelection.appendTrailingWhitespace(); 476 newSelection.appendTrailingWhitespace();
451 477
452 return updateSelectionForMouseDownDispatchingSelectStart( 478 return updateSelectionForMouseDownDispatchingSelectStart(
453 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), 479 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection),
454 WordGranularity); 480 WordGranularity, visibility);
455 } 481 }
456 482
457 void SelectionController::selectClosestMisspellingFromHitTestResult( 483 void SelectionController::selectClosestMisspellingFromHitTestResult(
458 const HitTestResult& result, 484 const HitTestResult& result,
459 AppendTrailingWhitespace appendTrailingWhitespace) { 485 AppendTrailingWhitespace appendTrailingWhitespace) {
460 Node* innerNode = result.innerNode(); 486 Node* innerNode = result.innerNode();
461 VisibleSelectionInFlatTree newSelection; 487 VisibleSelectionInFlatTree newSelection;
462 488
463 if (!innerNode || !innerNode->layoutObject()) 489 if (!innerNode || !innerNode->layoutObject())
464 return; 490 return;
(...skipping 13 matching lines...) Expand all
478 newSelection = createVisibleSelection( 504 newSelection = createVisibleSelection(
479 SelectionInFlatTree::Builder().collapse(start).extend(end).build()); 505 SelectionInFlatTree::Builder().collapse(start).extend(end).build());
480 } 506 }
481 } 507 }
482 508
483 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) 509 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend)
484 newSelection.appendTrailingWhitespace(); 510 newSelection.appendTrailingWhitespace();
485 511
486 updateSelectionForMouseDownDispatchingSelectStart( 512 updateSelectionForMouseDownDispatchingSelectStart(
487 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), 513 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection),
488 WordGranularity); 514 WordGranularity, HandleVisibility::NotVisible);
489 } 515 }
490 516
491 void SelectionController::selectClosestWordFromMouseEvent( 517 void SelectionController::selectClosestWordFromMouseEvent(
492 const MouseEventWithHitTestResults& result) { 518 const MouseEventWithHitTestResults& result) {
493 if (!m_mouseDownMayStartSelect) 519 if (!m_mouseDownMayStartSelect)
494 return; 520 return;
495 521
496 AppendTrailingWhitespace appendTrailingWhitespace = 522 AppendTrailingWhitespace appendTrailingWhitespace =
497 (result.event().clickCount() == 2 && 523 (result.event().clickCount() == 2 &&
498 m_frame->editor().isSelectTrailingWhitespaceEnabled()) 524 m_frame->editor().isSelectTrailingWhitespaceEnabled())
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 const VisiblePositionInFlatTree pos = 561 const VisiblePositionInFlatTree pos =
536 visiblePositionOfHitTestResult(result.hitTestResult()); 562 visiblePositionOfHitTestResult(result.hitTestResult());
537 if (pos.isNotNull() && 563 if (pos.isNotNull() &&
538 pos.deepEquivalent().anchorNode()->isDescendantOf(URLElement)) { 564 pos.deepEquivalent().anchorNode()->isDescendantOf(URLElement)) {
539 newSelection = createVisibleSelection( 565 newSelection = createVisibleSelection(
540 SelectionInFlatTree::Builder().selectAllChildren(*URLElement).build()); 566 SelectionInFlatTree::Builder().selectAllChildren(*URLElement).build());
541 } 567 }
542 568
543 updateSelectionForMouseDownDispatchingSelectStart( 569 updateSelectionForMouseDownDispatchingSelectStart(
544 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), 570 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection),
545 WordGranularity); 571 WordGranularity, HandleVisibility::NotVisible);
546 } 572 }
547 573
548 // TODO(xiaochengh): We should not use reference to return value. 574 // TODO(xiaochengh): We should not use reference to return value.
549 static void adjustEndpointsAtBidiBoundary( 575 static void adjustEndpointsAtBidiBoundary(
550 VisiblePositionInFlatTree& visibleBase, 576 VisiblePositionInFlatTree& visibleBase,
551 VisiblePositionInFlatTree& visibleExtent) { 577 VisiblePositionInFlatTree& visibleExtent) {
552 DCHECK(visibleBase.isValid()); 578 DCHECK(visibleBase.isValid());
553 DCHECK(visibleExtent.isValid()); 579 DCHECK(visibleExtent.isValid());
554 580
555 RenderedPosition base(visibleBase); 581 RenderedPosition base(visibleBase);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) { 619 base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) {
594 visibleExtent = createVisiblePosition( 620 visibleExtent = createVisiblePosition(
595 toPositionInFlatTree(extent.positionAtRightBoundaryOfBiDiRun())); 621 toPositionInFlatTree(extent.positionAtRightBoundaryOfBiDiRun()));
596 return; 622 return;
597 } 623 }
598 } 624 }
599 625
600 void SelectionController::setNonDirectionalSelectionIfNeeded( 626 void SelectionController::setNonDirectionalSelectionIfNeeded(
601 const VisibleSelectionInFlatTree& passedNewSelection, 627 const VisibleSelectionInFlatTree& passedNewSelection,
602 TextGranularity granularity, 628 TextGranularity granularity,
603 EndPointsAdjustmentMode endpointsAdjustmentMode) { 629 EndPointsAdjustmentMode endpointsAdjustmentMode,
630 HandleVisibility handleVisibility) {
604 VisibleSelectionInFlatTree newSelection = passedNewSelection; 631 VisibleSelectionInFlatTree newSelection = passedNewSelection;
605 bool isDirectional = 632 bool isDirectional =
606 m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() || 633 m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() ||
607 newSelection.isDirectional(); 634 newSelection.isDirectional();
608 635
609 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets 636 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
610 // needs to be audited. See http://crbug.com/590369 for more details. 637 // needs to be audited. See http://crbug.com/590369 for more details.
611 document().updateStyleAndLayoutIgnorePendingStylesheets(); 638 document().updateStyleAndLayoutIgnorePendingStylesheets();
612 639
613 const PositionInFlatTree& basePosition = 640 const PositionInFlatTree& basePosition =
(...skipping 19 matching lines...) Expand all
633 newSelection.setExtent(newExtent); 660 newSelection.setExtent(newExtent);
634 } else if (originalBase.isNotNull()) { 661 } else if (originalBase.isNotNull()) {
635 if (selection().visibleSelection<EditingInFlatTreeStrategy>().base() == 662 if (selection().visibleSelection<EditingInFlatTreeStrategy>().base() ==
636 newSelection.base()) 663 newSelection.base())
637 newSelection.setBase(originalBase); 664 newSelection.setBase(originalBase);
638 m_originalBaseInFlatTree = VisiblePositionInFlatTree(); 665 m_originalBaseInFlatTree = VisiblePositionInFlatTree();
639 } 666 }
640 667
641 // Adjusting base and extent will make newSelection always directional 668 // Adjusting base and extent will make newSelection always directional
642 newSelection.setIsDirectional(isDirectional); 669 newSelection.setIsDirectional(isDirectional);
643 if (selection().visibleSelection<EditingInFlatTreeStrategy>() == newSelection) 670 const bool isHandleVisible = handleVisibility == HandleVisibility::Visible;
671 if (selection().visibleSelection<EditingInFlatTreeStrategy>() ==
672 newSelection &&
673 selection().isHandleVisible() == isHandleVisible)
644 return; 674 return;
645 675
646 const FrameSelection::SetSelectionOptions options = 676 FrameSelection::SetSelectionOptions options =
647 FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle; 677 FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle;
678 if (isHandleVisible)
679 options |= FrameSelection::HandleVisible;
648 selection().setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded, 680 selection().setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded,
649 granularity); 681 granularity);
650 } 682 }
651 683
652 bool SelectionController::setCaretAtHitTestResult( 684 bool SelectionController::setCaretAtHitTestResult(
653 const HitTestResult& hitTestResult) { 685 const HitTestResult& hitTestResult) {
654 Node* innerNode = hitTestResult.innerNode(); 686 Node* innerNode = hitTestResult.innerNode();
655 if (!innerNode) 687 if (!innerNode)
656 return false; 688 return false;
657 689
658 const VisiblePositionInFlatTree& visibleHitPos = 690 const VisiblePositionInFlatTree& visibleHitPos =
659 visiblePositionOfHitTestResult(hitTestResult); 691 visiblePositionOfHitTestResult(hitTestResult);
660 const VisiblePositionInFlatTree& visiblePos = 692 const VisiblePositionInFlatTree& visiblePos =
661 visibleHitPos.isNull() 693 visibleHitPos.isNull()
662 ? createVisiblePosition( 694 ? createVisiblePosition(
663 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode)) 695 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode))
664 : visibleHitPos; 696 : visibleHitPos;
665 697
666 return updateSelectionForMouseDownDispatchingSelectStart( 698 return updateSelectionForMouseDownDispatchingSelectStart(
667 innerNode, 699 innerNode,
668 expandSelectionToRespectUserSelectAll( 700 expandSelectionToRespectUserSelectAll(
669 innerNode, createVisibleSelection( 701 innerNode, createVisibleSelection(
670 SelectionInFlatTree::Builder() 702 SelectionInFlatTree::Builder()
671 .collapse(visiblePos.toPositionWithAffinity()) 703 .collapse(visiblePos.toPositionWithAffinity())
672 .build())), 704 .build())),
673 CharacterGranularity); 705 CharacterGranularity, HandleVisibility::Visible);
674 } 706 }
675 707
676 bool SelectionController::handleMousePressEventDoubleClick( 708 bool SelectionController::handleMousePressEventDoubleClick(
677 const MouseEventWithHitTestResults& event) { 709 const MouseEventWithHitTestResults& event) {
678 TRACE_EVENT0("blink", 710 TRACE_EVENT0("blink",
679 "SelectionController::handleMousePressEventDoubleClick"); 711 "SelectionController::handleMousePressEventDoubleClick");
680 712
681 if (!selection().isAvailable()) 713 if (!selection().isAvailable())
682 return false; 714 return false;
683 715
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 const VisiblePositionInFlatTree& pos = 758 const VisiblePositionInFlatTree& pos =
727 visiblePositionOfHitTestResult(event.hitTestResult()); 759 visiblePositionOfHitTestResult(event.hitTestResult());
728 if (pos.isNotNull()) { 760 if (pos.isNotNull()) {
729 newSelection = 761 newSelection =
730 createVisibleSelection(SelectionInFlatTree::Builder() 762 createVisibleSelection(SelectionInFlatTree::Builder()
731 .collapse(pos.toPositionWithAffinity()) 763 .collapse(pos.toPositionWithAffinity())
732 .setGranularity(ParagraphGranularity) 764 .setGranularity(ParagraphGranularity)
733 .build()); 765 .build());
734 } 766 }
735 767
768 bool isHandleVisible = event.event().fromTouch() && newSelection.isRange();
769
736 return updateSelectionForMouseDownDispatchingSelectStart( 770 return updateSelectionForMouseDownDispatchingSelectStart(
737 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), 771 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection),
738 ParagraphGranularity); 772 ParagraphGranularity, isHandleVisible ? HandleVisibility::Visible
773 : HandleVisibility::NotVisible);
739 } 774 }
740 775
741 void SelectionController::handleMousePressEvent( 776 void SelectionController::handleMousePressEvent(
742 const MouseEventWithHitTestResults& event) { 777 const MouseEventWithHitTestResults& event) {
743 // If we got the event back, that must mean it wasn't prevented, 778 // If we got the event back, that must mean it wasn't prevented,
744 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. 779 // so it's allowed to start a drag or selection if it wasn't in a scrollbar.
745 m_mouseDownMayStartSelect = 780 m_mouseDownMayStartSelect =
746 (canMouseDownStartSelect(event.innerNode()) || isLinkSelection(event)) && 781 (canMouseDownStartSelect(event.innerNode()) || isLinkSelection(event)) &&
747 !event.scrollbar(); 782 !event.scrollbar();
748 m_mouseDownWasSingleClickInSelection = false; 783 m_mouseDownWasSingleClickInSelection = false;
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 pos.deepEquivalent().parentAnchoredEquivalent()), 973 pos.deepEquivalent().parentAnchoredEquivalent()),
939 DocumentMarker::MisspellingMarkers()) 974 DocumentMarker::MisspellingMarkers())
940 .size() > 0; 975 .size() > 0;
941 } 976 }
942 977
943 void SelectionController::sendContextMenuEvent( 978 void SelectionController::sendContextMenuEvent(
944 const MouseEventWithHitTestResults& mev, 979 const MouseEventWithHitTestResults& mev,
945 const LayoutPoint& position) { 980 const LayoutPoint& position) {
946 if (!selection().isAvailable()) 981 if (!selection().isAvailable())
947 return; 982 return;
948 if (selection().contains(position) || mev.scrollbar() || 983 if (selection().contains(mev.hitTestResult()) || mev.scrollbar() ||
949 // FIXME: In the editable case, word selection sometimes selects content 984 // FIXME: In the editable case, word selection sometimes selects content
950 // that isn't underneath the mouse. 985 // that isn't underneath the mouse.
951 // If the selection is non-editable, we do word selection to make it 986 // If the selection is non-editable, we do word selection to make it
952 // easier to use the contextual menu items available for text selections. 987 // easier to use the contextual menu items available for text selections.
953 // But only if we're above text. 988 // But only if we're above text.
954 !(selection().isContentEditable() || 989 !(selection().isContentEditable() ||
955 (mev.innerNode() && mev.innerNode()->isTextNode()))) 990 (mev.innerNode() && mev.innerNode()->isTextNode())))
956 return; 991 return;
957 992
958 // Context menu events are always allowed to perform a selection. 993 // Context menu events are always allowed to perform a selection.
959 AutoReset<bool> mouseDownMayStartSelectChange(&m_mouseDownMayStartSelect, 994 AutoReset<bool> mouseDownMayStartSelectChange(&m_mouseDownMayStartSelect,
960 true); 995 true);
961 996
962 if (hitTestResultIsMisspelled(mev.hitTestResult())) 997 if (hitTestResultIsMisspelled(mev.hitTestResult()))
963 return selectClosestMisspellingFromMouseEvent(mev); 998 return selectClosestMisspellingFromMouseEvent(mev);
964 999
965 if (!m_frame->editor().behavior().shouldSelectOnContextualMenuClick()) 1000 if (!m_frame->editor().behavior().shouldSelectOnContextualMenuClick())
966 return; 1001 return;
967 1002
968 selectClosestWordOrLinkFromMouseEvent(mev); 1003 selectClosestWordOrLinkFromMouseEvent(mev);
969 } 1004 }
970 1005
971 void SelectionController::passMousePressEventToSubframe( 1006 void SelectionController::passMousePressEventToSubframe(
972 const MouseEventWithHitTestResults& mev) { 1007 const MouseEventWithHitTestResults& mev) {
973 // If we're clicking into a frame that is selected, the frame will appear 1008 // If we're clicking into a frame that is selected, the frame will appear
974 // greyed out even though we're clicking on the selection. This looks 1009 // greyed out even though we're clicking on the selection. This looks
975 // really strange (having the whole frame be greyed out), so we deselect the 1010 // really strange (having the whole frame be greyed out), so we deselect the
976 // selection. 1011 // selection.
977 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); 1012 if (!selection().contains(mev.hitTestResult()))
978 if (!selection().contains(p))
979 return; 1013 return;
980 1014
981 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets 1015 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
982 // needs to be audited. See http://crbug.com/590369 for more details. 1016 // needs to be audited. See http://crbug.com/590369 for more details.
983 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); 1017 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();
984 1018
985 const VisiblePositionInFlatTree& visiblePos = 1019 const VisiblePositionInFlatTree& visiblePos =
986 visiblePositionOfHitTestResult(mev.hitTestResult()); 1020 visiblePositionOfHitTestResult(mev.hitTestResult());
987 if (visiblePos.isNull()) { 1021 if (visiblePos.isNull()) {
988 selection().setSelection(VisibleSelectionInFlatTree()); 1022 selection().setSelection(VisibleSelectionInFlatTree());
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 return event.event().altKey() && event.isOverLink(); 1060 return event.event().altKey() && event.isOverLink();
1027 } 1061 }
1028 1062
1029 bool isExtendingSelection(const MouseEventWithHitTestResults& event) { 1063 bool isExtendingSelection(const MouseEventWithHitTestResults& event) {
1030 bool isMouseDownOnLinkOrImage = 1064 bool isMouseDownOnLinkOrImage =
1031 event.isOverLink() || event.hitTestResult().image(); 1065 event.isOverLink() || event.hitTestResult().image();
1032 return event.event().shiftKey() && !isMouseDownOnLinkOrImage; 1066 return event.event().shiftKey() && !isMouseDownOnLinkOrImage;
1033 } 1067 }
1034 1068
1035 } // namespace blink 1069 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698