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