| 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 |