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

Unified Diff: ui/touch_selection/touch_selection_controller_aura_unittest.cc

Issue 698253004: Reland: Implement Aura side of unified touch text selection for contents (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased after addition of touch_handle_orientation file Created 5 years, 10 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_aura_unittest.cc
diff --git a/ui/touch_selection/touch_selection_controller_aura_unittest.cc b/ui/touch_selection/touch_selection_controller_aura_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..26e3c4f6e21f532253abe5df59d9ccbc09a6b9c2
--- /dev/null
+++ b/ui/touch_selection/touch_selection_controller_aura_unittest.cc
@@ -0,0 +1,395 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/touch_selection/touch_selection_controller_aura.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/window.h"
+#include "ui/events/test/event_generator.h"
+#include "ui/touch_selection/touch_handle_drawable_aura.h"
+#include "ui/touch_selection/touch_selection_menu_runner.h"
+
+namespace ui {
+namespace {
+
+// A mock implementation for TouchSelectionMenuRunner used in tests.
+class TestTouchSelectionMenuRunner : public TouchSelectionMenuRunner {
+ public:
+ TestTouchSelectionMenuRunner() {}
+ ~TestTouchSelectionMenuRunner() override {}
+
+ bool is_running() const { return is_running_; }
+
+ private:
+ // TouchSelectionMenuRunner:
+ void RunMenu(TouchSelectionMenuClient* client,
+ const gfx::Rect& anchor_rect,
+ const gfx::Size& handle_image_size,
+ aura::Window* context) override {
+ is_running_ = true;
+ }
+
+ void CloseMenu() override {
+ is_running_ = false;
+ }
+
+ bool IsRunning() const override {
+ return is_running_;
+ }
+
+ bool is_running_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestTouchSelectionMenuRunner);
+};
+
+// Convenience to make constructing a GestureEvent simpler.
+class GestureEventForTest : public GestureEvent {
+ public:
+ GestureEventForTest(EventType type, int x, int y)
+ : GestureEvent(x, y, 0, base::TimeDelta(),
+ GestureEventDetails(type)) {}
+};
+
+// Convenience to make constructing a TouchEvent simpler.
+class TouchEventForTest : public TouchEvent {
+ public:
+ TouchEventForTest(EventType type, gfx::Point location)
+ : TouchEvent(type, location, 0, base::TimeDelta()) {}
+};
+
+} // namespace
+
+// A subclass of TouchSelectionControllerAura which adds some test functionality
+// to it.
+class TestTouchSelectionControllerAura
+ : public TouchSelectionControllerAura {
+ public:
+ TestTouchSelectionControllerAura(TouchSelectionControllerAuraClient* client)
+ : TouchSelectionControllerAura(client),
+ last_drawable_(nullptr) {
+ set_immediate_quick_menu_for_testing(true);
+ }
+
+ ~TestTouchSelectionControllerAura() override {}
+
+ TouchHandleDrawable* last_drawable() const { return last_drawable_; }
+
+ bool is_insertion_active() const {
+ return is_insertion_active_for_testing();
+ }
+
+ bool is_selection_active() const {
+ return is_selection_active_for_testing();
+ }
+
+ protected:
+ // TouchSelectionControllerAura:
+ scoped_ptr<TouchHandleDrawable> CreateDrawable() override {
+ scoped_ptr<TouchHandleDrawable> drawable =
+ TouchSelectionControllerAura::CreateDrawable();
+ last_drawable_ = drawable.get();
+ return drawable;
+ }
+
+ private:
+ TouchHandleDrawable* last_drawable_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestTouchSelectionControllerAura);
+};
+
+class TouchSelectionControllerAuraTest
+ : public aura::test::AuraTestBase,
+ public TouchSelectionControllerAuraClient {
+ public:
+ TouchSelectionControllerAuraTest() {}
+ ~TouchSelectionControllerAuraTest() override {}
+
+ protected:
+ void ChangeSelection(const gfx::PointF& start_top,
+ const gfx::PointF& start_bottom,
+ const gfx::PointF& end_top,
+ const gfx::PointF& end_bottom) {
+ SelectionBound start_bound, end_bound;
+ start_bound.set_type(SelectionBound::LEFT);
+ end_bound.set_type(SelectionBound::RIGHT);
+ start_bound.SetEdge(start_top, start_bottom);
+ end_bound.SetEdge(end_top, end_bottom);
+ start_bound.set_visible(true);
+ end_bound.set_visible(true);
+ controller_->OnSelectionBoundsUpdated(start_bound, end_bound);
+ }
+
+ void ChangeInsertion(const gfx::Point& top,
+ const gfx::Point& bottom) {
+ SelectionBound bound;
+ bound.set_type(SelectionBound::CENTER);
+ bound.SetEdge(top, bottom);
+ bound.set_visible(true);
+ controller_->OnSelectionBoundsUpdated(bound, bound);
+ }
+
+ void ClearSelection() {
+ controller_->OnSelectionBoundsUpdated(SelectionBound(), SelectionBound());
+ }
+
+ void ClearInsertion() { ClearSelection(); }
+
+ aura::Window* parent_window() const { return parent_window_.get(); }
+
+ TestTouchSelectionMenuRunner* menu_runner() const {
+ return menu_runner_.get();
+ }
+
+ TestTouchSelectionControllerAura* controller() const {
+ return controller_.get();
+ }
+
+ private:
+ // aura::test::AuraTestBase:
+ void SetUp() override {
+ AuraTestBase::SetUp();
+
+ menu_runner_.reset(new TestTouchSelectionMenuRunner());
+
+ parent_window_.reset(CreateNormalWindow(0, root_window(), nullptr));
+ parent_window_->SetBounds(gfx::Rect(0, 0, 400, 400));
+
+ controller_.reset(new TestTouchSelectionControllerAura(this));
+ }
+
+ void TearDown() override {
+ controller_.reset();
+ parent_window_.reset();
+ menu_runner_.reset();
+
+ AuraTestBase::TearDown();
+ }
+
+ // TouchSelectionControllerAuraClient:
+ void MoveCaret(const gfx::PointF& position) override {}
+
+ void MoveRangeSelectionExtent(const gfx::PointF& extent) override {}
+
+ void SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent) override {}
+
+ aura::Window* GetParentWindow() const override {
+ return parent_window_.get();
+ }
+
+ gfx::Rect GetClientBounds() const override {
+ return parent_window_->bounds();
+ }
+
+ bool IsCommandIdEnabled(int command_id) const override { return true; }
+
+ void ExecuteCommand(int command_id, int event_flags) override {}
+
+ void OpenContextMenu(const gfx::PointF& point) override {}
+
+ scoped_ptr<aura::Window> parent_window_;
+ scoped_ptr<TestTouchSelectionControllerAura> controller_;
+ scoped_ptr<TestTouchSelectionMenuRunner> menu_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerAuraTest);
+};
+
+// Tests if touch selection quick menu is shown when touch selection is
+// activated and hidden when touch selection is deactivated.
+TEST_F(TouchSelectionControllerAuraTest, QuickMenuShowHide) {
+ gfx::Point top(5, 5);
+ gfx::Point bottom(5, 15);
+
+ controller()->OnSelectionEditable(true);
+ GestureEventForTest tap(ET_GESTURE_TAP, top.x(), top.y());
+ controller()->HandleGestureEvent(&tap);
+ ChangeInsertion(top, bottom);
+ EXPECT_TRUE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+ EXPECT_TRUE(menu_runner()->is_running());
+
+ ClearInsertion();
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+ EXPECT_FALSE(menu_runner()->is_running());
+}
+
+// Tests if touch selection quick menu is hidden during a scroll.
+TEST_F(TouchSelectionControllerAuraTest, QuickMenuHiddenOnScroll) {
+ gfx::Point top(5, 5);
+ gfx::Point bottom(5, 15);
+
+ controller()->OnSelectionEditable(true);
+ GestureEventForTest tap(ET_GESTURE_TAP, top.x(), top.y());
+ controller()->HandleGestureEvent(&tap);
+ ChangeInsertion(top, bottom);
+ EXPECT_TRUE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+ EXPECT_TRUE(menu_runner()->is_running());
+
+ GestureEventForTest scroll_begin(ET_GESTURE_SCROLL_BEGIN, top.x(), top.y());
+ controller()->HandleGestureEvent(&scroll_begin);
+ EXPECT_TRUE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+ EXPECT_FALSE(menu_runner()->is_running());
+
+ GestureEventForTest scroll_end(ET_GESTURE_SCROLL_END, top.x(), top.y());
+ controller()->HandleGestureEvent(&scroll_end);
+ EXPECT_TRUE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+ EXPECT_TRUE(menu_runner()->is_running());
+
+ ClearInsertion();
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+ EXPECT_FALSE(menu_runner()->is_running());
+}
+
+// Tests if touch selection quick menu is hidden while a handle is being
+// dragged.
+TEST_F(TouchSelectionControllerAuraTest, QuickMenuHiddenOnHandleDrag) {
+ gfx::Point top(5, 5);
+ gfx::Point bottom(5, 15);
+
+ controller()->OnSelectionEditable(true);
+ GestureEventForTest tap(ET_GESTURE_TAP, top.x(), top.y());
+ controller()->HandleGestureEvent(&tap);
+ ChangeInsertion(top, bottom);
+ EXPECT_TRUE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+ EXPECT_TRUE(menu_runner()->is_running());
+
+ gfx::RectF handle_bounds = controller()->last_drawable()->GetVisibleBounds();
+ gfx::Point drag_point = gfx::ToRoundedPoint(handle_bounds.CenterPoint());
+
+ TouchEventForTest touch_pressed(ET_TOUCH_PRESSED, drag_point);
+ controller()->HandleTouchEvent(&touch_pressed);
+ EXPECT_TRUE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+ EXPECT_FALSE(menu_runner()->is_running());
+
+ TouchEventForTest touch_released(ET_TOUCH_RELEASED, drag_point);
+ controller()->HandleTouchEvent(&touch_released);
+ EXPECT_TRUE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+ EXPECT_TRUE(menu_runner()->is_running());
+
+ ClearInsertion();
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+ EXPECT_FALSE(menu_runner()->is_running());
+}
+
+// Tests if taps on selection in an editable text are handled properly.
+TEST_F(TouchSelectionControllerAuraTest, TapOnEditableSelection) {
+ gfx::Point start_top(5, 5);
+ gfx::Point start_bottom(5, 15);
+ gfx::Point middle(15, 10);
+ gfx::Point end_top(25, 5);
+ gfx::Point end_bottom(25, 15);
+
+ controller()->OnSelectionEditable(true);
+ ChangeSelection(start_top, start_bottom, end_top, end_bottom);
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+
+ // When touch selection is inactive, tapping on selection should consume the
+ // event and activate touch selection.
+ GestureEventForTest tap1(ET_GESTURE_TAP, middle.x(), middle.y());
+ controller()->HandleGestureEvent(&tap1);
+ EXPECT_TRUE(tap1.handled());
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_TRUE(controller()->is_selection_active());
+
+ // When touch selection is active, tapping on selection should leave the event
+ // unhandled, so that the event can be forwarded to the renderer.
+ GestureEventForTest tap2(ET_GESTURE_TAP, middle.x(), middle.y());
+ controller()->HandleGestureEvent(&tap2);
+ EXPECT_FALSE(tap2.handled());
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_TRUE(controller()->is_selection_active());
+
+ ClearSelection();
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+}
+
+// Tests if taps on selection in a non-editable text are handled properly.
+TEST_F(TouchSelectionControllerAuraTest, TapOnNonEditableSelection) {
+ gfx::Point start_top(5, 5);
+ gfx::Point start_bottom(5, 15);
+ gfx::Point middle(15, 10);
+ gfx::Point end_top(25, 5);
+ gfx::Point end_bottom(25, 15);
+
+ controller()->OnSelectionEditable(false);
+ ChangeSelection(start_top, start_bottom, end_top, end_bottom);
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+
+ // When touch selection is inactive, tapping on selection should consume the
+ // event and activate touch selection.
+ GestureEventForTest tap1(ET_GESTURE_TAP, middle.x(), middle.y());
+ controller()->HandleGestureEvent(&tap1);
+ EXPECT_TRUE(tap1.handled());
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_TRUE(controller()->is_selection_active());
+
+ // When touch selection is active, tapping on selection should consume the
+ // event to prevent it from being forwarded to the renderer.
+ GestureEventForTest tap2(ET_GESTURE_TAP, middle.x(), middle.y());
+ controller()->HandleGestureEvent(&tap2);
+ EXPECT_TRUE(tap2.handled());
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_TRUE(controller()->is_selection_active());
+
+ ClearSelection();
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+}
+
+// Tests if touch selection is deactivated on a key event.
+TEST_F(TouchSelectionControllerAuraTest, DeactivatedOnKeyEvent) {
+ gfx::Point top(5, 5);
+ gfx::Point bottom(5, 15);
+
+ RunAllPendingInMessageLoop();
+ controller()->OnSelectionEditable(true);
+ GestureEventForTest tap(ET_GESTURE_TAP, top.x(), top.y());
+ controller()->HandleGestureEvent(&tap);
+ ChangeInsertion(top, bottom);
+ EXPECT_TRUE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+
+ test::EventGenerator generator(root_window());
+ generator.PressKey(VKEY_A, 0);
+ RunAllPendingInMessageLoop();
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+}
+
+// Tests if touch selection is deactivated on a mouse event.
+TEST_F(TouchSelectionControllerAuraTest, DeactivatedOnMouseEvent) {
+ gfx::Point top(5, 5);
+ gfx::Point bottom(5, 15);
+
+ RunAllPendingInMessageLoop();
+ controller()->OnSelectionEditable(true);
+ GestureEventForTest tap(ET_GESTURE_TAP, top.x(), top.y());
+ controller()->HandleGestureEvent(&tap);
+ ChangeInsertion(top, bottom);
+ EXPECT_TRUE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+
+ test::EventGenerator generator(root_window());
+ generator.set_current_location(top);
+ RunAllPendingInMessageLoop();
+ generator.MoveMouseTo(bottom);
+ RunAllPendingInMessageLoop();
+ EXPECT_FALSE(controller()->is_insertion_active());
+ EXPECT_FALSE(controller()->is_selection_active());
+}
+
+} // namespace ui

Powered by Google App Engine
This is Rietveld 408576698