| 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 |