Chromium Code Reviews| 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/test/events_test_utils.h" | |
| 16 #include "ui/gfx/geometry/point.h" | 17 #include "ui/gfx/geometry/point.h" |
| 17 #include "ui/gl/gl_implementation.h" | 18 #include "ui/gl/gl_implementation.h" |
| 18 #include "ui/gl/gl_surface.h" | 19 #include "ui/gl/gl_surface.h" |
| 19 | 20 |
| 20 namespace ui { | 21 namespace ui { |
| 21 | 22 |
| 22 namespace { | 23 namespace { |
| 23 // Records all mouse and touch events. | 24 // Records all mouse and touch events. |
| 24 class EventCapturer : public ui::EventHandler { | 25 class EventCapturer : public ui::EventHandler { |
| 25 public: | 26 public: |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 50 const ScopedVector<ui::LocatedEvent>& captured_events() const { | 51 const ScopedVector<ui::LocatedEvent>& captured_events() const { |
| 51 return events_; | 52 return events_; |
| 52 } | 53 } |
| 53 | 54 |
| 54 private: | 55 private: |
| 55 ScopedVector<ui::LocatedEvent> events_; | 56 ScopedVector<ui::LocatedEvent> events_; |
| 56 | 57 |
| 57 DISALLOW_COPY_AND_ASSIGN(EventCapturer); | 58 DISALLOW_COPY_AND_ASSIGN(EventCapturer); |
| 58 }; | 59 }; |
| 59 | 60 |
| 61 int Factorial(int n) { | |
| 62 if (n <= 0) | |
| 63 return 0; | |
| 64 if (n == 1) | |
| 65 return 1; | |
| 66 if (n == 2) | |
| 67 return 2; | |
| 68 return n * Factorial(n - 1); | |
| 69 } | |
| 70 | |
| 60 } // namespace | 71 } // namespace |
| 61 | 72 |
| 62 class TouchExplorationTest : public aura::test::AuraTestBase { | 73 class TouchExplorationTest : public aura::test::AuraTestBase { |
| 63 public: | 74 public: |
| 64 TouchExplorationTest() | 75 TouchExplorationTest() |
| 65 : simulated_clock_(new base::SimpleTestTickClock()) {} | 76 : simulated_clock_(new base::SimpleTestTickClock()) {} |
| 66 virtual ~TouchExplorationTest() {} | 77 virtual ~TouchExplorationTest() {} |
| 67 | 78 |
| 68 virtual void SetUp() OVERRIDE { | 79 virtual void SetUp() OVERRIDE { |
| 69 if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) | 80 if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 941 EXPECT_EQ(first_touch_location, captured_events[0]->location()); | 952 EXPECT_EQ(first_touch_location, captured_events[0]->location()); |
| 942 ClearCapturedEvents(); | 953 ClearCapturedEvents(); |
| 943 | 954 |
| 944 ui::TouchEvent first_touch_release( | 955 ui::TouchEvent first_touch_release( |
| 945 ui::ET_TOUCH_RELEASED, first_touch_location, 0, Now()); | 956 ui::ET_TOUCH_RELEASED, first_touch_location, 0, Now()); |
| 946 generator_->Dispatch(&first_touch_release); | 957 generator_->Dispatch(&first_touch_release); |
| 947 ASSERT_EQ(captured_events.size(), 1u); | 958 ASSERT_EQ(captured_events.size(), 1u); |
| 948 EXPECT_TRUE(IsInNoFingersDownState()); | 959 EXPECT_TRUE(IsInNoFingersDownState()); |
| 949 } | 960 } |
| 950 | 961 |
| 962 TEST_F(TouchExplorationTest, AllFingerPermutations) { | |
| 963 SwitchTouchExplorationMode(true); | |
| 964 | |
| 965 // We will test all permutations of events from three different fingers | |
| 966 // to ensure that we return to NO_FINGERS_DOWN when fingers have been | |
| 967 // released. | |
| 968 ScopedVector<ui::TouchEvent> all_events; | |
| 969 for (int touch_id = 0; touch_id < 3; touch_id++){ | |
| 970 all_events.push_back( | |
| 971 new TouchEvent(ui::ET_TOUCH_PRESSED, | |
| 972 gfx::Point(10 * touch_id + 1, 10 * touch_id + 2), | |
|
aboxhall
2014/06/27 22:37:26
Suggestion: you could just have x and y values tha
evy
2014/06/30 17:33:08
Done.
| |
| 973 touch_id, | |
| 974 Now())); | |
| 975 all_events.push_back( | |
| 976 new TouchEvent(ui::ET_TOUCH_MOVED, | |
| 977 gfx::Point(10 * touch_id + 3, 10 * touch_id + 4), | |
| 978 touch_id, | |
| 979 Now())); | |
| 980 all_events.push_back( | |
| 981 new TouchEvent(ui::ET_TOUCH_RELEASED, | |
| 982 gfx::Point(10 * touch_id + 5, 10 * touch_id + 6), | |
| 983 touch_id, | |
| 984 Now())); | |
| 985 } | |
| 986 const int num_events = all_events.size(); | |
| 987 const int num_permutations = Factorial(num_events); | |
| 988 | |
| 989 for (int p = 0; p < num_permutations; p++) { | |
| 990 std::vector<ui::TouchEvent*> queued_events = all_events.get(); | |
| 991 std::vector<bool> fingers_pressed(3, false); | |
| 992 // current_factorial starts at factorial(num_events - 1) | |
|
aboxhall
2014/06/27 22:37:26
This comment is now out of date.
evy
2014/06/30 17:33:08
Done.
| |
| 993 // and decreases each iteration | |
| 994 int current_num_permutations = num_permutations; | |
| 995 for (int events_left = num_events; events_left > 0; events_left--) { | |
| 996 VLOG(0) << "\nEvents left: " << events_left; | |
| 997 int index = 0; | |
| 998 if (events_left == num_events) { | |
| 999 // This is the first event generated. We divide the number | |
| 1000 // of possible permutations by the number of events to choose from | |
| 1001 // (which is currently all of them). We then integer divide p by | |
| 1002 // this new value to decide which event will be first in this | |
| 1003 // permutation. e.g. If there are 4 events and 24 permutations, | |
| 1004 // the first 6 permutations will start with the first event. | |
| 1005 index = p / (current_num_permutations / events_left); | |
|
aboxhall
2014/06/27 22:37:26
Thanks, I actually mostly understand this now! How
evy
2014/06/30 17:33:08
Done. I'm not sure if this is clear enough yet. Ca
| |
| 1006 // Now we have one fewer event to deal with. So there are fewer | |
| 1007 // permuations to consider for the remaining events. | |
| 1008 // e.g. If now there are 3 events left, there were 24 permutations | |
| 1009 // but there are now 6 permutations. | |
| 1010 // Note that the first 2 permutations of these 6 will start with | |
| 1011 // the first of the remaining events. | |
| 1012 current_num_permutations /= events_left; | |
| 1013 } else if (events_left > 1) { | |
| 1014 // The logic here is similar to the case where there are num_events | |
| 1015 // left, but we need to adjust the value of p because we are | |
| 1016 // working with a smaller number of permutations of the fewer | |
| 1017 // events that are remaining. | |
| 1018 // e.g. If there are 3 events left, the number of permutations | |
| 1019 // should be 6. So we want to adjust p (currently 0 to 23 in the | |
| 1020 // big for loop) to get values between 0 and 5. So we do p % 6 | |
| 1021 VLOG(0) << "p " << p << " current num " << current_num_permutations; | |
| 1022 index = (p % current_num_permutations) / | |
| 1023 (current_num_permutations / events_left); | |
| 1024 current_num_permutations /= events_left; | |
| 1025 } else if (events_left == 1) { | |
| 1026 // When there is only one event left to be queued, there is only | |
| 1027 // one index available. | |
| 1028 index = 0; | |
| 1029 } | |
| 1030 ui::TouchEvent* next_dispatch = queued_events[index]; | |
| 1031 ASSERT_TRUE(next_dispatch != NULL); | |
| 1032 EventTestApi test_dispatch(next_dispatch); | |
| 1033 test_dispatch.set_time_stamp(Now()); | |
| 1034 generator_->Dispatch(next_dispatch); | |
| 1035 queued_events.erase(queued_events.begin() + index); | |
| 1036 // Note: it is possible to send a touched move event in the state | |
| 1037 // SINGLE_TAP_RELEASED or TOUCH_EXPLORE_RELEASED | |
| 1038 // because the events are not always generated in a sensical | |
| 1039 // order. If there is a LOG(ERROR) for touch moved hit in | |
| 1040 // InSingleTapOrTouchExploreReleased, that is fine here. | |
| 1041 | |
| 1042 // Keep track of what fingers have been pressed, to release | |
| 1043 // only those fingers at the end, so the check for being in | |
| 1044 // no fingers down can be accurate. | |
| 1045 if (next_dispatch->type() == ET_TOUCH_PRESSED) { | |
| 1046 fingers_pressed[next_dispatch->touch_id()] = true; | |
| 1047 } else if (next_dispatch->type() == ET_TOUCH_RELEASED) { | |
| 1048 fingers_pressed[next_dispatch->touch_id()] = false; | |
| 1049 } | |
| 1050 } | |
| 1051 ASSERT_EQ(queued_events.size(), 0u); | |
| 1052 | |
| 1053 // Release fingers recorded as pressed. | |
| 1054 for(int j = 0; j < int(fingers_pressed.size()); j++){ | |
| 1055 if (fingers_pressed[j] == true) { | |
| 1056 generator_->ReleaseTouchId(j); | |
| 1057 fingers_pressed[j] = false; | |
| 1058 } | |
| 1059 } | |
| 1060 AdvanceSimulatedTimePastTapDelay(); | |
| 1061 EXPECT_TRUE(IsInNoFingersDownState()); | |
| 1062 ClearCapturedEvents(); | |
| 1063 } | |
| 1064 } | |
| 1065 | |
| 951 } // namespace ui | 1066 } // namespace ui |
| OLD | NEW |