| 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
|
|
|