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" | |
17 #include "ui/gfx/geometry/point.h" | 16 #include "ui/gfx/geometry/point.h" |
18 #include "ui/gl/gl_implementation.h" | 17 #include "ui/gl/gl_implementation.h" |
19 #include "ui/gl/gl_surface.h" | 18 #include "ui/gl/gl_surface.h" |
20 | 19 |
21 namespace ui { | 20 namespace ui { |
22 | 21 |
23 namespace { | 22 namespace { |
24 // Records all mouse and touch events. | 23 // Records all mouse and touch events. |
25 class EventCapturer : public ui::EventHandler { | 24 class EventCapturer : public ui::EventHandler { |
26 public: | 25 public: |
(...skipping 24 matching lines...) Expand all Loading... |
51 const ScopedVector<ui::LocatedEvent>& captured_events() const { | 50 const ScopedVector<ui::LocatedEvent>& captured_events() const { |
52 return events_; | 51 return events_; |
53 } | 52 } |
54 | 53 |
55 private: | 54 private: |
56 ScopedVector<ui::LocatedEvent> events_; | 55 ScopedVector<ui::LocatedEvent> events_; |
57 | 56 |
58 DISALLOW_COPY_AND_ASSIGN(EventCapturer); | 57 DISALLOW_COPY_AND_ASSIGN(EventCapturer); |
59 }; | 58 }; |
60 | 59 |
61 int Factorial(int n) { | |
62 if (n <= 0) | |
63 return 0; | |
64 if (n == 1) | |
65 return 1; | |
66 return n * Factorial(n - 1); | |
67 } | |
68 | |
69 } // namespace | 60 } // namespace |
70 | 61 |
71 class TouchExplorationTest : public aura::test::AuraTestBase { | 62 class TouchExplorationTest : public aura::test::AuraTestBase { |
72 public: | 63 public: |
73 TouchExplorationTest() | 64 TouchExplorationTest() |
74 : simulated_clock_(new base::SimpleTestTickClock()) {} | 65 : simulated_clock_(new base::SimpleTestTickClock()) {} |
75 virtual ~TouchExplorationTest() {} | 66 virtual ~TouchExplorationTest() {} |
76 | 67 |
77 virtual void SetUp() OVERRIDE { | 68 virtual void SetUp() OVERRIDE { |
78 if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) | 69 if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 | 104 |
114 void ClearCapturedEvents() { | 105 void ClearCapturedEvents() { |
115 event_capturer_.Reset(); | 106 event_capturer_.Reset(); |
116 } | 107 } |
117 | 108 |
118 void AdvanceSimulatedTimePastTapDelay() { | 109 void AdvanceSimulatedTimePastTapDelay() { |
119 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); | 110 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); |
120 touch_exploration_controller_->CallTapTimerNowForTesting(); | 111 touch_exploration_controller_->CallTapTimerNowForTesting(); |
121 } | 112 } |
122 | 113 |
123 void AdvanceSimulatedTimePastPotentialTapDelay() { | |
124 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); | |
125 touch_exploration_controller_->CallTapTimerNowIfRunningForTesting(); | |
126 } | |
127 | |
128 void SuppressVLOGs(bool suppress) { | |
129 touch_exploration_controller_->SuppressVLOGsForTesting(suppress); | |
130 } | |
131 | |
132 void SwitchTouchExplorationMode(bool on) { | 114 void SwitchTouchExplorationMode(bool on) { |
133 if (!on && touch_exploration_controller_.get()) { | 115 if (!on && touch_exploration_controller_.get()) { |
134 touch_exploration_controller_.reset(); | 116 touch_exploration_controller_.reset(); |
135 } else if (on && !touch_exploration_controller_.get()) { | 117 } else if (on && !touch_exploration_controller_.get()) { |
136 touch_exploration_controller_.reset( | 118 touch_exploration_controller_.reset( |
137 new ui::TouchExplorationController(root_window())); | 119 new ui::TouchExplorationController(root_window())); |
138 touch_exploration_controller_->SetEventHandlerForTesting( | 120 touch_exploration_controller_->SetEventHandlerForTesting( |
139 &event_capturer_); | 121 &event_capturer_); |
140 cursor_client()->ShowCursor(); | 122 cursor_client()->ShowCursor(); |
141 cursor_client()->DisableMouseEvents(); | 123 cursor_client()->DisableMouseEvents(); |
(...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
852 // in TwoToOneFinger. | 834 // in TwoToOneFinger. |
853 TEST_F(TouchExplorationTest, TwoToOneFingerRelaseFirst) { | 835 TEST_F(TouchExplorationTest, TwoToOneFingerRelaseFirst) { |
854 gfx::Point first_touch_location = gfx::Point(11,12); | 836 gfx::Point first_touch_location = gfx::Point(11,12); |
855 gfx::Point second_touch_location = gfx::Point(21, 22); | 837 gfx::Point second_touch_location = gfx::Point(21, 22); |
856 EnterTwoToOne(first_touch_location, second_touch_location); | 838 EnterTwoToOne(first_touch_location, second_touch_location); |
857 const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents(); | 839 const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents(); |
858 ASSERT_EQ(captured_events.size(), 1u); | 840 ASSERT_EQ(captured_events.size(), 1u); |
859 ClearCapturedEvents(); | 841 ClearCapturedEvents(); |
860 | 842 |
861 // Actions before release have already been tested in the previous test. | 843 // Actions before release have already been tested in the previous test. |
| 844 |
862 // A release of the first finger should send an event, as the state | 845 // A release of the first finger should send an event, as the state |
863 // changes to the wait state. | 846 // changes to the wait state. |
864 ui::TouchEvent first_touch_release( | 847 ui::TouchEvent first_touch_release( |
865 ui::ET_TOUCH_RELEASED, first_touch_location, 0, Now()); | 848 ui::ET_TOUCH_RELEASED, first_touch_location, 0, Now()); |
866 generator_->Dispatch(&first_touch_release); | 849 generator_->Dispatch(&first_touch_release); |
867 ASSERT_EQ(captured_events.size(), 1u); | 850 ASSERT_EQ(captured_events.size(), 1u); |
868 ClearCapturedEvents(); | 851 ClearCapturedEvents(); |
869 | 852 |
870 // No events should be sent after the second finger is lifted. | 853 // No events should be sent after the second finger is lifted. |
871 | 854 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 EXPECT_EQ(first_touch_location, captured_events[0]->location()); | 941 EXPECT_EQ(first_touch_location, captured_events[0]->location()); |
959 ClearCapturedEvents(); | 942 ClearCapturedEvents(); |
960 | 943 |
961 ui::TouchEvent first_touch_release( | 944 ui::TouchEvent first_touch_release( |
962 ui::ET_TOUCH_RELEASED, first_touch_location, 0, Now()); | 945 ui::ET_TOUCH_RELEASED, first_touch_location, 0, Now()); |
963 generator_->Dispatch(&first_touch_release); | 946 generator_->Dispatch(&first_touch_release); |
964 ASSERT_EQ(captured_events.size(), 1u); | 947 ASSERT_EQ(captured_events.size(), 1u); |
965 EXPECT_TRUE(IsInNoFingersDownState()); | 948 EXPECT_TRUE(IsInNoFingersDownState()); |
966 } | 949 } |
967 | 950 |
968 TEST_F(TouchExplorationTest, AllFingerPermutations) { | |
969 SwitchTouchExplorationMode(true); | |
970 SuppressVLOGs(true); | |
971 // We will test all permutations of events from three different fingers | |
972 // to ensure that we return to NO_FINGERS_DOWN when fingers have been | |
973 // released. | |
974 ScopedVector<ui::TouchEvent> all_events; | |
975 for (int touch_id = 0; touch_id < 3; touch_id++){ | |
976 int x = 10*touch_id + 1; | |
977 int y = 10*touch_id + 2; | |
978 all_events.push_back(new TouchEvent( | |
979 ui::ET_TOUCH_PRESSED, gfx::Point(x++, y++), touch_id, Now())); | |
980 all_events.push_back(new TouchEvent( | |
981 ui::ET_TOUCH_MOVED, gfx::Point(x++, y++), touch_id, Now())); | |
982 all_events.push_back(new TouchEvent( | |
983 ui::ET_TOUCH_RELEASED, gfx::Point(x, y), touch_id, Now())); | |
984 } | |
985 | |
986 // I'm going to explain this algorithm, and use an example in parentheses. | |
987 // The example will be all permutations of a b c d. | |
988 // There are four letters and 4! = 24 permutations. | |
989 const int num_events = all_events.size(); | |
990 const int num_permutations = Factorial(num_events); | |
991 | |
992 for (int p = 0; p < num_permutations; p++) { | |
993 std::vector<ui::TouchEvent*> queued_events = all_events.get(); | |
994 std::vector<bool> fingers_pressed(3, false); | |
995 | |
996 int current_num_permutations = num_permutations; | |
997 for (int events_left = num_events; events_left > 0; events_left--) { | |
998 // |p| indexes to each permutation when there are num_permutations | |
999 // permutations. (e.g. 0 is abcd, 1 is abdc, 2 is acbd, 3 is acdb...) | |
1000 // But how do we find the index for the current number of permutations? | |
1001 // To find the permutation within the part of the sequence we're | |
1002 // currently looking at, we need a number between 0 and | |
1003 // |current_num_permutations| - 1. | |
1004 // (e.g. if we already chose the first letter, there are 3! = 6 | |
1005 // options left, so we do p % 6. So |current_permutation| would go | |
1006 // from 0 to 5 and then reset to 0 again, for all combinations of | |
1007 // whichever three letters are remaining, as we loop through the | |
1008 // permutations) | |
1009 int current_permutation = p % current_num_permutations; | |
1010 | |
1011 // Since this is is the total number of permutations starting with | |
1012 // this event and including future events, there could be multiple | |
1013 // values of current_permutation that will generate the same event | |
1014 // in this iteration. | |
1015 // (e.g. If we chose 'a' but have b c d to choose from, we choose b when | |
1016 // |current_permutation| = 0, 1 and c when |current_permutation| = 2, 3. | |
1017 // Note that each letter gets two numbers, which is the next | |
1018 // current_num_permutations, 2! for the two letters left.) | |
1019 | |
1020 // Branching out from the first event, there are num_permutations | |
1021 // permutations, and each value of |p| is associated with one of these | |
1022 // permutations. However, once the first event is chosen, there | |
1023 // are now |num_events| - 1 events left, so the number of permutations | |
1024 // for the rest of the events changes, and will always be equal to | |
1025 // the factorial of the events_left. | |
1026 // (e.g. There are 3! = 6 permutations that start with 'a', so if we | |
1027 // start with 'a' there will be 6 ways to then choose from b c d.) | |
1028 // So we now set-up for the next iteration by setting | |
1029 // current_num_permutations to the factorial of the next number of | |
1030 // events left. | |
1031 current_num_permutations /= events_left; | |
1032 | |
1033 // To figure out what current event we want to choose, we integer | |
1034 // divide the current permutation by the next current_num_permutations. | |
1035 // (e.g. If there are 4 letters a b c d and 24 permutations, we divide | |
1036 // by 24/4 = 6. Values 0 to 5 when divided by 6 equals 0, so the first | |
1037 // 6 permutations start with 'a', and the last 6 will start with 'd'. | |
1038 // Note that there are 6 that start with 'a' because there are 6 | |
1039 // permutations for the next three letters that follow 'a'.) | |
1040 int index = current_permutation / current_num_permutations; | |
1041 | |
1042 ui::TouchEvent* next_dispatch = queued_events[index]; | |
1043 ASSERT_TRUE(next_dispatch != NULL); | |
1044 | |
1045 // |next_dispatch| has to be put in this container so that its time | |
1046 // stamp can be changed to this point in the test, when it is being | |
1047 // dispatched.. | |
1048 EventTestApi test_dispatch(next_dispatch); | |
1049 test_dispatch.set_time_stamp(Now()); | |
1050 generator_->Dispatch(next_dispatch); | |
1051 queued_events.erase(queued_events.begin() + index); | |
1052 | |
1053 // Keep track of what fingers have been pressed, to release | |
1054 // only those fingers at the end, so the check for being in | |
1055 // no fingers down can be accurate. | |
1056 if (next_dispatch->type() == ET_TOUCH_PRESSED) { | |
1057 fingers_pressed[next_dispatch->touch_id()] = true; | |
1058 } else if (next_dispatch->type() == ET_TOUCH_RELEASED) { | |
1059 fingers_pressed[next_dispatch->touch_id()] = false; | |
1060 } | |
1061 } | |
1062 ASSERT_EQ(queued_events.size(), 0u); | |
1063 | |
1064 // Release fingers recorded as pressed. | |
1065 for(int j = 0; j < int(fingers_pressed.size()); j++){ | |
1066 if (fingers_pressed[j] == true) { | |
1067 generator_->ReleaseTouchId(j); | |
1068 fingers_pressed[j] = false; | |
1069 } | |
1070 } | |
1071 AdvanceSimulatedTimePastPotentialTapDelay(); | |
1072 EXPECT_TRUE(IsInNoFingersDownState()); | |
1073 ClearCapturedEvents(); | |
1074 } | |
1075 } | |
1076 | |
1077 } // namespace ui | 951 } // namespace ui |
OLD | NEW |