Enable magnifier and haptic feedback for swipe to move cursor
Design doc (internal): go/cursor-control-magnifier 1) Plumbing to forward cursor control gesture to RWHVA. 2) Temporarily hide insertion handles when magnifier is showing. Note that we are not calling SetAlpha() since OnInsertionChanged() will reset the alpha before the cursor control ends. 3) Reuse existing logic for selection popup controller to enable magnifier and haptic feedback. Bug: 1134492 Change-Id: I2312283a4baa775ac70d89431d444d48fff7b242 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2424900 Reviewed-by: Bo <boliu@chromium.org> Reviewed-by: Dave Tapuska <dtapuska@chromium.org> Reviewed-by: Robert Flack <flackr@chromium.org> Reviewed-by: Mohsen Izadi <mohsen@chromium.org> Reviewed-by: Shimi Zhang <ctzsm@chromium.org> Commit-Queue: Changwan Ryu <changwan@chromium.org> Cr-Commit-Position: refs/heads/master@{#824618}
This commit is contained in:
content/browser/renderer_host
ui/touch_selection
@ -99,6 +99,7 @@
|
||||
#include "ui/gfx/geometry/dip_util.h"
|
||||
#include "ui/gfx/geometry/rect_conversions.h"
|
||||
#include "ui/gfx/geometry/size_conversions.h"
|
||||
#include "ui/touch_selection/selection_event_type.h"
|
||||
#include "ui/touch_selection/touch_selection_controller.h"
|
||||
|
||||
namespace content {
|
||||
@ -1633,6 +1634,9 @@ void RenderWidgetHostViewAndroid::GestureEventAck(
|
||||
|
||||
if (gesture_listener_manager_)
|
||||
gesture_listener_manager_->GestureEventAck(event, ack_result);
|
||||
|
||||
if (event.data.scroll_begin.cursor_control || swipe_to_move_cursor_activated_)
|
||||
OnSwipeToMoveCursorGestureAck(event);
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewAndroid::ChildDidAckGestureEvent(
|
||||
@ -2440,6 +2444,37 @@ void RenderWidgetHostViewAndroid::SetDisplayFeatureForTesting(
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewAndroid::OnSwipeToMoveCursorGestureAck(
|
||||
const blink::WebGestureEvent& event) {
|
||||
if (!touch_selection_controller_ || !selection_popup_controller_) {
|
||||
swipe_to_move_cursor_activated_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.GetType()) {
|
||||
case blink::WebInputEvent::Type::kGestureScrollBegin: {
|
||||
swipe_to_move_cursor_activated_ = true;
|
||||
touch_selection_controller_->OnSwipeToMoveCursorBegin();
|
||||
OnSelectionEvent(ui::INSERTION_HANDLE_DRAG_STARTED);
|
||||
break;
|
||||
}
|
||||
case blink::WebInputEvent::Type::kGestureScrollUpdate: {
|
||||
gfx::RectF rect = touch_selection_controller_->GetRectBetweenBounds();
|
||||
selection_popup_controller_->OnDragUpdate(
|
||||
gfx::PointF(event.PositionInWidget().x(), rect.right_center().y()));
|
||||
break;
|
||||
}
|
||||
case blink::WebInputEvent::Type::kGestureScrollEnd: {
|
||||
swipe_to_move_cursor_activated_ = false;
|
||||
touch_selection_controller_->OnSwipeToMoveCursorEnd();
|
||||
OnSelectionEvent(ui::INSERTION_HANDLE_DRAG_STOPPED);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewAndroid::WasEvicted() {
|
||||
// Eviction can occur when the CompositorFrameSink has changed. This can
|
||||
// occur either from a lost connection, as well as from the initial conneciton
|
||||
|
@ -456,6 +456,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
|
||||
|
||||
void OnUpdateScopedSelectionHandles();
|
||||
|
||||
void OnSwipeToMoveCursorGestureAck(const blink::WebGestureEvent& event);
|
||||
|
||||
bool is_showing_;
|
||||
|
||||
// Window-specific bits that affect widget visibility.
|
||||
@ -558,6 +560,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
|
||||
// TODO(ericrk): Make this more robust.
|
||||
bool in_sync_copy_contents_ = false;
|
||||
|
||||
// Whether swipe-to-move-cursor gesture is activated.
|
||||
bool swipe_to_move_cursor_activated_ = false;
|
||||
|
||||
// A cached copy of the most up to date RenderFrameMetadata.
|
||||
base::Optional<cc::RenderFrameMetadata> last_render_frame_metadata_;
|
||||
|
||||
|
@ -366,6 +366,23 @@ bool TouchSelectionController::WillHandleTouchEventImpl(
|
||||
return false;
|
||||
}
|
||||
|
||||
void TouchSelectionController::OnSwipeToMoveCursorBegin() {
|
||||
if (config_.hide_active_handle) {
|
||||
// Hide the handle when magnifier is showing since it can confuse the user.
|
||||
SetTemporarilyHidden(true);
|
||||
|
||||
// If the user has typed something, the insertion handle might be hidden.
|
||||
// Prepare to show touch handles on end.
|
||||
show_touch_handles_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void TouchSelectionController::OnSwipeToMoveCursorEnd() {
|
||||
// Show the handle at the end if magnifier was showing.
|
||||
if (config_.hide_active_handle)
|
||||
SetTemporarilyHidden(false);
|
||||
}
|
||||
|
||||
void TouchSelectionController::OnDragBegin(
|
||||
const TouchSelectionDraggable& draggable,
|
||||
const gfx::PointF& drag_position) {
|
||||
|
@ -139,6 +139,11 @@ class UI_TOUCH_SELECTION_EXPORT TouchSelectionController
|
||||
const gfx::PointF& GetStartPosition() const;
|
||||
const gfx::PointF& GetEndPosition() const;
|
||||
|
||||
// To be called when swipe-to-move-cursor motion begins.
|
||||
void OnSwipeToMoveCursorBegin();
|
||||
// To be called when swipe-to-move-cursor motion ends.
|
||||
void OnSwipeToMoveCursorEnd();
|
||||
|
||||
const gfx::SelectionBound& start() const { return start_; }
|
||||
const gfx::SelectionBound& end() const { return end_; }
|
||||
|
||||
|
@ -1658,4 +1658,71 @@ TEST_F(TouchSelectionControllerTest, HideActiveSelectionHandle) {
|
||||
EXPECT_EQ(1.f, test_controller.GetEndAlpha());
|
||||
}
|
||||
|
||||
TEST_F(TouchSelectionControllerTest, SwipeToMoveCursor_HideHandlesIfShown) {
|
||||
// Step 1: Extra set-up.
|
||||
// For Android P+, we need to hide handles while showing magnifier.
|
||||
SetHideActiveHandle(true);
|
||||
TouchSelectionControllerTestApi test_controller(&controller());
|
||||
|
||||
gfx::RectF insertion_rect(5, 5, 0, 10);
|
||||
bool visible = true;
|
||||
|
||||
OnTapEvent();
|
||||
ChangeInsertion(insertion_rect, visible);
|
||||
EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_HANDLE_SHOWN));
|
||||
EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventStart());
|
||||
|
||||
EXPECT_TRUE(test_controller.GetStartVisible());
|
||||
|
||||
// Step 2: Swipe-to-move-cursor begins: hide handles.
|
||||
controller().OnSwipeToMoveCursorBegin();
|
||||
EXPECT_FALSE(test_controller.GetStartVisible());
|
||||
|
||||
// Step 3: Move insertion: still hidden.
|
||||
gfx::RectF new_insertion_rect(10, 5, 0, 10);
|
||||
ChangeInsertion(new_insertion_rect, visible);
|
||||
EXPECT_FALSE(test_controller.GetStartVisible());
|
||||
|
||||
// Step 4: Swipe-to-move-cursor ends: show handles.
|
||||
controller().OnSwipeToMoveCursorEnd();
|
||||
EXPECT_TRUE(test_controller.GetStartVisible());
|
||||
}
|
||||
|
||||
TEST_F(TouchSelectionControllerTest, SwipeToMoveCursor_HandleWasNotShown) {
|
||||
// Step 1: Extra set-up.
|
||||
// For Android P+, we need to hide handles while showing magnifier.
|
||||
SetHideActiveHandle(true);
|
||||
TouchSelectionControllerTestApi test_controller(&controller());
|
||||
|
||||
gfx::RectF insertion_rect(5, 5, 0, 10);
|
||||
bool visible = true;
|
||||
|
||||
OnTapEvent();
|
||||
ChangeInsertion(insertion_rect, visible);
|
||||
EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_HANDLE_SHOWN));
|
||||
EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventStart());
|
||||
|
||||
EXPECT_TRUE(test_controller.GetStartVisible());
|
||||
|
||||
// Step 2: Handle is initially hidden, i.e., due to user typing.
|
||||
controller().HideAndDisallowShowingAutomatically();
|
||||
EXPECT_FALSE(test_controller.GetStartVisible());
|
||||
|
||||
// Step 3: Swipe-to-move-cursor begins: hide handles.
|
||||
controller().OnSwipeToMoveCursorBegin();
|
||||
EXPECT_FALSE(test_controller.GetStartVisible());
|
||||
|
||||
// Step 4: Move insertion.
|
||||
// Note that this step is needed to show handle at the end since
|
||||
// OnInsertionChanged() should activate start_ again, although it will stay
|
||||
// temporarily hidden.
|
||||
gfx::RectF new_insertion_rect(10, 5, 0, 10);
|
||||
ChangeInsertion(new_insertion_rect, visible);
|
||||
EXPECT_FALSE(test_controller.GetStartVisible());
|
||||
|
||||
// Step 5: Swipe-to-move-cursor ends: show handles.
|
||||
controller().OnSwipeToMoveCursorEnd();
|
||||
EXPECT_TRUE(test_controller.GetStartVisible());
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
Reference in New Issue
Block a user