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

Unified Diff: chrome/browser/chromeos/accessibility/touch_exploration_controller_unittest.cc

Issue 240333007: wip: Second crack at implementing the touch exploration mode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding a flag to disable the touch exploration mode. Created 6 years, 8 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: chrome/browser/chromeos/accessibility/touch_exploration_controller_unittest.cc
diff --git a/chrome/browser/chromeos/accessibility/touch_exploration_controller_unittest.cc b/chrome/browser/chromeos/accessibility/touch_exploration_controller_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..23dc817a346e86611eaa7f9c434d1f65befa5940
--- /dev/null
+++ b/chrome/browser/chromeos/accessibility/touch_exploration_controller_unittest.cc
@@ -0,0 +1,447 @@
+// Copyright (c) 2014 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/chromeos/touch_exploration_controller.h"
+
+#include "ash/accessibility_delegate.h"
+#include "ash/root_window_controller.h"
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/test/root_window_controller_test_api_chromeos.h"
+#include "base/time/time.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
+#include "ui/gfx/geometry/point.h"
+
+namespace ui {
+
+// Records all mouse and touch events.
+class EventCapturer : public ui::EventHandler {
+ public:
+ EventCapturer() { Reset(); }
+ virtual ~EventCapturer() {
+ Reset();
+ }
+
+ void Reset() {
+ std::vector<ui::LocatedEvent*>::iterator it;
+ for (it = events_.begin(); it != events_.end(); ++it) {
+ delete *it;
+ }
+ events_.clear();
+ }
+
+ virtual void OnEvent(ui::Event* event) OVERRIDE {
+ ui::LocatedEvent* event_copy;
+ if (event->IsMouseEvent())
+ event_copy = new ui::MouseEvent(static_cast<ui::MouseEvent&>(*event));
+ else if (event->IsTouchEvent())
+ event_copy = new ui::TouchEvent(static_cast<ui::TouchEvent&>(*event));
+ else
+ return;
+ events_.push_back(event_copy);
+ // Stop event propagation so we don't click on random stuff that
+ // might break test assumptions.
+ event->StopPropagation();
+ // If there is a possibility that we're in an infinite loop, we should
+ // exit early with a sensible error rather than letting the test time out.
+ ASSERT_LT(events_.size(), 100u);
+ }
+ const std::vector<ui::LocatedEvent*>& captured_events() const {
+ return events_;
+ }
+
+ private:
+ std::vector<ui::LocatedEvent*> events_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventCapturer);
+};
+
+class TouchExplorationTest : public ash::test::AshTestBase {
+ public:
+ TouchExplorationTest() : root_window_(NULL) {}
+ virtual ~TouchExplorationTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ash::test::AshTestBase::SetUp();
+ root_window_ = ash::Shell::GetInstance()->GetPrimaryRootWindow();
+ ash::Shell::GetInstance()->AddPreTargetHandler(&event_capturer_);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ ash::Shell::GetInstance()->RemovePreTargetHandler(&event_capturer_);
+ SwitchTouchExplorationMode(false);
+ ash::test::AshTestBase::TearDown();
+ }
+
+ const std::vector<ui::LocatedEvent*>& GetCapturedEvents() {
+ return event_capturer_.captured_events();
+ }
+
+ void ClearCapturedEvents() {
+ event_capturer_.Reset();
+ }
+
+ protected:
+ aura::Window* root_window() {return root_window_;}
+
+ void SwitchTouchExplorationMode(bool on) {
+ ash::AccessibilityDelegate* ad =
+ ash::Shell::GetInstance()->accessibility_delegate();
+ if (on != ad->IsSpokenFeedbackEnabled())
+ ad->ToggleSpokenFeedback(ash::A11Y_NOTIFICATION_NONE);
+ ash::test::RootWindowControllerTestApi root_window_controller_test_api(
+ ash::Shell::GetPrimaryRootWindowController());
+ root_window_controller_test_api.UpdateTouchExplorationState();
+ EXPECT_EQ(on, ad->IsSpokenFeedbackEnabled());
+ }
+
+ bool IsMouseCursorVisible() {
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root_window_);
+ return cursor_client && cursor_client->IsCursorVisible();
+ }
+
+ bool IsInTouchToMouseMode() {
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root_window_);
+ return cursor_client &&
+ cursor_client->IsMouseEventsEnabled() &&
+ !cursor_client->IsCursorVisible();
+ }
+
+ private:
+ aura::Window* root_window_;
+ EventCapturer event_capturer_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchExplorationTest);
+};
+
+// Executes a number of assertions to confirm that |e1| and |e2| are touch
+// events and are equal to each other.
+void ConfirmEventsAreTouchAndEqual(ui::Event* e1, ui::Event* e2) {
+ EXPECT_TRUE(e1->IsTouchEvent());
+ EXPECT_TRUE(e2->IsTouchEvent());
+ ui::TouchEvent* touch_event1 = static_cast<ui::TouchEvent*>(e1);
+ ui::TouchEvent* touch_event2 = static_cast<ui::TouchEvent*>(e2);
+ EXPECT_EQ(touch_event1->type(), touch_event2->type());
+ EXPECT_EQ(touch_event1->location(), touch_event2->location());
+ EXPECT_EQ(touch_event1->touch_id(), touch_event2->touch_id());
+ EXPECT_EQ(touch_event1->flags(), touch_event2->flags());
+ EXPECT_EQ(touch_event1->time_stamp(), touch_event2->time_stamp());
+}
+
+// Executes a number of assertions to confirm that |e1| and |e2| are mouse
+// events and are equal to each other.
+void ConfirmEventsAreMouseAndEqual(ui::Event* e1, ui::Event* e2) {
+ EXPECT_TRUE(e1->IsMouseEvent());
+ EXPECT_TRUE(e2->IsMouseEvent());
+ ui::MouseEvent* mouse_event1 = static_cast<ui::MouseEvent*>(e1);
+ ui::MouseEvent* mouse_event2 = static_cast<ui::MouseEvent*>(e2);
+ EXPECT_EQ(mouse_event1->type(), mouse_event2->type());
+ EXPECT_EQ(mouse_event1->location(), mouse_event2->location());
+ EXPECT_EQ(mouse_event1->root_location(), mouse_event2->root_location());
+ EXPECT_EQ(mouse_event1->flags(), mouse_event2->flags());
+}
+
+// Simple test to confirm one-finger touches are transformed into mouse moves.
+TEST_F(TouchExplorationTest, OneFingerTouch) {
+ SwitchTouchExplorationMode(true);
+ gfx::Point location_start = GetEventGenerator().current_location();
+ gfx::Point location_end(11, 12);
+ gfx::Point location_mouse_move(13, 14);
+ GetEventGenerator().PressTouch();
+ EXPECT_TRUE(IsInTouchToMouseMode());
+ GetEventGenerator().MoveTouch(location_end);
+ // Confirm the actual mouse moves are unaffected.
+ ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED,
+ gfx::Point(13, 14),
+ gfx::Point(13, 14),
+ 0,
+ 0);
+ GetEventGenerator().Dispatch(&mouse_move);
+ EXPECT_TRUE(IsMouseCursorVisible());
+ GetEventGenerator().ReleaseTouch();
+
+ std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
+ std::vector<ui::LocatedEvent*>::const_iterator it;
+ int num_mouse_moves = 0;
+ for (it = captured_events.begin(); it != captured_events.end(); ++it) {
+ int type = (*it)->type();
+ // Ignore enter and exit mouse events synthesized when the mouse cursor is
+ // shown or hidden.
+ if (type == ui::ET_MOUSE_ENTERED || type == ui::ET_MOUSE_EXITED)
+ continue;
+ EXPECT_EQ((*it)->type(), ui::ET_MOUSE_MOVED);
+ if (num_mouse_moves == 0)
+ EXPECT_EQ((*it)->location(), location_start);
+ if (num_mouse_moves == 1 || num_mouse_moves == 3)
+ EXPECT_EQ((*it)->location(), location_end);
+ if (num_mouse_moves == 2)
+ ConfirmEventsAreMouseAndEqual(*it, &mouse_move);
+ if (num_mouse_moves != 2) {
+ EXPECT_TRUE((*it)->flags() & ui::EF_IS_SYNTHESIZED);
+ EXPECT_TRUE((*it)->flags() & ui::EF_FROM_TOUCH);
+ }
+ num_mouse_moves++;
+ }
+ EXPECT_EQ(num_mouse_moves, 4);
+}
+
+// Turn the touch exploration mode on in the middle of the touch gesture.
+// Confirm that events from the finger which was touching when the mode was
+// turned on don't get rewritten.
+TEST_F(TouchExplorationTest, TurnOnMidTouch) {
+ SwitchTouchExplorationMode(false);
+ GetEventGenerator().PressTouchId(1);
+ EXPECT_FALSE(IsInTouchToMouseMode());
+ ClearCapturedEvents();
+
+ // Enable touch exploration mode while the first finger is touching the
+ // screen. Ensure that subsequent events from that first finger are not
+ // affected by the touch exploration mode, while the touch events from another
+ // finger get rewritten.
+ SwitchTouchExplorationMode(true);
+ ui::TouchEvent touch_move(ui::ET_TOUCH_MOVED,
+ gfx::Point(11, 12),
+ 1,
+ ui::EventTimeForNow());
+ GetEventGenerator().Dispatch(&touch_move);
+ std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
+ EXPECT_EQ(captured_events.size(), 1u);
+ ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_move);
+ ClearCapturedEvents();
+
+ // The press from the second finger should get rewritten.
+ GetEventGenerator().PressTouchId(2);
+ EXPECT_TRUE(IsInTouchToMouseMode());
+ captured_events = GetCapturedEvents();
+ std::vector<ui::LocatedEvent*>::const_iterator it;
+ for (it = captured_events.begin(); it != captured_events.end(); ++it) {
+ if ((*it)->type() == ui::ET_MOUSE_MOVED)
+ break;
+ }
+ EXPECT_FALSE(it == captured_events.end());
+ ClearCapturedEvents();
+
+ // The release of the first finger shouldn't be affected.
+ ui::TouchEvent touch_release(ui::ET_TOUCH_RELEASED,
+ gfx::Point(11, 12),
+ 1,
+ ui::EventTimeForNow());
+ GetEventGenerator().Dispatch(&touch_release);
+ captured_events = GetCapturedEvents();
+ EXPECT_EQ(captured_events.size(), 1u);
+ ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_release);
+ ClearCapturedEvents();
+
+ // The move and release from the second finger should get rewritten.
+ GetEventGenerator().MoveTouchId(gfx::Point(13, 14), 2);
+ GetEventGenerator().ReleaseTouchId(2);
+ captured_events = GetCapturedEvents();
+ EXPECT_EQ(captured_events.size(), 2u);
+ EXPECT_EQ(captured_events[0]->type(), ui::ET_MOUSE_MOVED);
+ EXPECT_EQ(captured_events[1]->type(), ui::ET_MOUSE_MOVED);
+}
+
+TEST_F(TouchExplorationTest, TwoFingerTouch) {
+ SwitchTouchExplorationMode(true);
+ GetEventGenerator().PressTouchId(1);
+ ClearCapturedEvents();
+
+ // Confirm events from the second finger go through as is.
+ ui::TouchEvent touch_press(ui::ET_TOUCH_PRESSED,
+ gfx::Point(10, 11),
+ 2,
+ ui::EventTimeForNow());
+ GetEventGenerator().Dispatch(&touch_press);
+ std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
+ // There will be a ET_MOUSE_EXITED event synthesized when the mouse cursor is
+ // hidden - ignore it.
+ std::vector<ui::LocatedEvent*>::const_iterator it;
+ for (it = captured_events.begin(); it != captured_events.end(); ++it) {
+ if ((*it)->type() == ui::ET_TOUCH_PRESSED) {
+ ConfirmEventsAreTouchAndEqual(*it, &touch_press);
+ break;
+ }
+ }
+ EXPECT_FALSE(it == captured_events.end());
+ ClearCapturedEvents();
+ ui::TouchEvent touch_move(ui::ET_TOUCH_MOVED,
+ gfx::Point(20, 21),
+ 2,
+ ui::EventTimeForNow());
+ ui::TouchEvent touch_stationary(ui::ET_TOUCH_STATIONARY,
+ gfx::Point(20, 21),
+ 2,
+ ui::EventTimeForNow());
+ GetEventGenerator().Dispatch(&touch_move);
+ GetEventGenerator().Dispatch(&touch_stationary);
+ captured_events = GetCapturedEvents();
+ EXPECT_EQ(captured_events.size(), 2u);
+ ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_move);
+ ConfirmEventsAreTouchAndEqual(captured_events[1], &touch_stationary);
+ ClearCapturedEvents();
+
+ // Confirm mouse moves go through unaffected.
+ ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED,
+ gfx::Point(13, 14),
+ gfx::Point(13, 14),
+ 0,
+ 0);
+ GetEventGenerator().Dispatch(&mouse_move);
+ EXPECT_TRUE(IsMouseCursorVisible());
+ captured_events = GetCapturedEvents();
+ // Ignore synthesized ET_MOUSE_ENTERED/ET_MOUSE_EXITED
+ for (it = captured_events.begin(); it != captured_events.end(); ++it) {
+ if ((*it)->type() == ui::ET_MOUSE_MOVED) {
+ ConfirmEventsAreMouseAndEqual(*it, &mouse_move);
+ break;
+ }
+ }
+ EXPECT_FALSE(it == captured_events.end());
+ ClearCapturedEvents();
+
+ // Have some other fingers touch/move/release
+ GetEventGenerator().PressTouchId(3);
+ EXPECT_FALSE(IsMouseCursorVisible());
+ GetEventGenerator().PressTouchId(4);
+ GetEventGenerator().MoveTouchId(gfx::Point(30, 31), 3);
+ GetEventGenerator().StationaryTouchId(4);
+ GetEventGenerator().ReleaseTouchId(3);
+ GetEventGenerator().ReleaseTouchId(4);
+ ClearCapturedEvents();
+
+ // Events from the first finger should not go through while the second finger
+ // is touching.
+ gfx::Point touch1_location = gfx::Point(15, 16);
+ GetEventGenerator().MoveTouchId(touch1_location, 1);
+ GetEventGenerator().StationaryTouchId(1);
+ EXPECT_EQ(GetCapturedEvents().size(), 0u);
+
+ // A release of the second finger should go through, plus there should be a
+ // mouse move at |touch1_location| generated.
+ ui::TouchEvent touch_release(ui::ET_TOUCH_RELEASED,
+ gfx::Point(25, 26),
+ 2,
+ ui::EventTimeForNow());
+ GetEventGenerator().Dispatch(&touch_release);
+ captured_events = GetCapturedEvents();
+ EXPECT_GE(captured_events.size(), 2u);
+ ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_release);
+ // Ignore synthesized ET_MOUSE_ENTERED/ET_MOUSE_EXITED
+ for (it = captured_events.begin(); it != captured_events.end(); ++it) {
+ if ((*it)->type() == ui::ET_MOUSE_MOVED) {
+ EXPECT_EQ((*it)->location(), touch1_location);
+ break;
+ }
+ }
+ EXPECT_FALSE(it == captured_events.end());
+}
+
+TEST_F(TouchExplorationTest, MultiFingerTouch) {
+ SwitchTouchExplorationMode(true);
+ GetEventGenerator().PressTouchId(1);
+ GetEventGenerator().PressTouchId(2);
+ ClearCapturedEvents();
+
+ // Confirm events from other fingers go through as is.
+ ui::TouchEvent touch3_press(ui::ET_TOUCH_PRESSED,
+ gfx::Point(10, 11),
+ 3,
+ ui::EventTimeForNow());
+ ui::TouchEvent touch3_move1(ui::ET_TOUCH_MOVED,
+ gfx::Point(12, 13),
+ 3,
+ ui::EventTimeForNow());
+ ui::TouchEvent touch4_press(ui::ET_TOUCH_PRESSED,
+ gfx::Point(20, 21),
+ 4,
+ ui::EventTimeForNow());
+ ui::TouchEvent touch3_move2(ui::ET_TOUCH_MOVED,
+ gfx::Point(14, 15),
+ 3,
+ ui::EventTimeForNow());
+ ui::TouchEvent touch4_move(ui::ET_TOUCH_MOVED,
+ gfx::Point(22, 23),
+ 4,
+ ui::EventTimeForNow());
+ ui::TouchEvent touch3_release(ui::ET_TOUCH_RELEASED,
+ gfx::Point(14, 15),
+ 3,
+ ui::EventTimeForNow());
+ ui::TouchEvent touch4_release(ui::ET_TOUCH_RELEASED,
+ gfx::Point(22, 23),
+ 4,
+ ui::EventTimeForNow());
+ GetEventGenerator().Dispatch(&touch3_press);
+ GetEventGenerator().Dispatch(&touch3_move1);
+ GetEventGenerator().Dispatch(&touch4_press);
+ GetEventGenerator().Dispatch(&touch3_move2);
+ GetEventGenerator().Dispatch(&touch4_move);
+ GetEventGenerator().Dispatch(&touch3_release);
+ GetEventGenerator().Dispatch(&touch4_release);
+
+ std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
+ EXPECT_EQ(captured_events.size(), 7u);
+ ConfirmEventsAreTouchAndEqual(captured_events[0], &touch3_press);
+ ConfirmEventsAreTouchAndEqual(captured_events[1], &touch3_move1);
+ ConfirmEventsAreTouchAndEqual(captured_events[2], &touch4_press);
+ ConfirmEventsAreTouchAndEqual(captured_events[3], &touch3_move2);
+ ConfirmEventsAreTouchAndEqual(captured_events[4], &touch4_move);
+ ConfirmEventsAreTouchAndEqual(captured_events[5], &touch3_release);
+ ConfirmEventsAreTouchAndEqual(captured_events[6], &touch4_release);
+}
+
+// Test the case when there are multiple fingers on the screen and the first
+// finger is released. This should be rewritten as a release of the second
+// finger. Additionally, if the second finger is the only finger left touching,
+// we should enter a mouse move mode, and a mouse move event should be
+// dispatched.
+TEST_F(TouchExplorationTest, FirstFingerLifted) {
+ SwitchTouchExplorationMode(true);
+ GetEventGenerator().PressTouchId(1);
+ GetEventGenerator().PressTouchId(2);
+ gfx::Point touch2_location(10, 11);
+ GetEventGenerator().MoveTouchId(touch2_location, 2);
+ GetEventGenerator().PressTouchId(3);
+ gfx::Point touch3_location(20, 21);
+ GetEventGenerator().MoveTouchId(touch3_location, 3);
+ ClearCapturedEvents();
+
+ // Release of finger 1 should be rewritten as a release of finger 2.
+ GetEventGenerator().ReleaseTouchId(1);
+ EXPECT_FALSE(IsInTouchToMouseMode());
+ std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
+ EXPECT_EQ(captured_events.size(), 1u);
+ EXPECT_EQ(captured_events[0]->type(), ui::ET_TOUCH_RELEASED);
+ ui::TouchEvent* touch_event =
+ static_cast<ui::TouchEvent*>(captured_events[0]);
+ EXPECT_EQ(touch_event->touch_id(), 2);
+ EXPECT_EQ(touch_event->location(), touch2_location);
+ ClearCapturedEvents();
+
+ // Release of finger 2 should be rewritten as a release of finger 3, plus
+ // we should enter the mouse move mode and a mouse move event should be
+ // dispatched.
+ GetEventGenerator().ReleaseTouchId(2);
+ EXPECT_TRUE(IsInTouchToMouseMode());
+ captured_events = GetCapturedEvents();
+ EXPECT_GE(captured_events.size(), 2u);
+ EXPECT_EQ(captured_events[0]->type(), ui::ET_TOUCH_RELEASED);
+ touch_event = static_cast<ui::TouchEvent*>(captured_events[0]);
+ EXPECT_EQ(touch_event->touch_id(), 3);
+ EXPECT_EQ(touch_event->location(), touch3_location);
+ std::vector<ui::LocatedEvent*>::const_iterator it;
+ for (it = captured_events.begin(); it != captured_events.end(); ++it) {
+ if ((*it)->type() == ui::ET_MOUSE_MOVED) {
+ EXPECT_EQ((*it)->location(), touch3_location);
+ break;
+ }
+ }
+ EXPECT_FALSE(it == captured_events.end());
+}
+
+} // namespace ui
« no previous file with comments | « chrome/browser/chromeos/accessibility/touch_exploration_controller_browsertest.cc ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698