Chromium Code Reviews| Index: ui/touch_selection/touch_selection_controller.cc |
| diff --git a/ui/touch_selection/touch_selection_controller.cc b/ui/touch_selection/touch_selection_controller.cc |
| index 3d52b4c3e423f276b65541c1491b0e260411fb86..996ff9989158292d0c8ad6abc394e4d5d8d47ef3 100644 |
| --- a/ui/touch_selection/touch_selection_controller.cc |
| +++ b/ui/touch_selection/touch_selection_controller.cc |
| @@ -59,6 +59,10 @@ TouchSelectionController::TouchSelectionController( |
| selection_empty_(false), |
| selection_editable_(false), |
| temporarily_hidden_(false), |
| + temporarily_hidden_for_longpress_drag_(false), |
| + consume_remaining_motion_for_longpress_drag_(false), |
| + has_begun_longpress_drag_(false), |
| + has_active_touch_sequence_(false), |
| selection_handle_dragged_(false) { |
| DCHECK(client_); |
| } |
| @@ -126,6 +130,9 @@ void TouchSelectionController::OnSelectionBoundsChanged( |
| } |
| bool TouchSelectionController::WillHandleTouchEvent(const MotionEvent& event) { |
| + if (WillHandleTouchEventForLongPressDrag(event)) |
| + return true; |
| + |
| if (is_insertion_active_) { |
| DCHECK(insertion_handle_); |
| return insertion_handle_->WillHandleTouchEvent(event); |
| @@ -151,7 +158,15 @@ bool TouchSelectionController::WillHandleTouchEvent(const MotionEvent& event) { |
| return false; |
| } |
| -void TouchSelectionController::OnLongPressEvent() { |
| +void TouchSelectionController::OnLongPressEvent(const gfx::PointF& position) { |
| + // If the longpress occurs at the same location as start of the active |
| + // touch sequence, allow the resulting selection to be dragged by the |
| + // remainder of the active touch sequence. |
| + if (has_active_touch_sequence_ && |
| + ((touch_sequence_start_position_ - position).LengthSquared() < |
|
mfomitchev
2015/04/18 16:09:08
I must be missing something, but why do we need to
jdduke (slow)
2015/04/21 19:25:57
So, the issue right now is that touch events are f
mfomitchev
2015/04/21 21:08:57
If do #3, then the webpage will get all the touch
jdduke (slow)
2015/04/21 21:28:33
Indeed, we'd be at the mercy of the web page. This
mfomitchev
2015/04/21 22:20:29
Agreed.
So.. it seems like we could get a long pre
|
| + (tap_slop_ * tap_slop_))) { |
| + SetTemporarilyHiddenForLongPressDrag(true); |
| + } |
| response_pending_input_event_ = LONG_PRESS; |
| ShowSelectionHandlesAutomatically(); |
| ShowInsertionHandleAutomatically(); |
| @@ -191,14 +206,7 @@ void TouchSelectionController::SetTemporarilyHidden(bool hidden) { |
| if (temporarily_hidden_ == hidden) |
| return; |
| temporarily_hidden_ = hidden; |
| - |
| - TouchHandle::AnimationStyle animation_style = GetAnimationStyle(true); |
| - if (is_selection_active_) { |
| - start_selection_handle_->SetVisible(GetStartVisible(), animation_style); |
| - end_selection_handle_->SetVisible(GetEndVisible(), animation_style); |
| - } |
| - if (is_insertion_active_) |
| - insertion_handle_->SetVisible(GetStartVisible(), animation_style); |
| + OnHandleVisibilityOverrideChanged(); |
| } |
| void TouchSelectionController::OnSelectionEditable(bool editable) { |
| @@ -445,6 +453,12 @@ void TouchSelectionController::ActivateSelection() { |
| selection_start_time_ = base::TimeTicks::Now(); |
| response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; |
| client_->OnSelectionEvent(SELECTION_SHOWN); |
| + if (temporarily_hidden_for_longpress_drag_) { |
| + consume_remaining_motion_for_longpress_drag_ = true; |
| + longpress_drag_selection_offset_ = gfx::Vector2dF(); |
| + longpress_drag_initial_position_ = gfx::PointF(); |
| + has_begun_longpress_drag_ = false; |
| + } |
| } |
| } |
| @@ -456,7 +470,8 @@ void TouchSelectionController::DeactivateSelection() { |
| LogSelectionEnd(); |
| start_selection_handle_->SetEnabled(false); |
| end_selection_handle_->SetEnabled(false); |
| - is_selection_active_ = false; |
| + SetTemporarilyHiddenForLongPressDrag(false); |
| + consume_remaining_motion_for_longpress_drag_ = false; |
| client_->OnSelectionEvent(SELECTION_CLEARED); |
| } |
| @@ -469,6 +484,99 @@ void TouchSelectionController::ResetCachedValuesIfInactive() { |
| end_orientation_ = TouchHandleOrientation::UNDEFINED; |
| } |
| +bool TouchSelectionController::WillHandleTouchEventForLongPressDrag( |
| + const MotionEvent& event) { |
| + if (event.GetAction() == MotionEvent::ACTION_DOWN) { |
| + has_active_touch_sequence_ = true; |
| + touch_sequence_start_position_.SetPoint(event.GetX(), event.GetY()); |
| + SetTemporarilyHiddenForLongPressDrag(false); |
| + consume_remaining_motion_for_longpress_drag_ = false; |
| + } |
| + |
| + if (event.GetAction() == MotionEvent::ACTION_UP || |
| + event.GetAction() == MotionEvent::ACTION_CANCEL) { |
| + has_active_touch_sequence_ = false; |
| + touch_sequence_start_position_ = gfx::PointF(); |
| + SetTemporarilyHiddenForLongPressDrag(false); |
|
mfomitchev
2015/04/18 16:09:08
It would be nice to do UMA logging for this usecas
|
| + consume_remaining_motion_for_longpress_drag_ = false; |
|
mfomitchev
2015/04/21 22:20:29
When the user lifts the finger at the end of the l
jdduke (slow)
2015/04/21 22:29:34
Yep, at least, yes if we want to match the native
mfomitchev
2015/04/22 19:19:50
Ah, right. Ok, cool.
|
| + } |
| + |
| + if (!consume_remaining_motion_for_longpress_drag_) |
| + return false; |
| + |
| + if (event.GetAction() != MotionEvent::ACTION_MOVE) |
| + return false; |
| + |
| + gfx::PointF position(event.GetX(), event.GetY()); |
| + if (has_begun_longpress_drag_) { |
| + gfx::PointF drag_position = position + longpress_drag_selection_offset_; |
| + client_->MoveRangeSelectionExtent(drag_position); |
| + return true; |
| + } |
| + |
| + // We can't use |touch_sequence_start_position_| as the offset anchor, as |
| + // showing the selection UI may have shifted the motion coordinates. |
| + if (longpress_drag_initial_position_.IsOrigin()) { |
| + longpress_drag_initial_position_ = position; |
| + return true; |
| + } |
| + |
| + // Allow an additional slop affordance after the longpress occurs. |
| + gfx::Vector2dF delta = position - longpress_drag_initial_position_; |
| + if (delta.LengthSquared() < tap_slop_ * tap_slop_) |
| + return true; |
| + |
| + has_begun_longpress_drag_ = true; |
| + gfx::PointF start_position = |
| + start_selection_handle_->position() + GetStartLineOffset(); |
| + gfx::PointF end_position = |
| + end_selection_handle_->position() + GetEndLineOffset(); |
| + gfx::PointF base, extent; |
| + if (std::abs(delta.y()) > std::abs(delta.x())) { |
| + // If initial motion is vertical, anchor to the appropriate handle position. |
| + if (delta.y() < 0) { |
| + base = end_position; |
| + extent = start_position; |
| + } else { |
| + base = start_position; |
| + extent = end_position; |
| + } |
| + } else { |
| + // Otherwise anchor selection to the handle away from which we're moving. |
| + gfx::Vector2dF start_delta = start_position - position; |
| + gfx::Vector2dF end_delta = end_position - position; |
| + if (gfx::DotProduct(start_delta, delta) > |
| + gfx::DotProduct(end_delta, delta)) { |
| + base = end_position; |
| + extent = start_position; |
| + } else { |
| + base = start_position; |
| + extent = end_position; |
| + } |
| + } |
| + longpress_drag_selection_offset_ = extent - position; |
| + client_->SelectBetweenCoordinates(base, extent); |
| + return true; |
| +} |
| + |
| +void TouchSelectionController::SetTemporarilyHiddenForLongPressDrag( |
| + bool hidden) { |
| + if (hidden == temporarily_hidden_for_longpress_drag_) |
| + return; |
| + temporarily_hidden_for_longpress_drag_ = hidden; |
| + OnHandleVisibilityOverrideChanged(); |
| +} |
| + |
| +void TouchSelectionController::OnHandleVisibilityOverrideChanged() { |
| + TouchHandle::AnimationStyle animation_style = GetAnimationStyle(true); |
| + if (is_selection_active_) { |
| + start_selection_handle_->SetVisible(GetStartVisible(), animation_style); |
| + end_selection_handle_->SetVisible(GetEndVisible(), animation_style); |
| + } |
| + if (is_insertion_active_) |
| + insertion_handle_->SetVisible(GetStartVisible(), animation_style); |
| +} |
| + |
| gfx::Vector2dF TouchSelectionController::GetStartLineOffset() const { |
| return ComputeLineOffsetFromBottom(start_); |
| } |
| @@ -478,11 +586,17 @@ gfx::Vector2dF TouchSelectionController::GetEndLineOffset() const { |
| } |
| bool TouchSelectionController::GetStartVisible() const { |
| - return start_.visible() && !temporarily_hidden_; |
| + if (!start_.visible()) |
| + return false; |
| + |
| + return !temporarily_hidden_ && !temporarily_hidden_for_longpress_drag_; |
| } |
| bool TouchSelectionController::GetEndVisible() const { |
| - return end_.visible() && !temporarily_hidden_; |
| + if (!end_.visible()) |
| + return false; |
| + |
| + return !temporarily_hidden_ && !temporarily_hidden_for_longpress_drag_; |
| } |
| TouchHandle::AnimationStyle TouchSelectionController::GetAnimationStyle( |