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

Side by Side Diff: ui/chromeos/touch_exploration_controller_unittest.cc

Issue 410783002: Corner Passthrough for Accessibility (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@side-gestures
Patch Set: Rebase off Master Created 6 years, 4 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/chromeos/touch_exploration_controller.h" 5 #include "ui/chromeos/touch_exploration_controller.h"
6 6
7 #include "base/test/simple_test_tick_clock.h" 7 #include "base/test/simple_test_tick_clock.h"
8 #include "base/time/time.h" 8 #include "base/time/time.h"
9 #include "ui/aura/client/cursor_client.h" 9 #include "ui/aura/client/cursor_client.h"
10 #include "ui/aura/test/aura_test_base.h" 10 #include "ui/aura/test/aura_test_base.h"
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 if (n <= 0) 68 if (n <= 0)
69 return 0; 69 return 0;
70 if (n == 1) 70 if (n == 1)
71 return 1; 71 return 1;
72 return n * Factorial(n - 1); 72 return n * Factorial(n - 1);
73 } 73 }
74 74
75 class MockTouchExplorationControllerDelegate 75 class MockTouchExplorationControllerDelegate
76 : public ui::TouchExplorationControllerDelegate { 76 : public ui::TouchExplorationControllerDelegate {
77 public: 77 public:
78 virtual void PlayVolumeAdjustSound() OVERRIDE { 78 virtual void SetOutputLevel(int volume) OVERRIDE {
79 volume_changes_.push_back(volume);
80 }
81 virtual void PlayVolumeAdjustEarcon() OVERRIDE {
79 ++num_times_adjust_sound_played_; 82 ++num_times_adjust_sound_played_;
80 } 83 }
81 virtual void SetOutputLevel(int volume) OVERRIDE { 84 virtual void PlayPassthroughEarcon() OVERRIDE {
82 volume_changes_.push_back(volume); 85 ++num_times_passthrough_played_;
86 }
87 virtual void PlayExitScreenEarcon() OVERRIDE {
88 ++num_times_exit_screen_played_;
89 }
90 virtual void PlayEnterScreenEarcon() OVERRIDE {
91 ++num_times_enter_screen_played_;
83 } 92 }
84 93
85 const std::vector<float> VolumeChanges() { return volume_changes_; } 94 const std::vector<float> VolumeChanges() { return volume_changes_; }
86 const size_t NumAdjustSounds() { return num_times_adjust_sound_played_; } 95 const size_t NumAdjustSounds() { return num_times_adjust_sound_played_; }
96 const size_t NumPassthroughSounds() { return num_times_passthrough_played_; }
97 const size_t NumExitScreenSounds() { return num_times_exit_screen_played_; }
98 const size_t NumEnterScreenSounds() {
99 return num_times_enter_screen_played_;
100 }
101
102 void ResetCountersToZero() {
103 num_times_adjust_sound_played_ = 0;
104 num_times_passthrough_played_ = 0;
105 num_times_exit_screen_played_ = 0;
106 num_times_enter_screen_played_ = 0;
107 }
87 108
88 private: 109 private:
89 std::vector<float> volume_changes_; 110 std::vector<float> volume_changes_;
90 size_t num_times_adjust_sound_played_ = 0; 111 size_t num_times_adjust_sound_played_ = 0;
112 size_t num_times_passthrough_played_ = 0;
113 size_t num_times_exit_screen_played_ = 0;
114 size_t num_times_enter_screen_played_ = 0;
91 }; 115 };
92 116
93 } // namespace 117 } // namespace
94 118
95 class TouchExplorationControllerTestApi { 119 class TouchExplorationControllerTestApi {
96 public: 120 public:
97 TouchExplorationControllerTestApi( 121 TouchExplorationControllerTestApi(
98 TouchExplorationController* touch_exploration_controller) { 122 TouchExplorationController* touch_exploration_controller) {
99 touch_exploration_controller_.reset(touch_exploration_controller); 123 touch_exploration_controller_.reset(touch_exploration_controller);
100 } 124 }
101 125
102 void CallTapTimerNowForTesting() { 126 void CallTapTimerNowForTesting() {
103 DCHECK(touch_exploration_controller_->tap_timer_.IsRunning()); 127 DCHECK(touch_exploration_controller_->tap_timer_.IsRunning());
104 touch_exploration_controller_->tap_timer_.Stop(); 128 touch_exploration_controller_->tap_timer_.Stop();
105 touch_exploration_controller_->OnTapTimerFired(); 129 touch_exploration_controller_->OnTapTimerFired();
106 } 130 }
107 131
132 void CallLongPressTimerNowForTesting() {
133 DCHECK(touch_exploration_controller_->long_press_timer_.IsRunning());
134 touch_exploration_controller_->long_press_timer_.Stop();
135 touch_exploration_controller_->OnLongPressTimerFired();
136 }
137
108 void CallTapTimerNowIfRunningForTesting() { 138 void CallTapTimerNowIfRunningForTesting() {
109 if (touch_exploration_controller_->tap_timer_.IsRunning()) { 139 if (touch_exploration_controller_->tap_timer_.IsRunning()) {
110 touch_exploration_controller_->tap_timer_.Stop(); 140 touch_exploration_controller_->tap_timer_.Stop();
111 touch_exploration_controller_->OnTapTimerFired(); 141 touch_exploration_controller_->OnTapTimerFired();
112 } 142 }
113 } 143 }
114 144
115 bool IsInNoFingersDownStateForTesting() const { 145 bool IsInNoFingersDownStateForTesting() const {
116 return touch_exploration_controller_->state_ == 146 return touch_exploration_controller_->state_ ==
117 touch_exploration_controller_->NO_FINGERS_DOWN; 147 touch_exploration_controller_->NO_FINGERS_DOWN;
118 } 148 }
119 149
120 bool IsInGestureInProgressStateForTesting() const { 150 bool IsInGestureInProgressStateForTesting() const {
121 return touch_exploration_controller_->state_ == 151 return touch_exploration_controller_->state_ ==
122 touch_exploration_controller_->GESTURE_IN_PROGRESS; 152 touch_exploration_controller_->GESTURE_IN_PROGRESS;
123 } 153 }
124 154
125 bool IsInSlideGestureStateForTesting() const { 155 bool IsInSlideGestureStateForTesting() const {
126 return touch_exploration_controller_->state_ == 156 return touch_exploration_controller_->state_ ==
127 touch_exploration_controller_->SLIDE_GESTURE; 157 touch_exploration_controller_->SLIDE_GESTURE;
128 } 158 }
129 159
160 bool IsInCornerPassthroughStateForTesting() const {
161 return touch_exploration_controller_->state_ ==
162 touch_exploration_controller_->CORNER_PASSTHROUGH;
163 }
164
130 gfx::Rect BoundsOfRootWindowInDIPForTesting() const { 165 gfx::Rect BoundsOfRootWindowInDIPForTesting() const {
131 return touch_exploration_controller_->root_window_->GetBoundsInScreen(); 166 return touch_exploration_controller_->root_window_->GetBoundsInScreen();
132 } 167 }
133 168
134 // VLOGs should be suppressed in tests that generate a lot of logs, 169 // VLOGs should be suppressed in tests that generate a lot of logs,
135 // for example permutations of nine touch events. 170 // for example permutations of nine touch events.
136 void SuppressVLOGsForTesting(bool suppress) { 171 void SuppressVLOGsForTesting(bool suppress) {
137 touch_exploration_controller_->VLOG_on_ = !suppress; 172 touch_exploration_controller_->VLOG_on_ = !suppress;
138 } 173 }
139 174
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 256
222 void ClearCapturedEvents() { 257 void ClearCapturedEvents() {
223 event_capturer_.Reset(); 258 event_capturer_.Reset();
224 } 259 }
225 260
226 void AdvanceSimulatedTimePastTapDelay() { 261 void AdvanceSimulatedTimePastTapDelay() {
227 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); 262 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
228 touch_exploration_controller_->CallTapTimerNowForTesting(); 263 touch_exploration_controller_->CallTapTimerNowForTesting();
229 } 264 }
230 265
266 void AdvanceSimulatedTimePastLongPressDelay() {
267 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
268 touch_exploration_controller_->CallLongPressTimerNowForTesting();
269 }
270
231 void AdvanceSimulatedTimePastPotentialTapDelay() { 271 void AdvanceSimulatedTimePastPotentialTapDelay() {
232 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); 272 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
233 touch_exploration_controller_->CallTapTimerNowIfRunningForTesting(); 273 touch_exploration_controller_->CallTapTimerNowIfRunningForTesting();
234 } 274 }
235 275
236 void SuppressVLOGs(bool suppress) { 276 void SuppressVLOGs(bool suppress) {
237 touch_exploration_controller_->SuppressVLOGsForTesting(suppress); 277 touch_exploration_controller_->SuppressVLOGsForTesting(suppress);
238 } 278 }
239 279
240 void SwitchTouchExplorationMode(bool on) { 280 void SwitchTouchExplorationMode(bool on) {
(...skipping 19 matching lines...) Expand all
260 gfx::Point second_touch_location) { 300 gfx::Point second_touch_location) {
261 SwitchTouchExplorationMode(true); 301 SwitchTouchExplorationMode(true);
262 ui::TouchEvent first_touch_press( 302 ui::TouchEvent first_touch_press(
263 ui::ET_TOUCH_PRESSED, first_touch_location, 0, Now()); 303 ui::ET_TOUCH_PRESSED, first_touch_location, 0, Now());
264 generator_->Dispatch(&first_touch_press); 304 generator_->Dispatch(&first_touch_press);
265 ui::TouchEvent second_touch_press( 305 ui::TouchEvent second_touch_press(
266 ui::ET_TOUCH_PRESSED, second_touch_location, 1, Now()); 306 ui::ET_TOUCH_PRESSED, second_touch_location, 1, Now());
267 generator_->Dispatch(&second_touch_press); 307 generator_->Dispatch(&second_touch_press);
268 } 308 }
269 309
310 // Checks that Corner Passthrough is working. Assumes that corner is the
311 // bottom left corner or the bottom right corner.
312 void AssertCornerPassthroughWorking(gfx::Point corner) {
313 ASSERT_EQ(0U, delegate_.NumPassthroughSounds());
314
315 ui::TouchEvent first_press(ui::ET_TOUCH_PRESSED, corner, 0, Now());
316 generator_->Dispatch(&first_press);
317
318 AdvanceSimulatedTimePastLongPressDelay();
319 EXPECT_FALSE(IsInGestureInProgressState());
320 EXPECT_FALSE(IsInSlideGestureState());
321 EXPECT_FALSE(IsInTouchToMouseMode());
322 EXPECT_TRUE(IsInCornerPassthroughState());
323
324 gfx::Rect window = BoundsOfRootWindowInDIP();
325 // The following events should be passed through.
326 gfx::Point passthrough(window.right() / 2, window.bottom() / 2);
327 ui::TouchEvent passthrough_press(
328 ui::ET_TOUCH_PRESSED, passthrough, 1, Now());
329 ASSERT_EQ(1U, delegate_.NumPassthroughSounds());
330 generator_->Dispatch(&passthrough_press);
331 generator_->ReleaseTouchId(1);
332 generator_->PressTouchId(1);
333 EXPECT_FALSE(IsInGestureInProgressState());
334 EXPECT_FALSE(IsInSlideGestureState());
335 EXPECT_TRUE(IsInCornerPassthroughState());
336
337 std::vector<ui::LocatedEvent*> captured_events = GetCapturedLocatedEvents();
338 ASSERT_EQ(3U, captured_events.size());
339 EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[0]->type());
340 EXPECT_EQ(ui::ET_TOUCH_RELEASED, captured_events[1]->type());
341 EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[2]->type());
342 generator_->ReleaseTouchId(1);
343 ClearCapturedEvents();
344
345 generator_->ReleaseTouchId(0);
346 captured_events = GetCapturedLocatedEvents();
347 ASSERT_EQ(0U, captured_events.size());
348 EXPECT_FALSE(IsInTouchToMouseMode());
349 EXPECT_FALSE(IsInCornerPassthroughState());
350 ClearCapturedEvents();
351 }
352
270 bool IsInTouchToMouseMode() { 353 bool IsInTouchToMouseMode() {
271 aura::client::CursorClient* cursor_client = 354 aura::client::CursorClient* cursor_client =
272 aura::client::GetCursorClient(root_window()); 355 aura::client::GetCursorClient(root_window());
273 return cursor_client && 356 return cursor_client && cursor_client->IsMouseEventsEnabled() &&
274 cursor_client->IsMouseEventsEnabled() &&
275 !cursor_client->IsCursorVisible(); 357 !cursor_client->IsCursorVisible();
276 } 358 }
277 359
278 bool IsInNoFingersDownState() { 360 bool IsInNoFingersDownState() {
279 return touch_exploration_controller_->IsInNoFingersDownStateForTesting(); 361 return touch_exploration_controller_->IsInNoFingersDownStateForTesting();
280 } 362 }
281 363
282 bool IsInGestureInProgressState() { 364 bool IsInGestureInProgressState() {
283 return touch_exploration_controller_ 365 return touch_exploration_controller_
284 ->IsInGestureInProgressStateForTesting(); 366 ->IsInGestureInProgressStateForTesting();
285 } 367 }
286 368
287 bool IsInSlideGestureState() { 369 bool IsInSlideGestureState() {
288 return touch_exploration_controller_->IsInSlideGestureStateForTesting(); 370 return touch_exploration_controller_->IsInSlideGestureStateForTesting();
289 } 371 }
290 372
373 bool IsInCornerPassthroughState() {
374 return touch_exploration_controller_
375 ->IsInCornerPassthroughStateForTesting();
376 }
377
291 gfx::Rect BoundsOfRootWindowInDIP() { 378 gfx::Rect BoundsOfRootWindowInDIP() {
292 return touch_exploration_controller_->BoundsOfRootWindowInDIPForTesting(); 379 return touch_exploration_controller_->BoundsOfRootWindowInDIPForTesting();
293 } 380 }
294 381
295 float GetMaxDistanceFromEdge() const{ 382 float GetMaxDistanceFromEdge() const {
296 return touch_exploration_controller_->GetMaxDistanceFromEdge(); 383 return touch_exploration_controller_->GetMaxDistanceFromEdge();
297 } 384 }
298 385
299 float GetSlopDistanceFromEdge() const{ 386 float GetSlopDistanceFromEdge() const{
300 return touch_exploration_controller_->GetSlopDistanceFromEdge(); 387 return touch_exploration_controller_->GetSlopDistanceFromEdge();
301 } 388 }
302 389
303 base::TimeDelta Now() { 390 base::TimeDelta Now() {
304 // This is the same as what EventTimeForNow() does, but here we do it 391 // This is the same as what EventTimeForNow() does, but here we do it
305 // with our simulated clock. 392 // with our simulated clock.
(...skipping 1327 matching lines...) Expand 10 before | Expand all | Expand 10 after
1633 EXPECT_FALSE(IsInGestureInProgressState()); 1720 EXPECT_FALSE(IsInGestureInProgressState());
1634 EXPECT_FALSE(IsInSlideGestureState()); 1721 EXPECT_FALSE(IsInSlideGestureState());
1635 EXPECT_FALSE(IsInTouchToMouseMode()); 1722 EXPECT_FALSE(IsInTouchToMouseMode());
1636 1723
1637 AdvanceSimulatedTimePastTapDelay(); 1724 AdvanceSimulatedTimePastTapDelay();
1638 EXPECT_FALSE(IsInGestureInProgressState()); 1725 EXPECT_FALSE(IsInGestureInProgressState());
1639 EXPECT_FALSE(IsInSlideGestureState()); 1726 EXPECT_FALSE(IsInSlideGestureState());
1640 EXPECT_TRUE(IsInTouchToMouseMode()); 1727 EXPECT_TRUE(IsInTouchToMouseMode());
1641 } 1728 }
1642 1729
1730 // Corner passthrough should turn on if the user first holds down on either the
1731 // right or left corner past a delay and then places a finger anywhere else on
1732 // the screen.
1733 TEST_F(TouchExplorationTest, ActivateLeftCornerPassthrough) {
1734 SwitchTouchExplorationMode(true);
1735
1736 gfx::Rect window = BoundsOfRootWindowInDIP();
1737 gfx::Point left_corner(10, window.bottom() - GetMaxDistanceFromEdge() / 2);
1738 AssertCornerPassthroughWorking(left_corner);
1739 }
1740
1741 TEST_F(TouchExplorationTest, ActivateRightCornerPassthrough) {
1742 SwitchTouchExplorationMode(true);
1743
1744 gfx::Rect window = BoundsOfRootWindowInDIP();
1745 gfx::Point right_corner(window.right() - GetMaxDistanceFromEdge() / 2,
1746 window.bottom() - GetMaxDistanceFromEdge() / 2);
1747 AssertCornerPassthroughWorking(right_corner);
1748 }
1749
1750 // Earcons should play if the user slides off the screen or enters the screen
1751 // from the edge.
1752 TEST_F(TouchExplorationTest, EnterEarconPlays) {
1753 SwitchTouchExplorationMode(true);
1754
1755 gfx::Rect window = BoundsOfRootWindowInDIP();
1756 ui::TouchEvent upper_left_corner(
1757 ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), 1, Now());
1758 ui::TouchEvent upper_right_corner(
1759 ui::ET_TOUCH_PRESSED, gfx::Point(window.right(), 0), 1, Now());
1760 ui::TouchEvent lower_left_corner(
1761 ui::ET_TOUCH_PRESSED, gfx::Point(0, window.bottom()), 1, Now());
1762 ui::TouchEvent lower_right_corner(ui::ET_TOUCH_PRESSED,
1763 gfx::Point(window.right(), window.bottom()),
1764 1,
1765 Now());
1766
1767 generator_->Dispatch(&upper_left_corner);
1768 ASSERT_EQ(1U, delegate_.NumEnterScreenSounds());
1769 generator_->ReleaseTouchId(1);
1770 delegate_.ResetCountersToZero();
1771
1772 generator_->Dispatch(&upper_right_corner);
1773 ASSERT_EQ(1U, delegate_.NumEnterScreenSounds());
1774 generator_->ReleaseTouchId(1);
1775 delegate_.ResetCountersToZero();
1776
1777 generator_->Dispatch(&lower_left_corner);
1778 ASSERT_EQ(1U, delegate_.NumEnterScreenSounds());
1779 generator_->ReleaseTouchId(1);
1780 delegate_.ResetCountersToZero();
1781
1782 generator_->Dispatch(&lower_right_corner);
1783 ASSERT_EQ(1U, delegate_.NumEnterScreenSounds());
1784 generator_->ReleaseTouchId(1);
1785 delegate_.ResetCountersToZero();
1786 }
1787
1788 TEST_F(TouchExplorationTest, ExitEarconPlays) {
1789 SwitchTouchExplorationMode(true);
1790
1791 // On the device, it cannot actually tell if the finger has left the screen or
1792 // not. If the finger has left the screen, it reads it as a release that
1793 // occurred very close to the edge of the screen even if the finger is still
1794 // technically touching the moniter. To simulate this, a release that occurs
1795 // close to the edge is dispatched.
1796 gfx::Point initial_press(100, 200);
1797 gfx::Rect window = BoundsOfRootWindowInDIP();
1798 gfx::Point upper_left_corner(0, 0);
1799 gfx::Point upper_right_corner(window.right(), 0);
1800 gfx::Point lower_left_corner(0, window.bottom());
1801 gfx::Point lower_right_corner(window.right(), window.bottom());
1802
1803 generator_->PressTouch();
1804 generator_->MoveTouch(initial_press);
1805 generator_->MoveTouch(upper_left_corner);
1806 generator_->ReleaseTouch();
1807 ASSERT_EQ(1U, delegate_.NumExitScreenSounds());
1808 delegate_.ResetCountersToZero();
1809
1810 generator_->PressTouch();
1811 generator_->MoveTouch(initial_press);
1812 generator_->MoveTouch(upper_left_corner);
1813 generator_->ReleaseTouch();
1814 ASSERT_EQ(1U, delegate_.NumExitScreenSounds());
1815 delegate_.ResetCountersToZero();
1816
1817 generator_->PressTouch();
1818 generator_->MoveTouch(initial_press);
1819 generator_->MoveTouch(upper_right_corner);
1820 generator_->ReleaseTouch();
1821 ASSERT_EQ(1U, delegate_.NumExitScreenSounds());
1822 delegate_.ResetCountersToZero();
1823
1824 generator_->PressTouch();
1825 generator_->MoveTouch(initial_press);
1826 generator_->MoveTouch(lower_left_corner);
1827 generator_->ReleaseTouch();
1828 ASSERT_EQ(1U, delegate_.NumExitScreenSounds());
1829 delegate_.ResetCountersToZero();
1830
1831 generator_->PressTouch();
1832 generator_->MoveTouch(initial_press);
1833 generator_->MoveTouch(lower_right_corner);
1834 generator_->ReleaseTouch();
1835 ASSERT_EQ(1U, delegate_.NumExitScreenSounds());
1836 delegate_.ResetCountersToZero();
1837 }
1838
1643 } // namespace ui 1839 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698