Skip to content
This repository has been archived by the owner on Apr 3, 2020. It is now read-only.

Commit

Permalink
Fix issue with longpress drag selection motion
Browse files Browse the repository at this point in the history
If the user has already dragged outside the initial selected word region
by the time the browser gets a selection update, or if the selected word
isn't coincident with the longpress location, the subsequently dragged
selection endpoint can be wrong. For such cases, rather than
using the drag direction for drag anchor picking, just use the distance
between the current touch point and the selection endpoints.

BUG=466749

Review URL: https://codereview.chromium.org/1271823002

Cr-Commit-Position: refs/heads/master@{#341791}
(cherry picked from commit a188bd6)

Review URL: https://codereview.chromium.org/1259593010 .

Cr-Commit-Position: refs/branch-heads/2454@{#228}
Cr-Branched-From: 12bfc33-refs/heads/master@{#338390}
  • Loading branch information
Jared Duke committed Aug 4, 2015
1 parent 30b1422 commit 5e1e7b4
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 12 deletions.
35 changes: 24 additions & 11 deletions ui/touch_selection/longpress_drag_selector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
#include "ui/events/gesture_detection/motion_event.h"

namespace ui {
namespace {

gfx::Vector2dF SafeNormalize(const gfx::Vector2dF& v) {
return v.IsZero() ? v : ScaleVector2d(v, 1.f / v.Length());
}

} // namespace

LongPressDragSelector::LongPressDragSelector(
LongPressDragSelectorClient* client)
Expand Down Expand Up @@ -70,21 +77,27 @@ bool LongPressDragSelector::WillHandleTouchEvent(const MotionEvent& event) {
// If initial motion is up/down, extend the start/end selection bound.
extend_selection_start = delta.y() < 0;
} else {
// Otherwise extend the selection bound toward which we're moving.
// Otherwise extend the selection bound toward which we're moving, or
// the closest bound if motion is already away from both bounds.
// Note that, for mixed RTL text, or for multiline selections triggered
// by longpress, this may not pick the most suitable drag target
gfx::Vector2dF start_delta = selection_start - position;
gfx::Vector2dF start_delta = selection_start - longpress_drag_start_anchor_;
gfx::Vector2dF end_delta = selection_end - longpress_drag_start_anchor_;

// The vectors must be normalized to make dot product comparison meaningful.
if (!start_delta.IsZero())
start_delta.Scale(1.f / start_delta.Length());
gfx::Vector2dF end_delta = selection_end - position;
if (!end_delta.IsZero())
end_delta.Scale(1.f / start_delta.Length());

// The larger the dot product the more similar the direction.
extend_selection_start =
gfx::DotProduct(start_delta, delta) > gfx::DotProduct(end_delta, delta);
gfx::Vector2dF normalized_start_delta = SafeNormalize(start_delta);
gfx::Vector2dF normalized_end_delta = SafeNormalize(end_delta);
double start_dot_product = gfx::DotProduct(normalized_start_delta, delta);
double end_dot_product = gfx::DotProduct(normalized_end_delta, delta);

if (start_dot_product >= 0 || end_dot_product >= 0) {
// The greater the dot product the more similar the direction.
extend_selection_start = start_dot_product > end_dot_product;
} else {
// If we're already moving away from both endpoints, pick the closest.
extend_selection_start =
start_delta.LengthSquared() < end_delta.LengthSquared();
}
}

gfx::PointF extent = extend_selection_start ? selection_start : selection_end;
Expand Down
36 changes: 35 additions & 1 deletion ui/touch_selection/longpress_drag_selector_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ TEST_F(LongPressDragSelectorTest, BasicReverseDrag) {
EXPECT_FALSE(IsDragging());

// Initiate drag motion.
EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 5, 0)));
EXPECT_FALSE(IsDragging());

// As the initial motion is leftward, toward the selection start, the
Expand Down Expand Up @@ -330,4 +330,38 @@ TEST_F(LongPressDragSelectorTest, SelectionDeactivated) {
EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint()));
}

TEST_F(LongPressDragSelectorTest, DragFast) {
LongPressDragSelector selector(this);
MockMotionEvent event;

// Start a touch sequence.
EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0)));
EXPECT_FALSE(GetAndResetActiveStateChanged());

// Activate a longpress-triggered selection.
gfx::PointF selection_start(0, 10);
gfx::PointF selection_end(10, 10);
selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF());
EXPECT_TRUE(GetAndResetActiveStateChanged());
SetSelection(selection_start, selection_end);
selector.OnSelectionActivated();
EXPECT_FALSE(IsDragging());

// Initiate drag motion.
EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 15, 5)));
EXPECT_FALSE(IsDragging());

// As the initial motion exceeds both endpoints, the closer bound should
// be used for dragging, in this case the selection end.
EXPECT_TRUE(selector.WillHandleTouchEvent(
event.MovePoint(0, 15.f + kSlop * 2.f, 5.f + kSlop)));
EXPECT_TRUE(IsDragging());
EXPECT_EQ(selection_end, DragPosition());

// Release the touch sequence, ending the drag.
EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint()));
EXPECT_FALSE(IsDragging());
EXPECT_TRUE(GetAndResetActiveStateChanged());
}

} // namespace ui

0 comments on commit 5e1e7b4

Please sign in to comment.