OLD | NEW |
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 17 matching lines...) Expand all Loading... |
28 */ | 28 */ |
29 | 29 |
30 #include "core/editing/SelectionController.h" | 30 #include "core/editing/SelectionController.h" |
31 | 31 |
32 #include "core/HTMLNames.h" | 32 #include "core/HTMLNames.h" |
33 #include "core/dom/Document.h" | 33 #include "core/dom/Document.h" |
34 #include "core/editing/EditingUtilities.h" | 34 #include "core/editing/EditingUtilities.h" |
35 #include "core/editing/Editor.h" | 35 #include "core/editing/Editor.h" |
36 #include "core/editing/FrameSelection.h" | 36 #include "core/editing/FrameSelection.h" |
37 #include "core/editing/RenderedPosition.h" | 37 #include "core/editing/RenderedPosition.h" |
| 38 #include "core/editing/VisibleSelection.h" |
38 #include "core/editing/iterators/TextIterator.h" | 39 #include "core/editing/iterators/TextIterator.h" |
39 #include "core/editing/markers/DocumentMarkerController.h" | 40 #include "core/editing/markers/DocumentMarkerController.h" |
40 #include "core/events/Event.h" | 41 #include "core/events/Event.h" |
41 #include "core/frame/LocalFrame.h" | 42 #include "core/frame/LocalFrame.h" |
42 #include "core/frame/LocalFrameView.h" | 43 #include "core/frame/LocalFrameView.h" |
43 #include "core/frame/Settings.h" | 44 #include "core/frame/Settings.h" |
44 #include "core/input/EventHandler.h" | 45 #include "core/input/EventHandler.h" |
45 #include "core/layout/LayoutView.h" | 46 #include "core/layout/LayoutView.h" |
46 #include "core/layout/api/LayoutViewItem.h" | 47 #include "core/layout/api/LayoutViewItem.h" |
47 #include "core/page/FocusController.h" | 48 #include "core/page/FocusController.h" |
(...skipping 23 matching lines...) Expand all Loading... |
71 namespace { | 72 namespace { |
72 | 73 |
73 DispatchEventResult DispatchSelectStart(Node* node) { | 74 DispatchEventResult DispatchSelectStart(Node* node) { |
74 if (!node || !node->GetLayoutObject()) | 75 if (!node || !node->GetLayoutObject()) |
75 return DispatchEventResult::kNotCanceled; | 76 return DispatchEventResult::kNotCanceled; |
76 | 77 |
77 return node->DispatchEvent( | 78 return node->DispatchEvent( |
78 Event::CreateCancelableBubble(EventTypeNames::selectstart)); | 79 Event::CreateCancelableBubble(EventTypeNames::selectstart)); |
79 } | 80 } |
80 | 81 |
81 VisibleSelectionInFlatTree ExpandSelectionToRespectUserSelectAll( | 82 SelectionInFlatTree ExpandSelectionToRespectUserSelectAll( |
82 Node* target_node, | 83 Node* target_node, |
83 const VisibleSelectionInFlatTree& selection) { | 84 const VisibleSelectionInFlatTree& selection) { |
84 if (selection.IsNone()) | 85 if (selection.IsNone()) |
85 return selection; | 86 return SelectionInFlatTree(); |
86 Node* const root_user_select_all = | 87 Node* const root_user_select_all = |
87 EditingInFlatTreeStrategy::RootUserSelectAllForNode(target_node); | 88 EditingInFlatTreeStrategy::RootUserSelectAllForNode(target_node); |
88 if (!root_user_select_all) { | 89 if (!root_user_select_all) { |
89 SelectionInFlatTree::Builder builder; | 90 SelectionInFlatTree::Builder builder; |
90 if (selection.IsBaseFirst()) | 91 if (selection.IsBaseFirst()) |
91 builder.SetBaseAndExtent(selection.Start(), selection.End()); | 92 builder.SetBaseAndExtent(selection.Start(), selection.End()); |
92 else | 93 else |
93 builder.SetBaseAndExtent(selection.End(), selection.Start()); | 94 builder.SetBaseAndExtent(selection.End(), selection.Start()); |
94 builder.SetAffinity(selection.Affinity()); | 95 builder.SetAffinity(selection.Affinity()); |
95 return CreateVisibleSelection(builder.Build()); | 96 return builder.Build(); |
96 } | 97 } |
97 | 98 |
98 return CreateVisibleSelection( | 99 return SelectionInFlatTree::Builder(selection.AsSelection()) |
99 SelectionInFlatTree::Builder(selection.AsSelection()) | 100 .Collapse(MostBackwardCaretPosition( |
100 .Collapse(MostBackwardCaretPosition( | 101 PositionInFlatTree::BeforeNode(*root_user_select_all), |
101 PositionInFlatTree::BeforeNode(*root_user_select_all), | 102 kCanCrossEditingBoundary)) |
102 kCanCrossEditingBoundary)) | 103 .Extend(MostForwardCaretPosition( |
103 .Extend(MostForwardCaretPosition( | 104 PositionInFlatTree::AfterNode(*root_user_select_all), |
104 PositionInFlatTree::AfterNode(*root_user_select_all), | 105 kCanCrossEditingBoundary)) |
105 kCanCrossEditingBoundary)) | 106 .Build(); |
106 .Build()); | |
107 } | 107 } |
108 | 108 |
109 static int TextDistance(const PositionInFlatTree& start, | 109 static int TextDistance(const PositionInFlatTree& start, |
110 const PositionInFlatTree& end) { | 110 const PositionInFlatTree& end) { |
111 return TextIteratorInFlatTree::RangeLength( | 111 return TextIteratorInFlatTree::RangeLength( |
112 start, end, | 112 start, end, |
113 TextIteratorBehavior::AllVisiblePositionsRangeLengthBehavior()); | 113 TextIteratorBehavior::AllVisiblePositionsRangeLengthBehavior()); |
114 } | 114 } |
115 | 115 |
116 bool CanMouseDownStartSelect(Node* node) { | 116 bool CanMouseDownStartSelect(Node* node) { |
(...skipping 25 matching lines...) Expand all Loading... |
142 void SelectionController::ContextDestroyed(Document*) { | 142 void SelectionController::ContextDestroyed(Document*) { |
143 original_base_in_flat_tree_ = VisiblePositionInFlatTree(); | 143 original_base_in_flat_tree_ = VisiblePositionInFlatTree(); |
144 } | 144 } |
145 | 145 |
146 static PositionInFlatTree AdjustPositionRespectUserSelectAll( | 146 static PositionInFlatTree AdjustPositionRespectUserSelectAll( |
147 Node* inner_node, | 147 Node* inner_node, |
148 const PositionInFlatTree& selection_start, | 148 const PositionInFlatTree& selection_start, |
149 const PositionInFlatTree& selection_end, | 149 const PositionInFlatTree& selection_end, |
150 const PositionInFlatTree& position) { | 150 const PositionInFlatTree& position) { |
151 const VisibleSelectionInFlatTree& selection_in_user_select_all = | 151 const VisibleSelectionInFlatTree& selection_in_user_select_all = |
152 ExpandSelectionToRespectUserSelectAll( | 152 CreateVisibleSelection(ExpandSelectionToRespectUserSelectAll( |
153 inner_node, | 153 inner_node, position.IsNull() ? VisibleSelectionInFlatTree() |
154 position.IsNull() | 154 : CreateVisibleSelection( |
155 ? VisibleSelectionInFlatTree() | 155 SelectionInFlatTree::Builder() |
156 : CreateVisibleSelection( | 156 .Collapse(position) |
157 SelectionInFlatTree::Builder().Collapse(position).Build())); | 157 .Build()))); |
158 if (!selection_in_user_select_all.IsRange()) | 158 if (!selection_in_user_select_all.IsRange()) |
159 return position; | 159 return position; |
160 if (selection_in_user_select_all.Start().CompareTo(selection_start) < 0) | 160 if (selection_in_user_select_all.Start().CompareTo(selection_start) < 0) |
161 return selection_in_user_select_all.Start(); | 161 return selection_in_user_select_all.Start(); |
162 if (selection_end.CompareTo(selection_in_user_select_all.End()) < 0) | 162 if (selection_end.CompareTo(selection_in_user_select_all.End()) < 0) |
163 return selection_in_user_select_all.End(); | 163 return selection_in_user_select_all.End(); |
164 return position; | 164 return position; |
165 } | 165 } |
166 | 166 |
167 // Updating the selection is considered side-effect of the event and so it | 167 // Updating the selection is considered side-effect of the event and so it |
(...skipping 29 matching lines...) Expand all Loading... |
197 const LayoutPoint v_point = view->RootFrameToContents( | 197 const LayoutPoint v_point = view->RootFrameToContents( |
198 FlooredIntPoint(event.Event().PositionInRootFrame())); | 198 FlooredIntPoint(event.Event().PositionInRootFrame())); |
199 if (!extend_selection && this->Selection().Contains(v_point)) { | 199 if (!extend_selection && this->Selection().Contains(v_point)) { |
200 mouse_down_was_single_click_in_selection_ = true; | 200 mouse_down_was_single_click_in_selection_ = true; |
201 if (!event.Event().FromTouch()) | 201 if (!event.Event().FromTouch()) |
202 return false; | 202 return false; |
203 | 203 |
204 if (!this->Selection().IsHandleVisible()) { | 204 if (!this->Selection().IsHandleVisible()) { |
205 const bool did_select = | 205 const bool did_select = |
206 UpdateSelectionForMouseDownDispatchingSelectStart( | 206 UpdateSelectionForMouseDownDispatchingSelectStart( |
207 inner_node, selection, kCharacterGranularity, | 207 inner_node, selection.AsSelection(), kCharacterGranularity, |
208 HandleVisibility::kVisible); | 208 HandleVisibility::kVisible); |
209 if (did_select) { | 209 if (did_select) { |
210 frame_->GetEventHandler().ShowNonLocatedContextMenu(nullptr, | 210 frame_->GetEventHandler().ShowNonLocatedContextMenu(nullptr, |
211 kMenuSourceTouch); | 211 kMenuSourceTouch); |
212 } | 212 } |
213 return false; | 213 return false; |
214 } | 214 } |
215 } | 215 } |
216 } | 216 } |
217 | 217 |
(...skipping 21 matching lines...) Expand all Loading... |
239 builder.SetBaseAndExtent(start, pos); | 239 builder.SetBaseAndExtent(start, pos); |
240 } else { | 240 } else { |
241 const int distance_to_start = TextDistance(start, pos); | 241 const int distance_to_start = TextDistance(start, pos); |
242 const int distance_to_end = TextDistance(pos, end); | 242 const int distance_to_end = TextDistance(pos, end); |
243 builder.SetBaseAndExtent( | 243 builder.SetBaseAndExtent( |
244 distance_to_start <= distance_to_end ? end : start, pos); | 244 distance_to_start <= distance_to_end ? end : start, pos); |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 UpdateSelectionForMouseDownDispatchingSelectStart( | 248 UpdateSelectionForMouseDownDispatchingSelectStart( |
249 inner_node, CreateVisibleSelection(builder.Build()), | 249 inner_node, builder.Build(), this->Selection().Granularity(), |
250 this->Selection().Granularity(), HandleVisibility::kNotVisible); | 250 HandleVisibility::kNotVisible); |
251 return false; | 251 return false; |
252 } | 252 } |
253 | 253 |
254 if (selection_state_ == SelectionState::kExtendedSelection) { | 254 if (selection_state_ == SelectionState::kExtendedSelection) { |
255 UpdateSelectionForMouseDownDispatchingSelectStart( | 255 UpdateSelectionForMouseDownDispatchingSelectStart( |
256 inner_node, selection, kCharacterGranularity, | 256 inner_node, selection.AsSelection(), kCharacterGranularity, |
257 HandleVisibility::kNotVisible); | 257 HandleVisibility::kNotVisible); |
258 return false; | 258 return false; |
259 } | 259 } |
260 | 260 |
261 if (visible_pos.IsNull()) { | 261 if (visible_pos.IsNull()) { |
262 UpdateSelectionForMouseDownDispatchingSelectStart( | 262 UpdateSelectionForMouseDownDispatchingSelectStart( |
263 inner_node, VisibleSelectionInFlatTree(), kCharacterGranularity, | 263 inner_node, SelectionInFlatTree(), kCharacterGranularity, |
264 HandleVisibility::kNotVisible); | 264 HandleVisibility::kNotVisible); |
265 return false; | 265 return false; |
266 } | 266 } |
267 | 267 |
268 bool is_handle_visible = false; | 268 bool is_handle_visible = false; |
269 if (HasEditableStyle(*inner_node)) { | 269 if (HasEditableStyle(*inner_node)) { |
270 const bool is_text_box_empty = | 270 const bool is_text_box_empty = |
271 CreateVisibleSelection(SelectionInFlatTree::Builder() | 271 CreateVisibleSelection(SelectionInFlatTree::Builder() |
272 .SelectAllChildren(*inner_node) | 272 .SelectAllChildren(*inner_node) |
273 .Build()) | 273 .Build()) |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 if (Selection().Granularity() != kCharacterGranularity) | 433 if (Selection().Granularity() != kCharacterGranularity) |
434 builder.SetGranularity(Selection().Granularity()); | 434 builder.SetGranularity(Selection().Granularity()); |
435 | 435 |
436 SetNonDirectionalSelectionIfNeeded(builder.Build(), Selection().Granularity(), | 436 SetNonDirectionalSelectionIfNeeded(builder.Build(), Selection().Granularity(), |
437 kAdjustEndpointsAtBidiBoundary, | 437 kAdjustEndpointsAtBidiBoundary, |
438 HandleVisibility::kNotVisible); | 438 HandleVisibility::kNotVisible); |
439 } | 439 } |
440 | 440 |
441 bool SelectionController::UpdateSelectionForMouseDownDispatchingSelectStart( | 441 bool SelectionController::UpdateSelectionForMouseDownDispatchingSelectStart( |
442 Node* target_node, | 442 Node* target_node, |
443 const VisibleSelectionInFlatTree& selection, | 443 const SelectionInFlatTree& selection, |
444 TextGranularity granularity, | 444 TextGranularity granularity, |
445 HandleVisibility handle_visibility) { | 445 HandleVisibility handle_visibility) { |
446 if (target_node && target_node->GetLayoutObject() && | 446 if (target_node && target_node->GetLayoutObject() && |
447 !target_node->GetLayoutObject()->IsSelectable()) | 447 !target_node->GetLayoutObject()->IsSelectable()) |
448 return false; | 448 return false; |
449 | 449 |
| 450 // TODO(editing-dev): We should compute visible selection after dispatching |
| 451 // "selectstart", once we have |SelectionInFlatTree::IsValidFor()|. |
| 452 const VisibleSelectionInFlatTree& visible_selection = |
| 453 CreateVisibleSelection(selection); |
| 454 |
450 if (DispatchSelectStart(target_node) != DispatchEventResult::kNotCanceled) | 455 if (DispatchSelectStart(target_node) != DispatchEventResult::kNotCanceled) |
451 return false; | 456 return false; |
452 | 457 |
453 // |dispatchSelectStart()| can change document hosted by |m_frame|. | 458 // |dispatchSelectStart()| can change document hosted by |m_frame|. |
454 if (!this->Selection().IsAvailable()) | 459 if (!this->Selection().IsAvailable()) |
455 return false; | 460 return false; |
456 | 461 |
457 if (!selection.IsValidFor(this->Selection().GetDocument())) | 462 if (!visible_selection.IsValidFor(this->Selection().GetDocument())) |
458 return false; | 463 return false; |
459 | 464 |
460 if (selection.IsRange()) { | 465 if (visible_selection.IsRange()) { |
461 selection_state_ = SelectionState::kExtendedSelection; | 466 selection_state_ = SelectionState::kExtendedSelection; |
462 } else { | 467 } else { |
463 granularity = kCharacterGranularity; | 468 granularity = kCharacterGranularity; |
464 selection_state_ = SelectionState::kPlacedCaret; | 469 selection_state_ = SelectionState::kPlacedCaret; |
465 } | 470 } |
466 | 471 |
467 SetNonDirectionalSelectionIfNeeded(selection.AsSelection(), granularity, | 472 SetNonDirectionalSelectionIfNeeded(selection, granularity, |
468 kDoNotAdjustEndpoints, handle_visibility); | 473 kDoNotAdjustEndpoints, handle_visibility); |
469 | 474 |
470 return true; | 475 return true; |
471 } | 476 } |
472 | 477 |
473 bool SelectionController::SelectClosestWordFromHitTestResult( | 478 bool SelectionController::SelectClosestWordFromHitTestResult( |
474 const HitTestResult& result, | 479 const HitTestResult& result, |
475 AppendTrailingWhitespace append_trailing_whitespace, | 480 AppendTrailingWhitespace append_trailing_whitespace, |
476 SelectInputEventType select_input_event_type) { | 481 SelectInputEventType select_input_event_type) { |
477 Node* inner_node = result.InnerNode(); | 482 Node* inner_node = result.InnerNode(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 const HitTestResult& result, | 541 const HitTestResult& result, |
537 AppendTrailingWhitespace append_trailing_whitespace) { | 542 AppendTrailingWhitespace append_trailing_whitespace) { |
538 Node* inner_node = result.InnerNode(); | 543 Node* inner_node = result.InnerNode(); |
539 | 544 |
540 if (!inner_node || !inner_node->GetLayoutObject()) | 545 if (!inner_node || !inner_node->GetLayoutObject()) |
541 return; | 546 return; |
542 | 547 |
543 const VisiblePositionInFlatTree& pos = VisiblePositionOfHitTestResult(result); | 548 const VisiblePositionInFlatTree& pos = VisiblePositionOfHitTestResult(result); |
544 if (pos.IsNull()) { | 549 if (pos.IsNull()) { |
545 UpdateSelectionForMouseDownDispatchingSelectStart( | 550 UpdateSelectionForMouseDownDispatchingSelectStart( |
546 inner_node, VisibleSelectionInFlatTree(), kWordGranularity, | 551 inner_node, SelectionInFlatTree(), kWordGranularity, |
547 HandleVisibility::kNotVisible); | 552 HandleVisibility::kNotVisible); |
548 return; | 553 return; |
549 } | 554 } |
550 | 555 |
551 const PositionInFlatTree& marker_position = | 556 const PositionInFlatTree& marker_position = |
552 pos.DeepEquivalent().ParentAnchoredEquivalent(); | 557 pos.DeepEquivalent().ParentAnchoredEquivalent(); |
553 const DocumentMarker* const marker = | 558 const DocumentMarker* const marker = |
554 inner_node->GetDocument().Markers().MarkerAtPosition( | 559 inner_node->GetDocument().Markers().MarkerAtPosition( |
555 ToPositionInDOMTree(marker_position), | 560 ToPositionInDOMTree(marker_position), |
556 DocumentMarker::MisspellingMarkers()); | 561 DocumentMarker::MisspellingMarkers()); |
557 if (!marker) { | 562 if (!marker) { |
558 UpdateSelectionForMouseDownDispatchingSelectStart( | 563 UpdateSelectionForMouseDownDispatchingSelectStart( |
559 inner_node, VisibleSelectionInFlatTree(), kWordGranularity, | 564 inner_node, SelectionInFlatTree(), kWordGranularity, |
560 HandleVisibility::kNotVisible); | 565 HandleVisibility::kNotVisible); |
561 return; | 566 return; |
562 } | 567 } |
563 | 568 |
564 Node* container_node = marker_position.ComputeContainerNode(); | 569 Node* container_node = marker_position.ComputeContainerNode(); |
565 const PositionInFlatTree start(container_node, marker->StartOffset()); | 570 const PositionInFlatTree start(container_node, marker->StartOffset()); |
566 const PositionInFlatTree end(container_node, marker->EndOffset()); | 571 const PositionInFlatTree end(container_node, marker->EndOffset()); |
567 VisibleSelectionInFlatTree new_selection = CreateVisibleSelection( | 572 VisibleSelectionInFlatTree new_selection = CreateVisibleSelection( |
568 SelectionInFlatTree::Builder().Collapse(start).Extend(end).Build()); | 573 SelectionInFlatTree::Builder().Collapse(start).Extend(end).Build()); |
569 | 574 |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
780 const VisiblePositionInFlatTree& visible_hit_pos = | 785 const VisiblePositionInFlatTree& visible_hit_pos = |
781 VisiblePositionOfHitTestResult(hit_test_result); | 786 VisiblePositionOfHitTestResult(hit_test_result); |
782 const VisiblePositionInFlatTree& visible_pos = | 787 const VisiblePositionInFlatTree& visible_pos = |
783 visible_hit_pos.IsNull() | 788 visible_hit_pos.IsNull() |
784 ? CreateVisiblePosition( | 789 ? CreateVisiblePosition( |
785 PositionInFlatTree::FirstPositionInOrBeforeNode(inner_node)) | 790 PositionInFlatTree::FirstPositionInOrBeforeNode(inner_node)) |
786 : visible_hit_pos; | 791 : visible_hit_pos; |
787 | 792 |
788 if (visible_pos.IsNull()) { | 793 if (visible_pos.IsNull()) { |
789 UpdateSelectionForMouseDownDispatchingSelectStart( | 794 UpdateSelectionForMouseDownDispatchingSelectStart( |
790 inner_node, VisibleSelectionInFlatTree(), kCharacterGranularity, | 795 inner_node, SelectionInFlatTree(), kCharacterGranularity, |
791 HandleVisibility::kVisible); | 796 HandleVisibility::kVisible); |
792 return; | 797 return; |
793 } | 798 } |
794 UpdateSelectionForMouseDownDispatchingSelectStart( | 799 UpdateSelectionForMouseDownDispatchingSelectStart( |
795 inner_node, | 800 inner_node, |
796 ExpandSelectionToRespectUserSelectAll( | 801 ExpandSelectionToRespectUserSelectAll( |
797 inner_node, CreateVisibleSelection( | 802 inner_node, CreateVisibleSelection( |
798 SelectionInFlatTree::Builder() | 803 SelectionInFlatTree::Builder() |
799 .Collapse(visible_pos.ToPositionWithAffinity()) | 804 .Collapse(visible_pos.ToPositionWithAffinity()) |
800 .Build())), | 805 .Build())), |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1206 | 1211 |
1207 bool IsExtendingSelection(const MouseEventWithHitTestResults& event) { | 1212 bool IsExtendingSelection(const MouseEventWithHitTestResults& event) { |
1208 bool is_mouse_down_on_link_or_image = | 1213 bool is_mouse_down_on_link_or_image = |
1209 event.IsOverLink() || event.GetHitTestResult().GetImage(); | 1214 event.IsOverLink() || event.GetHitTestResult().GetImage(); |
1210 return (event.Event().GetModifiers() & WebInputEvent::Modifiers::kShiftKey) != | 1215 return (event.Event().GetModifiers() & WebInputEvent::Modifiers::kShiftKey) != |
1211 0 && | 1216 0 && |
1212 !is_mouse_down_on_link_or_image; | 1217 !is_mouse_down_on_link_or_image; |
1213 } | 1218 } |
1214 | 1219 |
1215 } // namespace blink | 1220 } // namespace blink |
OLD | NEW |