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

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: try running even rebaseline tests Created 4 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 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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 130
131 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); 131 DCHECK(!m_frame->document()->needsLayoutTreeUpdate());
132 Node* innerNode = event.innerNode(); 132 Node* innerNode = event.innerNode();
133 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) 133 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect))
134 return false; 134 return false;
135 135
136 // Extend the selection if the Shift key is down, unless the click is in a 136 // Extend the selection if the Shift key is down, unless the click is in a
137 // link or image. 137 // link or image.
138 bool extendSelection = isExtendingSelection(event); 138 bool extendSelection = isExtendingSelection(event);
139 139
140 VisibleSelectionInFlatTree newSelection =
141 selection().visibleSelection<EditingInFlatTreeStrategy>();
142
140 // Don't restart the selection when the mouse is pressed on an 143 // Don't restart the selection when the mouse is pressed on an
141 // existing selection so we can allow for text dragging. 144 // existing selection so we can allow for text dragging.
142 if (FrameView* view = m_frame->view()) { 145 if (!extendSelection && selection().contains(event.hitTestResult())) {
143 LayoutPoint vPoint = view->rootFrameToContents(event.event().position()); 146 m_mouseDownWasSingleClickInSelection = true;
144 if (!extendSelection && selection().contains(vPoint)) { 147 if (!event.event().fromTouch())
145 m_mouseDownWasSingleClickInSelection = true;
146 return false; 148 return false;
147 }
148 } 149 }
149 150
150 VisiblePositionInFlatTree visiblePos = 151 VisiblePositionInFlatTree visiblePos =
151 visiblePositionOfHitTestResult(event.hitTestResult()); 152 visiblePositionOfHitTestResult(event.hitTestResult());
152 if (visiblePos.isNull()) 153 if (visiblePos.isNull())
153 visiblePos = createVisiblePosition( 154 visiblePos = createVisiblePosition(
154 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode)); 155 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode));
155 PositionInFlatTree pos = visiblePos.deepEquivalent(); 156 PositionInFlatTree pos = visiblePos.deepEquivalent();
156 157
157 VisibleSelectionInFlatTree newSelection =
158 selection().visibleSelection<EditingInFlatTreeStrategy>();
159 TextGranularity granularity = CharacterGranularity; 158 TextGranularity granularity = CharacterGranularity;
160 159
161 if (extendSelection && !newSelection.isNone()) { 160 if (mouseDownWasSingleClickInSelection() && !newSelection.isHandleVisible()) {
161 newSelection.setIsHandleVisible(true);
162 } else if (extendSelection && !newSelection.isNone()) {
162 const VisibleSelectionInFlatTree selectionInUserSelectAll( 163 const VisibleSelectionInFlatTree selectionInUserSelectAll(
163 expandSelectionToRespectUserSelectAll(innerNode, 164 expandSelectionToRespectUserSelectAll(innerNode,
164 createVisibleSelection(pos))); 165 createVisibleSelection(pos)));
165 if (selectionInUserSelectAll.isRange()) { 166 if (selectionInUserSelectAll.isRange()) {
166 if (selectionInUserSelectAll.start().compareTo(newSelection.start()) < 0) 167 if (selectionInUserSelectAll.start().compareTo(newSelection.start()) < 0)
167 pos = selectionInUserSelectAll.start(); 168 pos = selectionInUserSelectAll.start();
168 else if (newSelection.end().compareTo(selectionInUserSelectAll.end()) < 0) 169 else if (newSelection.end().compareTo(selectionInUserSelectAll.end()) < 0)
169 pos = selectionInUserSelectAll.end(); 170 pos = selectionInUserSelectAll.end();
170 } 171 }
171 172
(...skipping 14 matching lines...) Expand all
186 newSelection.setExtent(pos); 187 newSelection.setExtent(pos);
187 } 188 }
188 189
189 if (selection().granularity() != CharacterGranularity) { 190 if (selection().granularity() != CharacterGranularity) {
190 granularity = selection().granularity(); 191 granularity = selection().granularity();
191 newSelection.expandUsingGranularity(selection().granularity()); 192 newSelection.expandUsingGranularity(selection().granularity());
192 } 193 }
193 } else if (m_selectionState != SelectionState::ExtendedSelection) { 194 } else if (m_selectionState != SelectionState::ExtendedSelection) {
194 newSelection = expandSelectionToRespectUserSelectAll( 195 newSelection = expandSelectionToRespectUserSelectAll(
195 innerNode, createVisibleSelection(visiblePos)); 196 innerNode, createVisibleSelection(visiblePos));
197 if (newSelection.isContentEditable()) {
198 bool isTextBoxEmpty =
199 VisibleSelection::selectionFromContentsOfNode(innerNode).isCaret();
200 bool notLeftClick = event.event().pointerProperties().button !=
201 WebPointerProperties::Button::Left;
202 if (!isTextBoxEmpty || notLeftClick)
203 newSelection.setIsHandleVisible(event.event().fromTouch());
aelias_OOO_until_Jul13 2016/10/07 02:40:20 Can you add a test that handles are *not* created
amaralp 2016/10/14 00:53:07 Added to EventHandlerTest.cpp
204 }
196 } 205 }
197 206
198 // Updating the selection is considered side-effect of the event and so it 207 // Updating the selection is considered side-effect of the event and so it
199 // doesn't impact the handled state. 208 // doesn't impact the handled state.
200 updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, 209 updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection,
201 granularity); 210 granularity);
202 return false; 211 return false;
203 } 212 }
204 213
205 void SelectionController::updateSelectionForMouseDrag( 214 void SelectionController::updateSelectionForMouseDrag(
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 : TextIteratorDefaultBehavior); 398 : TextIteratorDefaultBehavior);
390 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace()) 399 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace())
391 return; 400 return;
392 401
393 if (newSelection.rootEditableElement() && 402 if (newSelection.rootEditableElement() &&
394 pos.deepEquivalent() == 403 pos.deepEquivalent() ==
395 VisiblePositionInFlatTree::lastPositionInNode( 404 VisiblePositionInFlatTree::lastPositionInNode(
396 newSelection.rootEditableElement()) 405 newSelection.rootEditableElement())
397 .deepEquivalent()) 406 .deepEquivalent())
398 return; 407 return;
408 newSelection.setIsHandleVisible(true);
399 } 409 }
400 410
401 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend && 411 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend &&
402 newSelection.isRange()) 412 newSelection.isRange())
403 newSelection.appendTrailingWhitespace(); 413 newSelection.appendTrailingWhitespace();
404 414
405 updateSelectionForMouseDownDispatchingSelectStart( 415 updateSelectionForMouseDownDispatchingSelectStart(
406 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), 416 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection),
407 WordGranularity); 417 WordGranularity);
408 } 418 }
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 return false; 557 return false;
548 558
549 VisibleSelectionInFlatTree newSelection; 559 VisibleSelectionInFlatTree newSelection;
550 const VisiblePositionInFlatTree& pos = 560 const VisiblePositionInFlatTree& pos =
551 visiblePositionOfHitTestResult(event.hitTestResult()); 561 visiblePositionOfHitTestResult(event.hitTestResult());
552 if (pos.isNotNull()) { 562 if (pos.isNotNull()) {
553 newSelection = createVisibleSelection(pos); 563 newSelection = createVisibleSelection(pos);
554 newSelection.expandUsingGranularity(ParagraphGranularity); 564 newSelection.expandUsingGranularity(ParagraphGranularity);
555 } 565 }
556 566
567 newSelection.setIsHandleVisible(event.event().fromTouch() &&
568 newSelection.isRange());
569
557 return updateSelectionForMouseDownDispatchingSelectStart( 570 return updateSelectionForMouseDownDispatchingSelectStart(
558 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), 571 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection),
559 ParagraphGranularity); 572 ParagraphGranularity);
560 } 573 }
561 574
562 void SelectionController::handleMousePressEvent( 575 void SelectionController::handleMousePressEvent(
563 const MouseEventWithHitTestResults& event) { 576 const MouseEventWithHitTestResults& event) {
564 // If we got the event back, that must mean it wasn't prevented, 577 // If we got the event back, that must mean it wasn't prevented,
565 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. 578 // so it's allowed to start a drag or selection if it wasn't in a scrollbar.
566 m_mouseDownMayStartSelect = 579 m_mouseDownMayStartSelect =
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 726
714 Node* innerNode = hitTestResult.innerNode(); 727 Node* innerNode = hitTestResult.innerNode();
715 if (!innerNode) 728 if (!innerNode)
716 return false; 729 return false;
717 innerNode->document().updateStyleAndLayoutTree(); 730 innerNode->document().updateStyleAndLayoutTree();
718 bool innerNodeIsSelectable = 731 bool innerNodeIsSelectable =
719 hasEditableStyle(*innerNode) || innerNode->canStartSelection(); 732 hasEditableStyle(*innerNode) || innerNode->canStartSelection();
720 if (!innerNodeIsSelectable) 733 if (!innerNodeIsSelectable)
721 return false; 734 return false;
722 735
736 // If longpress occurs inside of a selection that doesn't have handles
737 // then we want to show the handes on the entire selection.
738 VisibleSelectionInFlatTree newSelection =
739 selection().visibleSelection<EditingInFlatTreeStrategy>();
740 if (selection().contains(hitTestResult) && !newSelection.isHandleVisible()) {
741 newSelection.setIsHandleVisible(true);
742 selection().setNonDirectionalSelectionIfNeeded(newSelection,
743 selection().granularity());
744 return true;
745 }
746
723 selectClosestWordFromHitTestResult(hitTestResult, 747 selectClosestWordFromHitTestResult(hitTestResult,
724 AppendTrailingWhitespace::DontAppend, 748 AppendTrailingWhitespace::DontAppend,
725 SelectInputEventType::Touch); 749 SelectInputEventType::Touch);
726 if (!selection().isAvailable()) { 750 if (!selection().isAvailable()) {
727 // "editing/selection/longpress-selection-in-iframe-removed-crash.html" 751 // "editing/selection/longpress-selection-in-iframe-removed-crash.html"
728 // reach here. 752 // reach here.
729 return false; 753 return false;
730 } 754 }
731 return selection().isRange(); 755 return selection().isRange();
732 } 756 }
(...skipping 13 matching lines...) Expand all
746 pos.deepEquivalent().parentAnchoredEquivalent()), 770 pos.deepEquivalent().parentAnchoredEquivalent()),
747 DocumentMarker::MisspellingMarkers()) 771 DocumentMarker::MisspellingMarkers())
748 .size() > 0; 772 .size() > 0;
749 } 773 }
750 774
751 void SelectionController::sendContextMenuEvent( 775 void SelectionController::sendContextMenuEvent(
752 const MouseEventWithHitTestResults& mev, 776 const MouseEventWithHitTestResults& mev,
753 const LayoutPoint& position) { 777 const LayoutPoint& position) {
754 if (!selection().isAvailable()) 778 if (!selection().isAvailable())
755 return; 779 return;
756 if (selection().contains(position) || mev.scrollbar() || 780 if (selection().contains(mev.hitTestResult()) || mev.scrollbar() ||
757 // FIXME: In the editable case, word selection sometimes selects content 781 // FIXME: In the editable case, word selection sometimes selects content
758 // that isn't underneath the mouse. 782 // that isn't underneath the mouse.
759 // If the selection is non-editable, we do word selection to make it 783 // If the selection is non-editable, we do word selection to make it
760 // easier to use the contextual menu items available for text selections. 784 // easier to use the contextual menu items available for text selections.
761 // But only if we're above text. 785 // But only if we're above text.
762 !(selection().isContentEditable() || 786 !(selection().isContentEditable() ||
763 (mev.innerNode() && mev.innerNode()->isTextNode()))) 787 (mev.innerNode() && mev.innerNode()->isTextNode())))
764 return; 788 return;
765 789
766 // Context menu events are always allowed to perform a selection. 790 // Context menu events are always allowed to perform a selection.
767 AutoReset<bool> mouseDownMayStartSelectChange(&m_mouseDownMayStartSelect, 791 AutoReset<bool> mouseDownMayStartSelectChange(&m_mouseDownMayStartSelect,
768 true); 792 true);
769 793
770 if (hitTestResultIsMisspelled(mev.hitTestResult())) 794 if (hitTestResultIsMisspelled(mev.hitTestResult()))
771 return selectClosestMisspellingFromMouseEvent(mev); 795 return selectClosestMisspellingFromMouseEvent(mev);
772 796
773 if (!m_frame->editor().behavior().shouldSelectOnContextualMenuClick()) 797 if (!m_frame->editor().behavior().shouldSelectOnContextualMenuClick())
774 return; 798 return;
775 799
776 selectClosestWordOrLinkFromMouseEvent(mev); 800 selectClosestWordOrLinkFromMouseEvent(mev);
777 } 801 }
778 802
779 void SelectionController::passMousePressEventToSubframe( 803 void SelectionController::passMousePressEventToSubframe(
780 const MouseEventWithHitTestResults& mev) { 804 const MouseEventWithHitTestResults& mev) {
781 // If we're clicking into a frame that is selected, the frame will appear 805 // If we're clicking into a frame that is selected, the frame will appear
782 // greyed out even though we're clicking on the selection. This looks 806 // greyed out even though we're clicking on the selection. This looks
783 // really strange (having the whole frame be greyed out), so we deselect the 807 // really strange (having the whole frame be greyed out), so we deselect the
784 // selection. 808 // selection.
785 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); 809 if (!selection().contains(mev.hitTestResult()))
786 if (!selection().contains(p))
787 return; 810 return;
788 811
789 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets 812 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
790 // needs to be audited. See http://crbug.com/590369 for more details. 813 // needs to be audited. See http://crbug.com/590369 for more details.
791 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); 814 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();
792 815
793 const VisiblePositionInFlatTree& visiblePos = 816 const VisiblePositionInFlatTree& visiblePos =
794 visiblePositionOfHitTestResult(mev.hitTestResult()); 817 visiblePositionOfHitTestResult(mev.hitTestResult());
795 VisibleSelectionInFlatTree newSelection = createVisibleSelection(visiblePos); 818 VisibleSelectionInFlatTree newSelection = createVisibleSelection(visiblePos);
796 selection().setSelection(newSelection); 819 selection().setSelection(newSelection);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
829 return event.event().altKey() && event.isOverLink(); 852 return event.event().altKey() && event.isOverLink();
830 } 853 }
831 854
832 bool isExtendingSelection(const MouseEventWithHitTestResults& event) { 855 bool isExtendingSelection(const MouseEventWithHitTestResults& event) {
833 bool isMouseDownOnLinkOrImage = 856 bool isMouseDownOnLinkOrImage =
834 event.isOverLink() || event.hitTestResult().image(); 857 event.isOverLink() || event.hitTestResult().image();
835 return event.event().shiftKey() && !isMouseDownOnLinkOrImage; 858 return event.event().shiftKey() && !isMouseDownOnLinkOrImage;
836 } 859 }
837 860
838 } // namespace blink 861 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698