summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchristiank <christiank@opera.com>2014-11-05 02:49:14 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-05 10:49:31 +0000
commitaeed9866ec8ef2172404784edeebc85aaafbf330 (patch)
tree5118b0b317a4d0f4fb1524a7794d32106fc1fcd8
parent61cb84971f5f21eb83b7e3b3ac43364aafb9b2d4 (diff)
downloadchromium_src-aeed9866ec8ef2172404784edeebc85aaafbf330.zip
chromium_src-aeed9866ec8ef2172404784edeebc85aaafbf330.tar.gz
chromium_src-aeed9866ec8ef2172404784edeebc85aaafbf330.tar.bz2
Update touch selection to only modify one selection point at a time.
This is made in preparation for enabling selection auto scroll using touch handles. BUG=340658 Review URL: https://codereview.chromium.org/657803002 Cr-Commit-Position: refs/heads/master@{#302776}
-rw-r--r--content/browser/android/content_view_core_impl.cc19
-rw-r--r--content/browser/android/content_view_core_impl.h6
-rw-r--r--content/browser/renderer_host/input/input_router_impl.cc51
-rw-r--r--content/browser/renderer_host/input/input_router_impl.h14
-rw-r--r--content/browser/renderer_host/input/input_router_impl_unittest.cc198
-rw-r--r--content/browser/renderer_host/input/touch_selection_controller.cc16
-rw-r--r--content/browser/renderer_host/input/touch_selection_controller.h6
-rw-r--r--content/browser/renderer_host/input/touch_selection_controller_unittest.cc139
-rw-r--r--content/browser/renderer_host/render_widget_host_unittest.cc4
-rw-r--r--content/browser/renderer_host/render_widget_host_view_android.cc12
-rw-r--r--content/browser/renderer_host/render_widget_host_view_android.h5
-rw-r--r--content/browser/web_contents/web_contents_impl.cc15
-rw-r--r--content/browser/web_contents/web_contents_impl.h5
-rw-r--r--content/common/input_messages.h18
-rw-r--r--content/common/view_messages.h3
-rw-r--r--content/renderer/render_frame_impl.cc19
-rw-r--r--content/renderer/render_frame_impl.h3
-rw-r--r--content/renderer/render_view_impl.cc2
18 files changed, 468 insertions, 67 deletions
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 18528b6..9aa69cd 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -770,17 +770,24 @@ void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
root_layer_->SetIsDrawable(true);
}
-void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& start,
- const gfx::PointF& end) {
+void ContentViewCoreImpl::MoveRangeSelectionExtent(const gfx::PointF& extent) {
if (!web_contents_)
return;
- gfx::Point start_point = gfx::Point(start.x(), start.y());
- gfx::Point end_point = gfx::Point(end.x(), end.y());
- if (start_point == end_point)
+ web_contents_->MoveRangeSelectionExtent(gfx::Point(extent.x(), extent.y()));
+}
+
+void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent) {
+ if (!web_contents_)
+ return;
+
+ gfx::Point base_point = gfx::Point(base.x(), base.y());
+ gfx::Point extent_point = gfx::Point(extent.x(), extent.y());
+ if (base_point == extent_point)
return;
- web_contents_->SelectRange(start_point, end_point);
+ web_contents_->SelectRange(base_point, extent_point);
}
ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index b9ff454..6e90696 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -270,8 +270,10 @@ class ContentViewCoreImpl : public ContentViewCore,
void AttachLayer(scoped_refptr<cc::Layer> layer);
void RemoveLayer(scoped_refptr<cc::Layer> layer);
- void SelectBetweenCoordinates(const gfx::PointF& start,
- const gfx::PointF& end);
+ void MoveRangeSelectionExtent(const gfx::PointF& extent);
+
+ void SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent);
private:
class ContentViewUserData;
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index 364f7ca..4848f6d 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -68,7 +68,7 @@ InputRouterImpl::InputRouterImpl(IPC::Sender* sender,
client_(client),
ack_handler_(ack_handler),
routing_id_(routing_id),
- select_range_pending_(false),
+ select_message_pending_(false),
move_caret_pending_(false),
mouse_move_pending_(false),
mouse_wheel_pending_(false),
@@ -83,7 +83,9 @@ InputRouterImpl::InputRouterImpl(IPC::Sender* sender,
UpdateTouchAckTimeoutEnabled();
}
-InputRouterImpl::~InputRouterImpl() {}
+InputRouterImpl::~InputRouterImpl() {
+ STLDeleteElements(&pending_select_messages_);
+}
void InputRouterImpl::Flush() {
flush_requested_ = true;
@@ -95,7 +97,8 @@ bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) {
switch (message->type()) {
// Check for types that require an ACK.
case InputMsg_SelectRange::ID:
- return SendSelectRange(message.Pass());
+ case InputMsg_MoveRangeSelectionExtent::ID:
+ return SendSelectMessage(message.Pass());
case InputMsg_MoveCaret::ID:
return SendMoveCaret(message.Pass());
case InputMsg_HandleInputEvent::ID:
@@ -267,8 +270,10 @@ bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(InputRouterImpl, message)
IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck)
IPC_MESSAGE_HANDLER(InputHostMsg_DidOverscroll, OnDidOverscroll)
- IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck)
+ IPC_MESSAGE_HANDLER(InputHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck)
+ IPC_MESSAGE_HANDLER(InputHostMsg_SelectRange_ACK, OnSelectMessageAck)
+ IPC_MESSAGE_HANDLER(InputHostMsg_MoveRangeSelectionExtent_ACK,
+ OnSelectMessageAck)
IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
OnHasTouchEventHandlers)
IPC_MESSAGE_HANDLER(InputHostMsg_SetTouchAction,
@@ -298,14 +303,25 @@ void InputRouterImpl::OnGestureEventAck(
ack_handler_->OnGestureEventAck(event, ack_result);
}
-bool InputRouterImpl::SendSelectRange(scoped_ptr<IPC::Message> message) {
- DCHECK(message->type() == InputMsg_SelectRange::ID);
- if (select_range_pending_) {
- next_selection_range_ = message.Pass();
+bool InputRouterImpl::SendSelectMessage(
+ scoped_ptr<IPC::Message> message) {
+ DCHECK(message->type() == InputMsg_SelectRange::ID ||
+ message->type() == InputMsg_MoveRangeSelectionExtent::ID);
+
+ // TODO(jdduke): Factor out common logic between selection and caret-related
+ // IPC messages.
+ if (select_message_pending_) {
+ if (!pending_select_messages_.empty() &&
+ pending_select_messages_.back()->type() == message->type()) {
+ delete pending_select_messages_.back();
+ pending_select_messages_.pop_back();
+ }
+
+ pending_select_messages_.push_back(message.release());
return true;
}
- select_range_pending_ = true;
+ select_message_pending_ = true;
return Send(message.release());
}
@@ -487,10 +503,15 @@ void InputRouterImpl::OnMsgMoveCaretAck() {
SendMoveCaret(next_move_caret_.Pass());
}
-void InputRouterImpl::OnSelectRangeAck() {
- select_range_pending_ = false;
- if (next_selection_range_)
- SendSelectRange(next_selection_range_.Pass());
+void InputRouterImpl::OnSelectMessageAck() {
+ select_message_pending_ = false;
+ if (!pending_select_messages_.empty()) {
+ scoped_ptr<IPC::Message> next_message =
+ make_scoped_ptr(pending_select_messages_.front());
+ pending_select_messages_.pop_front();
+
+ SendSelectMessage(next_message.Pass());
+ }
}
void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) {
@@ -679,7 +700,7 @@ bool InputRouterImpl::HasPendingEvents() const {
!key_queue_.empty() ||
mouse_move_pending_ ||
mouse_wheel_pending_ ||
- select_range_pending_ ||
+ select_message_pending_ ||
move_caret_pending_;
}
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h
index b08c1e3..2b00c12 100644
--- a/content/browser/renderer_host/input/input_router_impl.h
+++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -95,7 +95,7 @@ private:
InputEventAckState ack_result) override;
bool SendMoveCaret(scoped_ptr<IPC::Message> message);
- bool SendSelectRange(scoped_ptr<IPC::Message> message);
+ bool SendSelectMessage(scoped_ptr<IPC::Message> message);
bool Send(IPC::Message* message);
// Filters and forwards |input_event| to the appropriate handler.
@@ -148,7 +148,7 @@ private:
void OnInputEventAck(const InputHostMsg_HandleInputEvent_ACK_Params& ack);
void OnDidOverscroll(const DidOverscrollParams& params);
void OnMsgMoveCaretAck();
- void OnSelectRangeAck();
+ void OnSelectMessageAck();
void OnHasTouchEventHandlers(bool has_handlers);
void OnSetTouchAction(TouchAction touch_action);
@@ -212,11 +212,13 @@ private:
InputAckHandler* ack_handler_;
int routing_id_;
- // (Similar to |mouse_move_pending_|.) True while waiting for SelectRange_ACK.
- bool select_range_pending_;
+ // (Similar to |mouse_move_pending_|.) True while waiting for SelectRange_ACK
+ // or MoveRangeSelectionExtent_ACK.
+ bool select_message_pending_;
- // (Similar to |next_mouse_move_|.) The next SelectRange to send, if any.
- scoped_ptr<IPC::Message> next_selection_range_;
+ // Queue of pending select messages to send after receving the next select
+ // message ack.
+ std::deque<IPC::Message*> pending_select_messages_;
// (Similar to |mouse_move_pending_|.) True while waiting for MoveCaret_ACK.
bool move_caret_pending_;
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc
index 5b3d7d7..ed922c9d 100644
--- a/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -354,7 +354,7 @@ TEST_F(InputRouterImplTest, CoalescesRangeSelection) {
// Now ack the first message.
{
- scoped_ptr<IPC::Message> response(new ViewHostMsg_SelectRange_ACK(0));
+ scoped_ptr<IPC::Message> response(new InputHostMsg_SelectRange_ACK(0));
input_router_->OnMessageReceived(*response);
}
@@ -367,7 +367,197 @@ TEST_F(InputRouterImplTest, CoalescesRangeSelection) {
// Acking the coalesced msg should not send any more msg.
{
- scoped_ptr<IPC::Message> response(new ViewHostMsg_SelectRange_ACK(0));
+ scoped_ptr<IPC::Message> response(new InputHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+}
+
+TEST_F(InputRouterImplTest, CoalescesMoveRangeSelectionExtent) {
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(1, 2))));
+ ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(1, 2));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Send two more messages without acking.
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(3, 4))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(5, 6))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // Now ack the first message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ // Verify that the two messages are coalesced into one message.
+ ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(5, 6));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Acking the coalesced msg should not send any more msg.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+}
+
+TEST_F(InputRouterImplTest, InterleaveSelectRangeAndMoveRangeSelectionExtent) {
+ // Send first message: SelectRange.
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4))));
+ ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(1, 2),
+ gfx::Point(3, 4));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Send second message: MoveRangeSelectionExtent.
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(5, 6))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // Send third message: SelectRange.
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(7, 8), gfx::Point(9, 10))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // Ack the messages and verify that they're not coalesced and that they're in
+ // correct order.
+
+ // Ack the first message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(5, 6));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Ack the second message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(7, 8),
+ gfx::Point(9, 10));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Ack the third message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+}
+
+TEST_F(InputRouterImplTest,
+ CoalescesInterleavedSelectRangeAndMoveRangeSelectionExtent) {
+ // Send interleaved SelectRange and MoveRangeSelectionExtent messages. They
+ // should be coalesced as shown by the arrows.
+ // > SelectRange
+ // MoveRangeSelectionExtent
+ // MoveRangeSelectionExtent
+ // > MoveRangeSelectionExtent
+ // SelectRange
+ // > SelectRange
+ // > MoveRangeSelectionExtent
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4))));
+ ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(1, 2),
+ gfx::Point(3, 4));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(5, 6))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(7, 8))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(9, 10))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(11, 12), gfx::Point(13, 14))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(15, 16), gfx::Point(17, 18))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(19, 20))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // Ack the first message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ // Verify that the three MoveRangeSelectionExtent messages are coalesced into
+ // one message.
+ ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(9, 10));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Ack the second message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ // Verify that the two SelectRange messages are coalesced into one message.
+ ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(15, 16),
+ gfx::Point(17, 18));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Ack the third message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ // Verify the fourth message.
+ ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(19, 20));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Ack the fourth message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
input_router_->OnMessageReceived(*response);
}
EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
@@ -391,7 +581,7 @@ TEST_F(InputRouterImplTest, CoalescesCaretMove) {
// Now ack the first message.
{
- scoped_ptr<IPC::Message> response(new ViewHostMsg_MoveCaret_ACK(0));
+ scoped_ptr<IPC::Message> response(new InputHostMsg_MoveCaret_ACK(0));
input_router_->OnMessageReceived(*response);
}
@@ -402,7 +592,7 @@ TEST_F(InputRouterImplTest, CoalescesCaretMove) {
// Acking the coalesced msg should not send any more msg.
{
- scoped_ptr<IPC::Message> response(new ViewHostMsg_MoveCaret_ACK(0));
+ scoped_ptr<IPC::Message> response(new InputHostMsg_MoveCaret_ACK(0));
input_router_->OnMessageReceived(*response);
}
EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
diff --git a/content/browser/renderer_host/input/touch_selection_controller.cc b/content/browser/renderer_host/input/touch_selection_controller.cc
index e904e28..4c8807d 100644
--- a/content/browser/renderer_host/input/touch_selection_controller.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller.cc
@@ -209,13 +209,19 @@ void TouchSelectionController::OnHandleDragBegin(const TouchHandle& handle) {
return;
}
+ gfx::PointF base, extent;
if (&handle == start_selection_handle_.get()) {
- fixed_handle_position_ =
- end_selection_handle_->position() + GetEndLineOffset();
+ base = end_selection_handle_->position() + GetEndLineOffset();
+ extent = start_selection_handle_->position() + GetStartLineOffset();
} else {
- fixed_handle_position_ =
- start_selection_handle_->position() + GetStartLineOffset();
+ base = start_selection_handle_->position() + GetStartLineOffset();
+ extent = end_selection_handle_->position() + GetEndLineOffset();
}
+
+ // When moving the handle we want to move only the extent point. Before doing
+ // so we must make sure that the base point is set correctly.
+ client_->SelectBetweenCoordinates(base, extent);
+
client_->OnSelectionEvent(SELECTION_DRAG_STARTED, handle.position());
}
@@ -230,7 +236,7 @@ void TouchSelectionController::OnHandleDragUpdate(const TouchHandle& handle,
if (&handle == insertion_handle_.get()) {
client_->MoveCaret(line_position);
} else {
- client_->SelectBetweenCoordinates(fixed_handle_position_, line_position);
+ client_->MoveRangeSelectionExtent(line_position);
}
}
diff --git a/content/browser/renderer_host/input/touch_selection_controller.h b/content/browser/renderer_host/input/touch_selection_controller.h
index 1ded1a97..abe4ed4 100644
--- a/content/browser/renderer_host/input/touch_selection_controller.h
+++ b/content/browser/renderer_host/input/touch_selection_controller.h
@@ -31,8 +31,9 @@ class CONTENT_EXPORT TouchSelectionControllerClient {
virtual bool SupportsAnimation() const = 0;
virtual void SetNeedsAnimate() = 0;
virtual void MoveCaret(const gfx::PointF& position) = 0;
- virtual void SelectBetweenCoordinates(const gfx::PointF& start,
- const gfx::PointF& end) = 0;
+ virtual void MoveRangeSelectionExtent(const gfx::PointF& extent) = 0;
+ virtual void SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent) = 0;
virtual void OnSelectionEvent(SelectionEventType event,
const gfx::PointF& position) = 0;
virtual scoped_ptr<TouchHandleDrawable> CreateDrawable() = 0;
@@ -133,7 +134,6 @@ class CONTENT_EXPORT TouchSelectionController : public TouchHandleClient {
scoped_ptr<TouchHandle> start_selection_handle_;
scoped_ptr<TouchHandle> end_selection_handle_;
- gfx::PointF fixed_handle_position_;
bool is_selection_active_;
bool activate_selection_automatically_;
diff --git a/content/browser/renderer_host/input/touch_selection_controller_unittest.cc b/content/browser/renderer_host/input/touch_selection_controller_unittest.cc
index ca4af34..de7d620 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_unittest.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_unittest.cc
@@ -42,6 +42,7 @@ class TouchSelectionControllerTest : public testing::Test,
: last_event_(SELECTION_CLEARED),
caret_moved_(false),
selection_moved_(false),
+ selection_points_swapped_(false),
needs_animate_(false),
animation_enabled_(true),
dragging_enabled_(false) {}
@@ -69,11 +70,18 @@ class TouchSelectionControllerTest : public testing::Test,
caret_position_ = position;
}
- void SelectBetweenCoordinates(const gfx::PointF& start,
- const gfx::PointF& end) override {
+ void SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent) override {
+ if (base == selection_end_ && extent == selection_start_)
+ selection_points_swapped_ = true;
+
+ selection_start_ = base;
+ selection_end_ = extent;
+ }
+
+ virtual void MoveRangeSelectionExtent(const gfx::PointF& extent) override {
selection_moved_ = true;
- selection_start_ = start;
- selection_end_ = end;
+ selection_end_ = extent;
}
void OnSelectionEvent(SelectionEventType event,
@@ -148,6 +156,12 @@ class TouchSelectionControllerTest : public testing::Test,
return moved;
}
+ bool GetAndResetSelectionPointsSwapped() {
+ bool swapped = selection_points_swapped_;
+ selection_points_swapped_ = false;
+ return swapped;
+ }
+
const gfx::PointF& GetLastCaretPosition() const { return caret_position_; }
const gfx::PointF& GetLastSelectionStart() const { return selection_start_; }
const gfx::PointF& GetLastSelectionEnd() const { return selection_end_; }
@@ -164,6 +178,7 @@ class TouchSelectionControllerTest : public testing::Test,
SelectionEventType last_event_;
bool caret_moved_;
bool selection_moved_;
+ bool selection_points_swapped_;
bool needs_animate_;
bool animation_enabled_;
bool dragging_enabled_;
@@ -602,6 +617,122 @@ TEST_F(TouchSelectionControllerTest, SelectionDraggedWithOverlap) {
EXPECT_FALSE(GetAndResetSelectionMoved());
}
+TEST_F(TouchSelectionControllerTest, SelectionDraggedToSwitchBaseAndExtent) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ controller().OnLongPressEvent();
+
+ float line_height = 10.f;
+ gfx::RectF start_rect(50, line_height, 0, line_height);
+ gfx::RectF end_rect(100, line_height, 0, line_height);
+ bool visible = true;
+ ChangeSelection(start_rect, visible, end_rect, visible);
+ EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+
+ SetDraggingEnabled(true);
+
+ // Move the extent, not triggering a swap of points.
+ MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time,
+ end_rect.x(), end_rect.bottom());
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+
+ gfx::PointF base_offset = start_rect.CenterPoint();
+ gfx::PointF extent_offset = end_rect.CenterPoint();
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
+ end_rect.x(), end_rect.bottom() + 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+ EXPECT_EQ(base_offset, GetLastSelectionStart());
+ EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+
+ end_rect += gfx::Vector2dF(0, 5);
+ ChangeSelection(start_rect, visible, end_rect, visible);
+
+ // Move the base, triggering a swap of points.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
+ start_rect.x(), start_rect.bottom());
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+ EXPECT_TRUE(GetAndResetSelectionPointsSwapped());
+
+ base_offset = end_rect.CenterPoint();
+ extent_offset = start_rect.CenterPoint();
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
+ start_rect.x(), start_rect.bottom() + 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+ EXPECT_EQ(base_offset, GetLastSelectionStart());
+ EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+
+ start_rect += gfx::Vector2dF(0, 5);
+ ChangeSelection(start_rect, visible, end_rect, visible);
+
+ // Move the same point again, not triggering a swap of points.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
+ start_rect.x(), start_rect.bottom());
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+
+ base_offset = end_rect.CenterPoint();
+ extent_offset = start_rect.CenterPoint();
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
+ start_rect.x(), start_rect.bottom() + 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+ EXPECT_EQ(base_offset, GetLastSelectionStart());
+ EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+
+ start_rect += gfx::Vector2dF(0, 5);
+ ChangeSelection(start_rect, visible, end_rect, visible);
+
+ // Move the base, triggering a swap of points.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
+ end_rect.x(), end_rect.bottom());
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+ EXPECT_TRUE(GetAndResetSelectionPointsSwapped());
+
+ base_offset = start_rect.CenterPoint();
+ extent_offset = end_rect.CenterPoint();
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
+ end_rect.x(), end_rect.bottom() + 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+ EXPECT_EQ(base_offset, GetLastSelectionStart());
+ EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+}
+
TEST_F(TouchSelectionControllerTest, Animation) {
controller().OnTapEvent();
controller().OnSelectionEditable(true);
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 67af1bb..830ab01 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -1301,7 +1301,7 @@ TEST_F(RenderWidgetHostTest, InputRouterReceivesHandleInputEvent_ACK) {
TEST_F(RenderWidgetHostTest, InputRouterReceivesMoveCaret_ACK) {
host_->SetupForInputRouterTest();
- host_->OnMessageReceived(ViewHostMsg_MoveCaret_ACK(0));
+ host_->OnMessageReceived(InputHostMsg_MoveCaret_ACK(0));
EXPECT_TRUE(host_->mock_input_router()->message_received_);
}
@@ -1309,7 +1309,7 @@ TEST_F(RenderWidgetHostTest, InputRouterReceivesMoveCaret_ACK) {
TEST_F(RenderWidgetHostTest, InputRouterReceivesSelectRange_ACK) {
host_->SetupForInputRouterTest();
- host_->OnMessageReceived(ViewHostMsg_SelectRange_ACK(0));
+ host_->OnMessageReceived(InputHostMsg_SelectRange_ACK(0));
EXPECT_TRUE(host_->mock_input_router()->message_received_);
}
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index dac44e1..3a2dc88 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1160,11 +1160,17 @@ void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
MoveCaret(gfx::Point(position.x(), position.y()));
}
+void RenderWidgetHostViewAndroid::MoveRangeSelectionExtent(
+ const gfx::PointF& extent) {
+ DCHECK(content_view_core_);
+ content_view_core_->MoveRangeSelectionExtent(extent);
+}
+
void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
- const gfx::PointF& start,
- const gfx::PointF& end) {
+ const gfx::PointF& base,
+ const gfx::PointF& extent) {
DCHECK(content_view_core_);
- content_view_core_->SelectBetweenCoordinates(start, end);
+ content_view_core_->SelectBetweenCoordinates(base, extent);
}
void RenderWidgetHostViewAndroid::OnSelectionEvent(
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 48d6536..063a515 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -269,8 +269,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
virtual bool SupportsAnimation() const override;
virtual void SetNeedsAnimate() override;
virtual void MoveCaret(const gfx::PointF& position) override;
- virtual void SelectBetweenCoordinates(const gfx::PointF& start,
- const gfx::PointF& end) override;
+ virtual void MoveRangeSelectionExtent(const gfx::PointF& extent) override;
+ virtual void SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent) override;
virtual void OnSelectionEvent(SelectionEventType event,
const gfx::PointF& anchor_position) override;
virtual scoped_ptr<TouchHandleDrawable> CreateDrawable() override;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index c17dcf3..d3e8b13 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3174,14 +3174,23 @@ void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
type, Source<NavigationController>(&controller_), det);
}
-void WebContentsImpl::SelectRange(const gfx::Point& start,
- const gfx::Point& end) {
+void WebContentsImpl::MoveRangeSelectionExtent(const gfx::Point& extent) {
+ RenderFrameHost* focused_frame = GetFocusedFrame();
+ if (!focused_frame)
+ return;
+
+ focused_frame->Send(new InputMsg_MoveRangeSelectionExtent(
+ focused_frame->GetRoutingID(), extent));
+}
+
+void WebContentsImpl::SelectRange(const gfx::Point& base,
+ const gfx::Point& extent) {
RenderFrameHost* focused_frame = GetFocusedFrame();
if (!focused_frame)
return;
focused_frame->Send(
- new InputMsg_SelectRange(focused_frame->GetRoutingID(), start, end));
+ new InputMsg_SelectRange(focused_frame->GetRoutingID(), base, extent));
}
void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index e502796..7869292 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -638,9 +638,12 @@ class CONTENT_EXPORT WebContentsImpl
typedef base::Callback<void(WebContents*)> CreatedCallback;
+ // Requests the renderer to move the selection extent to a new position.
+ void MoveRangeSelectionExtent(const gfx::Point& extent);
+
// Requests the renderer to select the region between two points in the
// currently focused frame.
- void SelectRange(const gfx::Point& start, const gfx::Point& end);
+ void SelectRange(const gfx::Point& base, const gfx::Point& extent);
// Notifies the main frame that it can continue navigation (if it was deferred
// immediately at first response).
diff --git a/content/common/input_messages.h b/content/common/input_messages.h
index 9953035..95663f7 100644
--- a/content/common/input_messages.h
+++ b/content/common/input_messages.h
@@ -199,8 +199,13 @@ IPC_MESSAGE_ROUTED0(InputMsg_Unselect)
// Requests the renderer to select the region between two points.
// Expects a SelectRange_ACK message when finished.
IPC_MESSAGE_ROUTED2(InputMsg_SelectRange,
- gfx::Point /* start */,
- gfx::Point /* end */)
+ gfx::Point /* base */,
+ gfx::Point /* extent */)
+
+// Requests the renderer to move the selection extent point to a new position.
+// Expects a MoveRangeSelectionExtent_ACK message when finished.
+IPC_MESSAGE_ROUTED1(InputMsg_MoveRangeSelectionExtent,
+ gfx::Point /* extent */)
// Requests the renderer to move the caret selection toward the point.
// Expects a MoveCaret_ACK message when finished.
@@ -237,6 +242,15 @@ IPC_MESSAGE_ROUTED1(InputHostMsg_SetTouchAction,
IPC_MESSAGE_ROUTED1(InputHostMsg_DidOverscroll,
content::DidOverscrollParams /* params */)
+// Acknowledges receipt of a InputMsg_MoveCaret message.
+IPC_MESSAGE_ROUTED0(InputHostMsg_MoveCaret_ACK)
+
+// Acknowledges receipt of a InputMsg_MoveRangeSelectionExtent message.
+IPC_MESSAGE_ROUTED0(InputHostMsg_MoveRangeSelectionExtent_ACK)
+
+// Acknowledges receipt of a InputMsg_SelectRange message.
+IPC_MESSAGE_ROUTED0(InputHostMsg_SelectRange_ACK)
+
// Required for cancelling an ongoing input method composition.
IPC_MESSAGE_ROUTED0(InputHostMsg_ImeCancelComposition)
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 3f55ab5..426ac1f 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -1330,9 +1330,6 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_SetTooltipText,
base::string16 /* tooltip text string */,
blink::WebTextDirection /* text direction hint */)
-IPC_MESSAGE_ROUTED0(ViewHostMsg_SelectRange_ACK)
-IPC_MESSAGE_ROUTED0(ViewHostMsg_MoveCaret_ACK)
-
// Notification that the text selection has changed.
// Note: The secound parameter is the character based offset of the
// base::string16
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 3d8a05f..5319024 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -920,6 +920,8 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(InputMsg_SelectAll, OnSelectAll)
IPC_MESSAGE_HANDLER(InputMsg_SelectRange, OnSelectRange)
IPC_MESSAGE_HANDLER(InputMsg_Unselect, OnUnselect)
+ IPC_MESSAGE_HANDLER(InputMsg_MoveRangeSelectionExtent,
+ OnMoveRangeSelectionExtent)
IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
IPC_MESSAGE_HANDLER(InputMsg_ExtendSelectionAndDelete,
@@ -1282,13 +1284,13 @@ void RenderFrameImpl::OnSelectAll() {
frame_->executeCommand(WebString::fromUTF8("SelectAll"), GetFocusedElement());
}
-void RenderFrameImpl::OnSelectRange(const gfx::Point& start,
- const gfx::Point& end) {
+void RenderFrameImpl::OnSelectRange(const gfx::Point& base,
+ const gfx::Point& extent) {
// This IPC is dispatched by RenderWidgetHost, so use its routing id.
- Send(new ViewHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
+ Send(new InputHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
- frame_->selectRange(start, end);
+ frame_->selectRange(base, extent);
}
void RenderFrameImpl::OnUnselect() {
@@ -1296,6 +1298,15 @@ void RenderFrameImpl::OnUnselect() {
frame_->executeCommand(WebString::fromUTF8("Unselect"), GetFocusedElement());
}
+void RenderFrameImpl::OnMoveRangeSelectionExtent(const gfx::Point& point) {
+ // This IPC is dispatched by RenderWidgetHost, so use its routing id.
+ Send(new InputHostMsg_MoveRangeSelectionExtent_ACK(
+ GetRenderWidget()->routing_id()));
+
+ base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
+ frame_->moveRangeSelectionExtent(point);
+}
+
void RenderFrameImpl::OnReplace(const base::string16& text) {
if (!frame_->hasSelection())
frame_->selectWordAroundCaret();
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index f0d15ec..ccb30b4 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -541,8 +541,9 @@ class CONTENT_EXPORT RenderFrameImpl
void OnPasteAndMatchStyle();
void OnDelete();
void OnSelectAll();
- void OnSelectRange(const gfx::Point& start, const gfx::Point& end);
+ void OnSelectRange(const gfx::Point& base, const gfx::Point& extent);
void OnUnselect();
+ void OnMoveRangeSelectionExtent(const gfx::Point& point);
void OnReplace(const base::string16& text);
void OnReplaceMisspelling(const base::string16& text);
void OnCSSInsertRequest(const std::string& css);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 49f1732..15985fc 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1465,7 +1465,7 @@ void RenderViewImpl::OnMoveCaret(const gfx::Point& point) {
if (!webview())
return;
- Send(new ViewHostMsg_MoveCaret_ACK(routing_id_));
+ Send(new InputHostMsg_MoveCaret_ACK(routing_id_));
webview()->focusedFrame()->moveCaretSelection(point);
}