OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/touch_selection/touch_selection_controller.h" | 5 #include "ui/touch_selection/touch_selection_controller.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
10 | 10 |
11 namespace ui { | 11 namespace ui { |
12 namespace { | 12 namespace { |
13 | 13 |
14 gfx::Vector2dF ComputeLineOffsetFromBottom(const SelectionBound& bound) { | 14 gfx::Vector2dF ComputeLineOffsetFromBottom(const SelectionBound& bound) { |
15 gfx::Vector2dF line_offset = | 15 gfx::Vector2dF line_offset = |
16 gfx::ScaleVector2d(bound.edge_top() - bound.edge_bottom(), 0.5f); | 16 gfx::ScaleVector2d(bound.edge_top() - bound.edge_bottom(), 0.5f); |
17 // An offset of 5 DIPs is sufficient for most line sizes. For small lines, | 17 // An offset of 5 DIPs is sufficient for most line sizes. For small lines, |
18 // using half the line height avoids synthesizing a point on a line above | 18 // using half the line height avoids synthesizing a point on a line above |
19 // (or below) the intended line. | 19 // (or below) the intended line. |
20 const gfx::Vector2dF kMaxLineOffset(5.f, 5.f); | 20 const gfx::Vector2dF kMaxLineOffset(5.f, 5.f); |
21 line_offset.SetToMin(kMaxLineOffset); | 21 line_offset.SetToMin(kMaxLineOffset); |
22 line_offset.SetToMax(-kMaxLineOffset); | 22 line_offset.SetToMax(-kMaxLineOffset); |
23 return line_offset; | 23 return line_offset; |
24 } | 24 } |
25 | 25 |
26 TouchHandleOrientation ToTouchHandleOrientation(SelectionBound::Type type) { | 26 TouchHandleOrientation ToTouchHandleOrientation(SelectionBound::Type type) { |
27 switch (type) { | 27 switch (type) { |
28 case SelectionBound::LEFT: | 28 case SelectionBound::LEFT: |
29 return TOUCH_HANDLE_LEFT; | 29 return TouchHandleOrientation::LEFT; |
30 case SelectionBound::RIGHT: | 30 case SelectionBound::RIGHT: |
31 return TOUCH_HANDLE_RIGHT; | 31 return TouchHandleOrientation::RIGHT; |
32 case SelectionBound::CENTER: | 32 case SelectionBound::CENTER: |
33 return TOUCH_HANDLE_CENTER; | 33 return TouchHandleOrientation::CENTER; |
34 case SelectionBound::EMPTY: | 34 case SelectionBound::EMPTY: |
35 return TOUCH_HANDLE_ORIENTATION_UNDEFINED; | 35 return TouchHandleOrientation::UNDEFINED; |
36 } | 36 } |
37 NOTREACHED() << "Invalid selection bound type: " << type; | 37 NOTREACHED() << "Invalid selection bound type: " << type; |
38 return TOUCH_HANDLE_ORIENTATION_UNDEFINED; | 38 return TouchHandleOrientation::UNDEFINED; |
39 } | 39 } |
40 | 40 |
41 } // namespace | 41 } // namespace |
42 | 42 |
43 TouchSelectionController::TouchSelectionController( | 43 TouchSelectionController::TouchSelectionController( |
44 TouchSelectionControllerClient* client, | 44 TouchSelectionControllerClient* client, |
45 base::TimeDelta tap_timeout, | 45 base::TimeDelta tap_timeout, |
46 float tap_slop, | 46 float tap_slop, |
47 bool show_on_tap_for_empty_editable) | 47 bool show_on_tap_for_empty_editable) |
48 : client_(client), | 48 : client_(client), |
49 tap_timeout_(tap_timeout), | 49 tap_timeout_(tap_timeout), |
50 tap_slop_(tap_slop), | 50 tap_slop_(tap_slop), |
51 show_on_tap_for_empty_editable_(show_on_tap_for_empty_editable), | 51 show_on_tap_for_empty_editable_(show_on_tap_for_empty_editable), |
52 response_pending_input_event_(INPUT_EVENT_TYPE_NONE), | 52 response_pending_input_event_(INPUT_EVENT_TYPE_NONE), |
53 start_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), | 53 start_orientation_(TouchHandleOrientation::UNDEFINED), |
54 end_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), | 54 end_orientation_(TouchHandleOrientation::UNDEFINED), |
55 is_insertion_active_(false), | 55 is_insertion_active_(false), |
56 activate_insertion_automatically_(false), | 56 activate_insertion_automatically_(false), |
57 is_selection_active_(false), | 57 is_selection_active_(false), |
58 activate_selection_automatically_(false), | 58 activate_selection_automatically_(false), |
59 selection_empty_(false), | 59 selection_empty_(false), |
60 selection_editable_(false), | 60 selection_editable_(false), |
61 temporarily_hidden_(false), | 61 temporarily_hidden_(false), |
62 selection_handle_dragged_(false) { | 62 selection_handle_dragged_(false) { |
63 DCHECK(client_); | 63 DCHECK(client_); |
64 HideAndDisallowShowingAutomatically(); | 64 HideAndDisallowShowingAutomatically(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 is_selection_active_ && (start_selection_handle_->is_dragging() || | 96 is_selection_active_ && (start_selection_handle_->is_dragging() || |
97 end_selection_handle_->is_dragging()); | 97 end_selection_handle_->is_dragging()); |
98 | 98 |
99 // It's possible that the bounds temporarily overlap while a selection handle | 99 // It's possible that the bounds temporarily overlap while a selection handle |
100 // is being dragged, incorrectly reporting a CENTER orientation. | 100 // is being dragged, incorrectly reporting a CENTER orientation. |
101 // TODO(jdduke): This safeguard is racy, as it's possible the delayed response | 101 // TODO(jdduke): This safeguard is racy, as it's possible the delayed response |
102 // from handle positioning occurs *after* the handle dragging has ceased. | 102 // from handle positioning occurs *after* the handle dragging has ceased. |
103 // Instead, prevent selection -> insertion transitions without an intervening | 103 // Instead, prevent selection -> insertion transitions without an intervening |
104 // action or selection clearing of some sort, crbug.com/392696. | 104 // action or selection clearing of some sort, crbug.com/392696. |
105 if (is_selection_dragging) { | 105 if (is_selection_dragging) { |
106 if (start_orientation_ == TOUCH_HANDLE_CENTER) | 106 if (start_orientation_ == TouchHandleOrientation::CENTER) |
107 start_orientation_ = start_selection_handle_->orientation(); | 107 start_orientation_ = start_selection_handle_->orientation(); |
108 if (end_orientation_ == TOUCH_HANDLE_CENTER) | 108 if (end_orientation_ == TouchHandleOrientation::CENTER) |
109 end_orientation_ = end_selection_handle_->orientation(); | 109 end_orientation_ = end_selection_handle_->orientation(); |
110 } | 110 } |
111 | 111 |
112 if (GetStartPosition() != GetEndPosition() || | 112 if (GetStartPosition() != GetEndPosition() || |
113 (is_selection_dragging && | 113 (is_selection_dragging && |
114 start_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED && | 114 start_orientation_ != TouchHandleOrientation::UNDEFINED && |
115 end_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED)) { | 115 end_orientation_ != TouchHandleOrientation::UNDEFINED)) { |
116 OnSelectionChanged(); | 116 OnSelectionChanged(); |
117 return; | 117 return; |
118 } | 118 } |
119 | 119 |
120 if (start_orientation_ == TOUCH_HANDLE_CENTER && selection_editable_) { | 120 if (start_orientation_ == TouchHandleOrientation::CENTER && |
| 121 selection_editable_) { |
121 OnInsertionChanged(); | 122 OnInsertionChanged(); |
122 return; | 123 return; |
123 } | 124 } |
124 | 125 |
125 HideAndDisallowShowingAutomatically(); | 126 HideAndDisallowShowingAutomatically(); |
126 } | 127 } |
127 | 128 |
128 bool TouchSelectionController::WillHandleTouchEvent(const MotionEvent& event) { | 129 bool TouchSelectionController::WillHandleTouchEvent(const MotionEvent& event) { |
129 if (is_insertion_active_) { | 130 if (is_insertion_active_) { |
130 DCHECK(insertion_handle_); | 131 DCHECK(insertion_handle_); |
(...skipping 28 matching lines...) Expand all Loading... |
159 } | 160 } |
160 | 161 |
161 void TouchSelectionController::AllowShowingFromCurrentSelection() { | 162 void TouchSelectionController::AllowShowingFromCurrentSelection() { |
162 if (is_selection_active_ || is_insertion_active_) | 163 if (is_selection_active_ || is_insertion_active_) |
163 return; | 164 return; |
164 | 165 |
165 activate_selection_automatically_ = true; | 166 activate_selection_automatically_ = true; |
166 activate_insertion_automatically_ = true; | 167 activate_insertion_automatically_ = true; |
167 if (GetStartPosition() != GetEndPosition()) | 168 if (GetStartPosition() != GetEndPosition()) |
168 OnSelectionChanged(); | 169 OnSelectionChanged(); |
169 else if (start_orientation_ == TOUCH_HANDLE_CENTER && selection_editable_) | 170 else if (start_orientation_ == TouchHandleOrientation::CENTER && |
| 171 selection_editable_) |
170 OnInsertionChanged(); | 172 OnInsertionChanged(); |
171 } | 173 } |
172 | 174 |
173 void TouchSelectionController::OnTapEvent() { | 175 void TouchSelectionController::OnTapEvent() { |
174 response_pending_input_event_ = TAP; | 176 response_pending_input_event_ = TAP; |
175 ShowInsertionHandleAutomatically(); | 177 ShowInsertionHandleAutomatically(); |
176 if (selection_empty_) | 178 if (selection_empty_) |
177 DeactivateInsertion(); | 179 DeactivateInsertion(); |
178 ResetCachedValuesIfInactive(); | 180 ResetCachedValuesIfInactive(); |
179 } | 181 } |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 end_selection_handle_->SetVisible(GetEndVisible(), animation); | 347 end_selection_handle_->SetVisible(GetEndVisible(), animation); |
346 | 348 |
347 start_selection_handle_->SetPosition(GetStartPosition()); | 349 start_selection_handle_->SetPosition(GetStartPosition()); |
348 end_selection_handle_->SetPosition(GetEndPosition()); | 350 end_selection_handle_->SetPosition(GetEndPosition()); |
349 } | 351 } |
350 | 352 |
351 void TouchSelectionController::ActivateInsertion() { | 353 void TouchSelectionController::ActivateInsertion() { |
352 DCHECK(!is_selection_active_); | 354 DCHECK(!is_selection_active_); |
353 | 355 |
354 if (!insertion_handle_) | 356 if (!insertion_handle_) |
355 insertion_handle_.reset(new TouchHandle(this, TOUCH_HANDLE_CENTER)); | 357 insertion_handle_.reset( |
| 358 new TouchHandle(this, TouchHandleOrientation::CENTER)); |
356 | 359 |
357 if (!is_insertion_active_) { | 360 if (!is_insertion_active_) { |
358 is_insertion_active_ = true; | 361 is_insertion_active_ = true; |
359 insertion_handle_->SetEnabled(true); | 362 insertion_handle_->SetEnabled(true); |
360 client_->OnSelectionEvent(INSERTION_SHOWN, GetStartPosition()); | 363 client_->OnSelectionEvent(INSERTION_SHOWN, GetStartPosition()); |
361 } | 364 } |
362 } | 365 } |
363 | 366 |
364 void TouchSelectionController::DeactivateInsertion() { | 367 void TouchSelectionController::DeactivateInsertion() { |
365 if (!is_insertion_active_) | 368 if (!is_insertion_active_) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 end_selection_handle_->SetEnabled(false); | 416 end_selection_handle_->SetEnabled(false); |
414 is_selection_active_ = false; | 417 is_selection_active_ = false; |
415 client_->OnSelectionEvent(SELECTION_CLEARED, gfx::PointF()); | 418 client_->OnSelectionEvent(SELECTION_CLEARED, gfx::PointF()); |
416 } | 419 } |
417 | 420 |
418 void TouchSelectionController::ResetCachedValuesIfInactive() { | 421 void TouchSelectionController::ResetCachedValuesIfInactive() { |
419 if (is_selection_active_ || is_insertion_active_) | 422 if (is_selection_active_ || is_insertion_active_) |
420 return; | 423 return; |
421 start_ = SelectionBound(); | 424 start_ = SelectionBound(); |
422 end_ = SelectionBound(); | 425 end_ = SelectionBound(); |
423 start_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED; | 426 start_orientation_ = TouchHandleOrientation::UNDEFINED; |
424 end_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED; | 427 end_orientation_ = TouchHandleOrientation::UNDEFINED; |
425 } | 428 } |
426 | 429 |
427 const gfx::PointF& TouchSelectionController::GetStartPosition() const { | 430 const gfx::PointF& TouchSelectionController::GetStartPosition() const { |
428 return start_.edge_bottom(); | 431 return start_.edge_bottom(); |
429 } | 432 } |
430 | 433 |
431 const gfx::PointF& TouchSelectionController::GetEndPosition() const { | 434 const gfx::PointF& TouchSelectionController::GetEndPosition() const { |
432 return end_.edge_bottom(); | 435 return end_.edge_bottom(); |
433 } | 436 } |
434 | 437 |
(...skipping 29 matching lines...) Expand all Loading... |
464 base::TimeDelta duration = base::TimeTicks::Now() - selection_start_time_; | 467 base::TimeDelta duration = base::TimeTicks::Now() - selection_start_time_; |
465 UMA_HISTOGRAM_CUSTOM_TIMES("Event.TouchSelection.WasDraggedDuration", | 468 UMA_HISTOGRAM_CUSTOM_TIMES("Event.TouchSelection.WasDraggedDuration", |
466 duration, | 469 duration, |
467 base::TimeDelta::FromMilliseconds(500), | 470 base::TimeDelta::FromMilliseconds(500), |
468 base::TimeDelta::FromSeconds(60), | 471 base::TimeDelta::FromSeconds(60), |
469 60); | 472 60); |
470 } | 473 } |
471 } | 474 } |
472 | 475 |
473 } // namespace ui | 476 } // namespace ui |
OLD | NEW |