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" |
11 #include "ui/aura/test/event_generator.h" | 11 #include "ui/aura/test/event_generator.h" |
12 #include "ui/aura/test/test_cursor_client.h" | 12 #include "ui/aura/test/test_cursor_client.h" |
13 #include "ui/aura/window.h" | 13 #include "ui/aura/window.h" |
14 #include "ui/events/event.h" | 14 #include "ui/events/event.h" |
15 #include "ui/events/event_utils.h" | 15 #include "ui/events/event_utils.h" |
16 #include "ui/events/gestures/gesture_provider_aura.h" | 16 #include "ui/events/gestures/gesture_provider_aura.h" |
| 17 #include "ui/events/test/events_test_utils.h" |
17 #include "ui/gfx/geometry/point.h" | 18 #include "ui/gfx/geometry/point.h" |
18 #include "ui/gl/gl_implementation.h" | 19 #include "ui/gl/gl_implementation.h" |
19 #include "ui/gl/gl_surface.h" | 20 #include "ui/gl/gl_surface.h" |
20 | 21 |
21 namespace ui { | 22 namespace ui { |
22 | 23 |
23 namespace { | 24 namespace { |
24 // Records all mouse, touch, gesture, and key events. | 25 // Records all mouse, touch, gesture, and key events. |
25 class EventCapturer : public ui::EventHandler { | 26 class EventCapturer : public ui::EventHandler { |
26 public: | 27 public: |
(...skipping 28 matching lines...) Expand all Loading... |
55 } | 56 } |
56 | 57 |
57 const ScopedVector<ui::Event>& captured_events() const { return events_; } | 58 const ScopedVector<ui::Event>& captured_events() const { return events_; } |
58 | 59 |
59 private: | 60 private: |
60 ScopedVector<ui::Event> events_; | 61 ScopedVector<ui::Event> events_; |
61 | 62 |
62 DISALLOW_COPY_AND_ASSIGN(EventCapturer); | 63 DISALLOW_COPY_AND_ASSIGN(EventCapturer); |
63 }; | 64 }; |
64 | 65 |
| 66 int Factorial(int n) { |
| 67 if (n <= 0) |
| 68 return 0; |
| 69 if (n == 1) |
| 70 return 1; |
| 71 return n * Factorial(n - 1); |
| 72 } |
| 73 |
65 } // namespace | 74 } // namespace |
66 | 75 |
67 class TouchExplorationTest : public aura::test::AuraTestBase { | 76 class TouchExplorationTest : public aura::test::AuraTestBase { |
68 public: | 77 public: |
69 TouchExplorationTest() : simulated_clock_(new base::SimpleTestTickClock()) { | 78 TouchExplorationTest() : simulated_clock_(new base::SimpleTestTickClock()) { |
70 // Tests fail if time is ever 0. | 79 // Tests fail if time is ever 0. |
71 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); | 80 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); |
72 } | 81 } |
73 virtual ~TouchExplorationTest() {} | 82 virtual ~TouchExplorationTest() {} |
74 | 83 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 | 143 |
135 void ClearCapturedEvents() { | 144 void ClearCapturedEvents() { |
136 event_capturer_.Reset(); | 145 event_capturer_.Reset(); |
137 } | 146 } |
138 | 147 |
139 void AdvanceSimulatedTimePastTapDelay() { | 148 void AdvanceSimulatedTimePastTapDelay() { |
140 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); | 149 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); |
141 touch_exploration_controller_->CallTapTimerNowForTesting(); | 150 touch_exploration_controller_->CallTapTimerNowForTesting(); |
142 } | 151 } |
143 | 152 |
| 153 void AdvanceSimulatedTimePastPotentialTapDelay() { |
| 154 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); |
| 155 touch_exploration_controller_->CallTapTimerNowIfRunningForTesting(); |
| 156 } |
| 157 |
| 158 void SuppressVLOGs(bool suppress) { |
| 159 touch_exploration_controller_->SuppressVLOGsForTesting(suppress); |
| 160 } |
| 161 |
144 void SwitchTouchExplorationMode(bool on) { | 162 void SwitchTouchExplorationMode(bool on) { |
145 if (!on && touch_exploration_controller_.get()) { | 163 if (!on && touch_exploration_controller_.get()) { |
146 touch_exploration_controller_.reset(); | 164 touch_exploration_controller_.reset(); |
147 } else if (on && !touch_exploration_controller_.get()) { | 165 } else if (on && !touch_exploration_controller_.get()) { |
148 touch_exploration_controller_.reset( | 166 touch_exploration_controller_.reset( |
149 new ui::TouchExplorationController(root_window())); | 167 new ui::TouchExplorationController(root_window())); |
150 touch_exploration_controller_->SetEventHandlerForTesting( | 168 touch_exploration_controller_->SetEventHandlerForTesting( |
151 &event_capturer_); | 169 &event_capturer_); |
152 cursor_client()->ShowCursor(); | 170 cursor_client()->ShowCursor(); |
153 cursor_client()->DisableMouseEvents(); | 171 cursor_client()->DisableMouseEvents(); |
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1132 | 1150 |
1133 // The swipe registered and sent the appropriate key events. | 1151 // The swipe registered and sent the appropriate key events. |
1134 AssertDirectionalNavigationEvents(captured_events, direction); | 1152 AssertDirectionalNavigationEvents(captured_events, direction); |
1135 EXPECT_TRUE(IsInNoFingersDownState()); | 1153 EXPECT_TRUE(IsInNoFingersDownState()); |
1136 EXPECT_FALSE(IsInTouchToMouseMode()); | 1154 EXPECT_FALSE(IsInTouchToMouseMode()); |
1137 EXPECT_FALSE(IsInGestureInProgressState()); | 1155 EXPECT_FALSE(IsInGestureInProgressState()); |
1138 ClearCapturedEvents(); | 1156 ClearCapturedEvents(); |
1139 } | 1157 } |
1140 } | 1158 } |
1141 | 1159 |
| 1160 // Since there are so many permutations, this test is too slow in debug |
| 1161 // mode, so it will only be run in release mode. |
| 1162 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) |
| 1163 #define MAYBE_AllFingerPermutations AllFingerPermutations |
| 1164 #else |
| 1165 #define MAYBE_AllFingerPermutations DISABLED_AllFingerPermutations |
| 1166 #endif |
| 1167 |
| 1168 TEST_F(TouchExplorationTest, MAYBE_AllFingerPermutations) { |
| 1169 SwitchTouchExplorationMode(true); |
| 1170 SuppressVLOGs(true); |
| 1171 // We will test all permutations of events from three different fingers |
| 1172 // to ensure that we return to NO_FINGERS_DOWN when fingers have been |
| 1173 // released. |
| 1174 ScopedVector<ui::TouchEvent> all_events; |
| 1175 for (int touch_id = 0; touch_id < 3; touch_id++){ |
| 1176 int x = 10*touch_id + 1; |
| 1177 int y = 10*touch_id + 2; |
| 1178 all_events.push_back(new TouchEvent( |
| 1179 ui::ET_TOUCH_PRESSED, gfx::Point(x++, y++), touch_id, Now())); |
| 1180 all_events.push_back(new TouchEvent( |
| 1181 ui::ET_TOUCH_MOVED, gfx::Point(x++, y++), touch_id, Now())); |
| 1182 all_events.push_back(new TouchEvent( |
| 1183 ui::ET_TOUCH_RELEASED, gfx::Point(x, y), touch_id, Now())); |
| 1184 } |
| 1185 |
| 1186 // I'm going to explain this algorithm, and use an example in parentheses. |
| 1187 // The example will be all permutations of a b c d. |
| 1188 // There are four letters and 4! = 24 permutations. |
| 1189 const int num_events = all_events.size(); |
| 1190 const int num_permutations = Factorial(num_events); |
| 1191 |
| 1192 for (int p = 0; p < num_permutations; p++) { |
| 1193 std::vector<ui::TouchEvent*> queued_events = all_events.get(); |
| 1194 std::vector<bool> fingers_pressed(3, false); |
| 1195 |
| 1196 int current_num_permutations = num_permutations; |
| 1197 for (int events_left = num_events; events_left > 0; events_left--) { |
| 1198 // |p| indexes to each permutation when there are num_permutations |
| 1199 // permutations. (e.g. 0 is abcd, 1 is abdc, 2 is acbd, 3 is acdb...) |
| 1200 // But how do we find the index for the current number of permutations? |
| 1201 // To find the permutation within the part of the sequence we're |
| 1202 // currently looking at, we need a number between 0 and |
| 1203 // |current_num_permutations| - 1. |
| 1204 // (e.g. if we already chose the first letter, there are 3! = 6 |
| 1205 // options left, so we do p % 6. So |current_permutation| would go |
| 1206 // from 0 to 5 and then reset to 0 again, for all combinations of |
| 1207 // whichever three letters are remaining, as we loop through the |
| 1208 // permutations) |
| 1209 int current_permutation = p % current_num_permutations; |
| 1210 |
| 1211 // Since this is is the total number of permutations starting with |
| 1212 // this event and including future events, there could be multiple |
| 1213 // values of current_permutation that will generate the same event |
| 1214 // in this iteration. |
| 1215 // (e.g. If we chose 'a' but have b c d to choose from, we choose b when |
| 1216 // |current_permutation| = 0, 1 and c when |current_permutation| = 2, 3. |
| 1217 // Note that each letter gets two numbers, which is the next |
| 1218 // current_num_permutations, 2! for the two letters left.) |
| 1219 |
| 1220 // Branching out from the first event, there are num_permutations |
| 1221 // permutations, and each value of |p| is associated with one of these |
| 1222 // permutations. However, once the first event is chosen, there |
| 1223 // are now |num_events| - 1 events left, so the number of permutations |
| 1224 // for the rest of the events changes, and will always be equal to |
| 1225 // the factorial of the events_left. |
| 1226 // (e.g. There are 3! = 6 permutations that start with 'a', so if we |
| 1227 // start with 'a' there will be 6 ways to then choose from b c d.) |
| 1228 // So we now set-up for the next iteration by setting |
| 1229 // current_num_permutations to the factorial of the next number of |
| 1230 // events left. |
| 1231 current_num_permutations /= events_left; |
| 1232 |
| 1233 // To figure out what current event we want to choose, we integer |
| 1234 // divide the current permutation by the next current_num_permutations. |
| 1235 // (e.g. If there are 4 letters a b c d and 24 permutations, we divide |
| 1236 // by 24/4 = 6. Values 0 to 5 when divided by 6 equals 0, so the first |
| 1237 // 6 permutations start with 'a', and the last 6 will start with 'd'. |
| 1238 // Note that there are 6 that start with 'a' because there are 6 |
| 1239 // permutations for the next three letters that follow 'a'.) |
| 1240 int index = current_permutation / current_num_permutations; |
| 1241 |
| 1242 ui::TouchEvent* next_dispatch = queued_events[index]; |
| 1243 ASSERT_TRUE(next_dispatch != NULL); |
| 1244 |
| 1245 // |next_dispatch| has to be put in this container so that its time |
| 1246 // stamp can be changed to this point in the test, when it is being |
| 1247 // dispatched.. |
| 1248 EventTestApi test_dispatch(next_dispatch); |
| 1249 test_dispatch.set_time_stamp(Now()); |
| 1250 generator_->Dispatch(next_dispatch); |
| 1251 queued_events.erase(queued_events.begin() + index); |
| 1252 |
| 1253 // Keep track of what fingers have been pressed, to release |
| 1254 // only those fingers at the end, so the check for being in |
| 1255 // no fingers down can be accurate. |
| 1256 if (next_dispatch->type() == ET_TOUCH_PRESSED) { |
| 1257 fingers_pressed[next_dispatch->touch_id()] = true; |
| 1258 } else if (next_dispatch->type() == ET_TOUCH_RELEASED) { |
| 1259 fingers_pressed[next_dispatch->touch_id()] = false; |
| 1260 } |
| 1261 } |
| 1262 ASSERT_EQ(queued_events.size(), 0u); |
| 1263 |
| 1264 // Release fingers recorded as pressed. |
| 1265 for(int j = 0; j < int(fingers_pressed.size()); j++){ |
| 1266 if (fingers_pressed[j] == true) { |
| 1267 generator_->ReleaseTouchId(j); |
| 1268 fingers_pressed[j] = false; |
| 1269 } |
| 1270 } |
| 1271 AdvanceSimulatedTimePastPotentialTapDelay(); |
| 1272 EXPECT_TRUE(IsInNoFingersDownState()); |
| 1273 ClearCapturedEvents(); |
| 1274 } |
| 1275 } |
| 1276 |
1142 // With the simple swipe gestures, if additional fingers are added, then the | 1277 // With the simple swipe gestures, if additional fingers are added, then the |
1143 // state should change to passthrough. | 1278 // state should change to passthrough. |
1144 TEST_F(TouchExplorationTest, FromGestureToPassthrough) { | 1279 TEST_F(TouchExplorationTest, FromGestureToPassthrough) { |
1145 SwitchTouchExplorationMode(true); | 1280 SwitchTouchExplorationMode(true); |
1146 EXPECT_FALSE(IsInTouchToMouseMode()); | 1281 EXPECT_FALSE(IsInTouchToMouseMode()); |
1147 EXPECT_FALSE(IsInGestureInProgressState()); | 1282 EXPECT_FALSE(IsInGestureInProgressState()); |
1148 | 1283 |
1149 float distance = gesture_detector_config_.touch_slop + 1; | 1284 float distance = gesture_detector_config_.touch_slop + 1; |
1150 ui::TouchEvent first_press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 1), 0, Now()); | 1285 ui::TouchEvent first_press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 1), 0, Now()); |
1151 generator_->Dispatch(&first_press); | 1286 generator_->Dispatch(&first_press); |
(...skipping 20 matching lines...) Expand all Loading... |
1172 // The rest of the events should occur in passthrough. | 1307 // The rest of the events should occur in passthrough. |
1173 generator_->ReleaseTouchId(0); | 1308 generator_->ReleaseTouchId(0); |
1174 ASSERT_EQ(1U, captured_events.size()); | 1309 ASSERT_EQ(1U, captured_events.size()); |
1175 EXPECT_EQ(ui::ET_TOUCH_RELEASED, captured_events[0]->type()); | 1310 EXPECT_EQ(ui::ET_TOUCH_RELEASED, captured_events[0]->type()); |
1176 ClearCapturedEvents(); | 1311 ClearCapturedEvents(); |
1177 generator_->ReleaseTouchId(1); | 1312 generator_->ReleaseTouchId(1); |
1178 ASSERT_EQ(0U, captured_events.size()); | 1313 ASSERT_EQ(0U, captured_events.size()); |
1179 } | 1314 } |
1180 | 1315 |
1181 } // namespace ui | 1316 } // namespace ui |
OLD | NEW |