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