OLD | NEW |
---|---|
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 Loading... | |
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 void SetEventHandlerForTesting( | 145 void SetEventHandlerForTesting( |
116 ui::EventHandler* event_handler_for_testing) { | 146 ui::EventHandler* event_handler_for_testing) { |
117 touch_exploration_controller_->event_handler_for_testing_ = | 147 touch_exploration_controller_->event_handler_for_testing_ = |
118 event_handler_for_testing; | 148 event_handler_for_testing; |
119 } | 149 } |
120 | 150 |
121 bool IsInNoFingersDownStateForTesting() const { | 151 bool IsInNoFingersDownStateForTesting() const { |
122 return touch_exploration_controller_->state_ == | 152 return touch_exploration_controller_->state_ == |
123 touch_exploration_controller_->NO_FINGERS_DOWN; | 153 touch_exploration_controller_->NO_FINGERS_DOWN; |
124 } | 154 } |
125 | 155 |
126 bool IsInGestureInProgressStateForTesting() const { | 156 bool IsInGestureInProgressStateForTesting() const { |
127 return touch_exploration_controller_->state_ == | 157 return touch_exploration_controller_->state_ == |
128 touch_exploration_controller_->GESTURE_IN_PROGRESS; | 158 touch_exploration_controller_->GESTURE_IN_PROGRESS; |
129 } | 159 } |
130 | 160 |
131 bool IsInSlideGestureStateForTesting() const { | 161 bool IsInSlideGestureStateForTesting() const { |
132 return touch_exploration_controller_->state_ == | 162 return touch_exploration_controller_->state_ == |
133 touch_exploration_controller_->SLIDE_GESTURE; | 163 touch_exploration_controller_->SLIDE_GESTURE; |
134 } | 164 } |
135 | 165 |
166 bool IsInCornerPassthroughStateForTesting() const { | |
167 return touch_exploration_controller_->state_ == | |
168 touch_exploration_controller_->CORNER_PASSTHROUGH; | |
169 } | |
170 | |
136 gfx::Rect BoundsOfRootWindowInDIPForTesting() const { | 171 gfx::Rect BoundsOfRootWindowInDIPForTesting() const { |
137 return touch_exploration_controller_->root_window_->GetBoundsInScreen(); | 172 return touch_exploration_controller_->root_window_->GetBoundsInScreen(); |
138 } | 173 } |
139 | 174 |
140 // VLOGs should be suppressed in tests that generate a lot of logs, | 175 // VLOGs should be suppressed in tests that generate a lot of logs, |
141 // for example permutations of nine touch events. | 176 // for example permutations of nine touch events. |
142 void SuppressVLOGsForTesting(bool suppress) { | 177 void SuppressVLOGsForTesting(bool suppress) { |
143 touch_exploration_controller_->VLOG_on_ = !suppress; | 178 touch_exploration_controller_->VLOG_on_ = !suppress; |
144 } | 179 } |
145 | 180 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 | 262 |
228 void ClearCapturedEvents() { | 263 void ClearCapturedEvents() { |
229 event_capturer_.Reset(); | 264 event_capturer_.Reset(); |
230 } | 265 } |
231 | 266 |
232 void AdvanceSimulatedTimePastTapDelay() { | 267 void AdvanceSimulatedTimePastTapDelay() { |
233 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); | 268 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); |
234 touch_exploration_controller_->CallTapTimerNowForTesting(); | 269 touch_exploration_controller_->CallTapTimerNowForTesting(); |
235 } | 270 } |
236 | 271 |
272 void AdvanceSimulatedTimePastLongPressDelay() { | |
273 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); | |
274 touch_exploration_controller_->CallLongPressTimerNowForTesting(); | |
275 } | |
276 | |
237 void AdvanceSimulatedTimePastPotentialTapDelay() { | 277 void AdvanceSimulatedTimePastPotentialTapDelay() { |
238 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); | 278 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); |
239 touch_exploration_controller_->CallTapTimerNowIfRunningForTesting(); | 279 touch_exploration_controller_->CallTapTimerNowIfRunningForTesting(); |
240 } | 280 } |
241 | 281 |
242 void SuppressVLOGs(bool suppress) { | 282 void SuppressVLOGs(bool suppress) { |
243 touch_exploration_controller_->SuppressVLOGsForTesting(suppress); | 283 touch_exploration_controller_->SuppressVLOGsForTesting(suppress); |
244 } | 284 } |
245 | 285 |
246 void SwitchTouchExplorationMode(bool on) { | 286 void SwitchTouchExplorationMode(bool on) { |
(...skipping 21 matching lines...) Expand all Loading... | |
268 gfx::Point second_touch_location) { | 308 gfx::Point second_touch_location) { |
269 SwitchTouchExplorationMode(true); | 309 SwitchTouchExplorationMode(true); |
270 ui::TouchEvent first_touch_press( | 310 ui::TouchEvent first_touch_press( |
271 ui::ET_TOUCH_PRESSED, first_touch_location, 0, Now()); | 311 ui::ET_TOUCH_PRESSED, first_touch_location, 0, Now()); |
272 generator_->Dispatch(&first_touch_press); | 312 generator_->Dispatch(&first_touch_press); |
273 ui::TouchEvent second_touch_press( | 313 ui::TouchEvent second_touch_press( |
274 ui::ET_TOUCH_PRESSED, second_touch_location, 1, Now()); | 314 ui::ET_TOUCH_PRESSED, second_touch_location, 1, Now()); |
275 generator_->Dispatch(&second_touch_press); | 315 generator_->Dispatch(&second_touch_press); |
276 } | 316 } |
277 | 317 |
318 // Checks that Corner Passthrough is working. Assumes that corner is the | |
319 // bottom left corner or the bottom right corner. | |
320 void AssertCornerPassthroughWorking(gfx::Point corner) { | |
321 ASSERT_EQ(0U, delegate_.NumPassthroughSounds()); | |
322 | |
323 ui::TouchEvent first_press(ui::ET_TOUCH_PRESSED, corner, 0, Now()); | |
324 generator_->Dispatch(&first_press); | |
325 | |
326 AdvanceSimulatedTimePastLongPressDelay(); | |
327 EXPECT_FALSE(IsInGestureInProgressState()); | |
328 EXPECT_FALSE(IsInSlideGestureState()); | |
329 EXPECT_FALSE(IsInTouchToMouseMode()); | |
330 EXPECT_TRUE(IsInCornerPassthroughState()); | |
331 | |
332 gfx::Rect window = BoundsOfRootWindowInDIP(); | |
333 // The following events should be passed through. | |
334 gfx::Point passthrough(window.right() / 2, window.bottom() / 2); | |
335 ui::TouchEvent passthrough_press( | |
336 ui::ET_TOUCH_PRESSED, passthrough, 1, Now()); | |
337 ASSERT_EQ(1U, delegate_.NumPassthroughSounds()); | |
338 generator_->Dispatch(&passthrough_press); | |
339 generator_->ReleaseTouchId(1); | |
340 generator_->PressTouchId(1); | |
341 EXPECT_FALSE(IsInGestureInProgressState()); | |
342 EXPECT_FALSE(IsInSlideGestureState()); | |
343 EXPECT_TRUE(IsInCornerPassthroughState()); | |
344 | |
345 std::vector<ui::LocatedEvent*> captured_events = GetCapturedLocatedEvents(); | |
346 ASSERT_EQ(3U, captured_events.size()); | |
347 EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[0]->type()); | |
348 EXPECT_EQ(ui::ET_TOUCH_RELEASED, captured_events[1]->type()); | |
349 EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[2]->type()); | |
350 generator_->ReleaseTouchId(1); | |
351 ClearCapturedEvents(); | |
352 | |
353 generator_->ReleaseTouchId(0); | |
354 captured_events = GetCapturedLocatedEvents(); | |
355 ASSERT_EQ(0U, captured_events.size()); | |
356 EXPECT_FALSE(IsInTouchToMouseMode()); | |
357 EXPECT_FALSE(IsInCornerPassthroughState()); | |
358 ClearCapturedEvents(); | |
359 } | |
360 | |
278 bool IsInTouchToMouseMode() { | 361 bool IsInTouchToMouseMode() { |
279 aura::client::CursorClient* cursor_client = | 362 aura::client::CursorClient* cursor_client = |
280 aura::client::GetCursorClient(root_window()); | 363 aura::client::GetCursorClient(root_window()); |
281 return cursor_client && | 364 return cursor_client && cursor_client->IsMouseEventsEnabled() && |
282 cursor_client->IsMouseEventsEnabled() && | |
283 !cursor_client->IsCursorVisible(); | 365 !cursor_client->IsCursorVisible(); |
284 } | 366 } |
285 | 367 |
286 bool IsInNoFingersDownState() { | 368 bool IsInNoFingersDownState() { |
287 return touch_exploration_controller_->IsInNoFingersDownStateForTesting(); | 369 return touch_exploration_controller_->IsInNoFingersDownStateForTesting(); |
288 } | 370 } |
289 | 371 |
290 bool IsInGestureInProgressState() { | 372 bool IsInGestureInProgressState() { |
291 return touch_exploration_controller_ | 373 return touch_exploration_controller_ |
292 ->IsInGestureInProgressStateForTesting(); | 374 ->IsInGestureInProgressStateForTesting(); |
293 } | 375 } |
294 | 376 |
295 bool IsInSlideGestureState() { | 377 bool IsInSlideGestureState() { |
296 return touch_exploration_controller_->IsInSlideGestureStateForTesting(); | 378 return touch_exploration_controller_->IsInSlideGestureStateForTesting(); |
297 } | 379 } |
298 | 380 |
381 bool IsInCornerPassthroughState() { | |
382 return touch_exploration_controller_ | |
383 ->IsInCornerPassthroughStateForTesting(); | |
384 } | |
385 | |
299 gfx::Rect BoundsOfRootWindowInDIP() { | 386 gfx::Rect BoundsOfRootWindowInDIP() { |
300 return touch_exploration_controller_->BoundsOfRootWindowInDIPForTesting(); | 387 return touch_exploration_controller_->BoundsOfRootWindowInDIPForTesting(); |
301 } | 388 } |
302 | 389 |
303 float GetMaxDistanceFromEdge() const{ | 390 float GetMaxDistanceFromEdge() const { |
304 return touch_exploration_controller_->GetMaxDistanceFromEdge(); | 391 return touch_exploration_controller_->GetMaxDistanceFromEdge(); |
305 } | 392 } |
306 | 393 |
307 float GetSlopDistanceFromEdge() const{ | 394 float GetSlopDistanceFromEdge() const{ |
308 return touch_exploration_controller_->GetSlopDistanceFromEdge(); | 395 return touch_exploration_controller_->GetSlopDistanceFromEdge(); |
309 } | 396 } |
310 | 397 |
311 base::TimeDelta Now() { | 398 base::TimeDelta Now() { |
312 // This is the same as what EventTimeForNow() does, but here we do it | 399 // This is the same as what EventTimeForNow() does, but here we do it |
313 // with our simulated clock. | 400 // with our simulated clock. |
(...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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( | |
aboxhall
2014/07/28 22:41:44
Suggestion (similarly for ExitEarconPlays test): p
| |
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 |
OLD | NEW |