Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Unified Diff: ui/touch_selection/touch_selection_controller.cc

Issue 1087893003: Support longpress drag selection (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleanup Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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(

Powered by Google App Engine
This is Rietveld 408576698