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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/time/default_tick_clock.h" | 11 #include "base/time/default_tick_clock.h" |
| 12 #include "ui/accessibility/ax_enums.h" | |
| 12 #include "ui/aura/client/cursor_client.h" | 13 #include "ui/aura/client/cursor_client.h" |
| 13 #include "ui/aura/window.h" | 14 #include "ui/aura/window.h" |
| 14 #include "ui/aura/window_event_dispatcher.h" | 15 #include "ui/aura/window_event_dispatcher.h" |
| 15 #include "ui/aura/window_tree_host.h" | 16 #include "ui/aura/window_tree_host.h" |
| 16 #include "ui/events/event.h" | 17 #include "ui/events/event.h" |
| 17 #include "ui/events/event_processor.h" | 18 #include "ui/events/event_processor.h" |
| 18 #include "ui/events/event_utils.h" | 19 #include "ui/events/event_utils.h" |
| 19 #include "ui/gfx/geometry/rect.h" | 20 #include "ui/gfx/geometry/rect.h" |
| 20 | 21 |
| 21 #define SET_STATE(state) SetState(state, __func__) | 22 #define SET_STATE(state) SetState(state, __func__) |
| 22 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) | 23 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) |
| 23 | 24 |
| 24 namespace ui { | 25 namespace ui { |
| 25 | 26 |
| 26 namespace { | 27 namespace { |
| 27 | 28 |
| 28 // Delay between adjustment sounds. | 29 // Delay between adjustment sounds. |
| 29 const int kSoundDelayInMS = 150; | 30 const int kSoundDelayInMS = 150; |
| 30 | 31 |
| 31 // In ChromeOS, VKEY_LWIN is synonymous for the search key. | |
| 32 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; | |
| 33 | |
| 34 } // namespace | 32 } // namespace |
| 35 | 33 |
| 36 TouchExplorationController::TouchExplorationController( | 34 TouchExplorationController::TouchExplorationController( |
| 37 aura::Window* root_window, | 35 aura::Window* root_window, |
| 38 TouchExplorationControllerDelegate* delegate) | 36 TouchExplorationControllerDelegate* delegate) |
| 39 : root_window_(root_window), | 37 : root_window_(root_window), |
| 40 delegate_(delegate), | 38 delegate_(delegate), |
| 41 state_(NO_FINGERS_DOWN), | 39 state_(NO_FINGERS_DOWN), |
| 42 gesture_provider_(new GestureProviderAura(this, this)), | 40 gesture_provider_(new GestureProviderAura(this, this)), |
| 43 prev_state_(NO_FINGERS_DOWN), | 41 prev_state_(NO_FINGERS_DOWN), |
| 44 VLOG_on_(true), | 42 VLOG_on_(true), |
| 45 tick_clock_(NULL) { | 43 tick_clock_(NULL) { |
| 46 DCHECK(root_window); | 44 DCHECK(root_window); |
| 47 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); | 45 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); |
| 48 InitializeSwipeGestureMaps(); | |
| 49 } | 46 } |
| 50 | 47 |
| 51 TouchExplorationController::~TouchExplorationController() { | 48 TouchExplorationController::~TouchExplorationController() { |
| 52 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); | 49 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); |
| 53 } | 50 } |
| 54 | 51 |
| 55 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( | 52 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
| 56 const ui::Event& event, | 53 const ui::Event& event, |
| 57 std::unique_ptr<ui::Event>* rewritten_event) { | 54 std::unique_ptr<ui::Event>* rewritten_event) { |
| 58 if (!event.IsTouchEvent()) { | 55 if (!event.IsTouchEvent()) { |
| (...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 866 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { | 863 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { |
| 867 // A swipe gesture contains details for the direction in which the swipe | 864 // A swipe gesture contains details for the direction in which the swipe |
| 868 // occurred. TODO(evy) : Research which swipe results users most want and | 865 // occurred. TODO(evy) : Research which swipe results users most want and |
| 869 // remap these swipes to the best events. Hopefully in the near future | 866 // remap these swipes to the best events. Hopefully in the near future |
| 870 // there will also be a menu for users to pick custom mappings. | 867 // there will also be a menu for users to pick custom mappings. |
| 871 GestureEventDetails event_details = swipe_gesture->details(); | 868 GestureEventDetails event_details = swipe_gesture->details(); |
| 872 int num_fingers = event_details.touch_points(); | 869 int num_fingers = event_details.touch_points(); |
| 873 if (VLOG_on_) | 870 if (VLOG_on_) |
| 874 VLOG(0) << "\nSwipe with " << num_fingers << " fingers."; | 871 VLOG(0) << "\nSwipe with " << num_fingers << " fingers."; |
| 875 | 872 |
| 876 if (num_fingers > 4) | 873 ui::AXGesture gesture = ui::AX_GESTURE_NONE; |
| 877 return; | 874 if (event_details.swipe_left()) { |
| 875 switch (num_fingers) { | |
| 876 case 1: | |
| 877 gesture = ui::AX_GESTURE_SWIPE_LEFT_1; | |
| 878 break; | |
| 879 case 2: | |
| 880 gesture = ui::AX_GESTURE_SWIPE_LEFT_2; | |
| 881 break; | |
| 882 case 3: | |
| 883 gesture = ui::AX_GESTURE_SWIPE_LEFT_3; | |
| 884 break; | |
| 885 case 4: | |
| 886 gesture = ui::AX_GESTURE_SWIPE_LEFT_4; | |
| 887 break; | |
| 888 default: | |
|
oshima
2016/05/06 19:43:50
qq: this (5 fingers or more) can happen?
dmazzoni
2016/05/09 18:07:08
Yes, it can, we just don't intend to map 5 finger
| |
| 889 break; | |
| 890 } | |
| 891 } else if (event_details.swipe_up()) { | |
| 892 switch (num_fingers) { | |
| 893 case 1: | |
| 894 gesture = ui::AX_GESTURE_SWIPE_UP_1; | |
| 895 break; | |
| 896 case 2: | |
| 897 gesture = ui::AX_GESTURE_SWIPE_UP_2; | |
| 898 break; | |
| 899 case 3: | |
| 900 gesture = ui::AX_GESTURE_SWIPE_UP_3; | |
| 901 break; | |
| 902 case 4: | |
| 903 gesture = ui::AX_GESTURE_SWIPE_UP_4; | |
| 904 break; | |
| 905 default: | |
| 906 break; | |
| 907 } | |
| 908 } else if (event_details.swipe_right()) { | |
| 909 switch (num_fingers) { | |
| 910 case 1: | |
| 911 gesture = ui::AX_GESTURE_SWIPE_RIGHT_1; | |
| 912 break; | |
| 913 case 2: | |
| 914 gesture = ui::AX_GESTURE_SWIPE_RIGHT_2; | |
| 915 break; | |
| 916 case 3: | |
| 917 gesture = ui::AX_GESTURE_SWIPE_RIGHT_3; | |
| 918 break; | |
| 919 case 4: | |
| 920 gesture = ui::AX_GESTURE_SWIPE_RIGHT_4; | |
| 921 break; | |
| 922 default: | |
| 923 break; | |
| 924 } | |
| 925 } else if (event_details.swipe_down()) { | |
| 926 switch (num_fingers) { | |
| 927 case 1: | |
| 928 gesture = ui::AX_GESTURE_SWIPE_DOWN_1; | |
| 929 break; | |
| 930 case 2: | |
| 931 gesture = ui::AX_GESTURE_SWIPE_DOWN_2; | |
| 932 break; | |
| 933 case 3: | |
| 934 gesture = ui::AX_GESTURE_SWIPE_DOWN_3; | |
| 935 break; | |
| 936 case 4: | |
| 937 gesture = ui::AX_GESTURE_SWIPE_DOWN_4; | |
| 938 break; | |
| 939 default: | |
| 940 break; | |
| 941 } | |
| 942 } | |
| 878 | 943 |
| 879 if (event_details.swipe_left() && | 944 if (gesture != ui::AX_GESTURE_NONE) |
| 880 !left_swipe_gestures_[num_fingers].is_null()) { | 945 delegate_->HandleAccessibilityGesture(gesture); |
| 881 left_swipe_gestures_[num_fingers].Run(); | |
| 882 } else if (event_details.swipe_right() && | |
| 883 !right_swipe_gestures_[num_fingers].is_null()) { | |
| 884 right_swipe_gestures_[num_fingers].Run(); | |
| 885 } else if (event_details.swipe_up() && | |
| 886 !up_swipe_gestures_[num_fingers].is_null()) { | |
| 887 up_swipe_gestures_[num_fingers].Run(); | |
| 888 } else if (event_details.swipe_down() && | |
| 889 !down_swipe_gestures_[num_fingers].is_null()) { | |
| 890 down_swipe_gestures_[num_fingers].Run(); | |
| 891 } | |
| 892 } | 946 } |
| 893 | 947 |
| 894 int TouchExplorationController::FindEdgesWithinBounds(gfx::Point point, | 948 int TouchExplorationController::FindEdgesWithinBounds(gfx::Point point, |
| 895 float bounds) { | 949 float bounds) { |
| 896 // Since GetBoundsInScreen is in DIPs but point is not, then point needs to be | 950 // Since GetBoundsInScreen is in DIPs but point is not, then point needs to be |
| 897 // converted. | 951 // converted. |
| 898 root_window_->GetHost()->ConvertPointFromNativeScreen(&point); | 952 root_window_->GetHost()->ConvertPointFromNativeScreen(&point); |
| 899 gfx::Rect window = root_window_->GetBoundsInScreen(); | 953 gfx::Rect window = root_window_->GetBoundsInScreen(); |
| 900 | 954 |
| 901 float left_edge_limit = window.x() + bounds; | 955 float left_edge_limit = window.x() + bounds; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 912 result |= LEFT_EDGE; | 966 result |= LEFT_EDGE; |
| 913 if (point.x() > right_edge_limit) | 967 if (point.x() > right_edge_limit) |
| 914 result |= RIGHT_EDGE; | 968 result |= RIGHT_EDGE; |
| 915 if (point.y() < top_edge_limit) | 969 if (point.y() < top_edge_limit) |
| 916 result |= TOP_EDGE; | 970 result |= TOP_EDGE; |
| 917 if (point.y() > bottom_edge_limit) | 971 if (point.y() > bottom_edge_limit) |
| 918 result |= BOTTOM_EDGE; | 972 result |= BOTTOM_EDGE; |
| 919 return result; | 973 return result; |
| 920 } | 974 } |
| 921 | 975 |
| 922 void TouchExplorationController::DispatchShiftSearchKeyEvent( | |
| 923 const ui::KeyboardCode third_key) { | |
| 924 // In order to activate the shortcut shift+search+<arrow key> | |
| 925 // three KeyPressed events must be dispatched in succession along | |
| 926 // with three KeyReleased events. | |
| 927 | |
| 928 ui::KeyEvent shift_down( | |
| 929 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN); | |
| 930 ui::KeyEvent search_down( | |
| 931 ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN); | |
| 932 ui::KeyEvent third_key_down(ui::ET_KEY_PRESSED, third_key, ui::EF_SHIFT_DOWN); | |
| 933 | |
| 934 ui::KeyEvent third_key_up(ui::ET_KEY_RELEASED, third_key, ui::EF_SHIFT_DOWN); | |
| 935 ui::KeyEvent search_up( | |
| 936 ui::ET_KEY_RELEASED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN); | |
| 937 ui ::KeyEvent shift_up(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE); | |
| 938 | |
| 939 DispatchEvent(&shift_down); | |
| 940 DispatchEvent(&search_down); | |
| 941 DispatchEvent(&third_key_down); | |
| 942 DispatchEvent(&third_key_up); | |
| 943 DispatchEvent(&search_up); | |
| 944 DispatchEvent(&shift_up); | |
| 945 } | |
| 946 | |
| 947 base::Closure TouchExplorationController::BindShiftSearchKeyEvent( | |
| 948 const ui::KeyboardCode third_key) { | |
| 949 return base::Bind(&TouchExplorationController::DispatchShiftSearchKeyEvent, | |
| 950 base::Unretained(this), | |
| 951 third_key); | |
| 952 } | |
| 953 | |
| 954 void TouchExplorationController::DispatchKeyWithFlags( | 976 void TouchExplorationController::DispatchKeyWithFlags( |
| 955 const ui::KeyboardCode key, | 977 const ui::KeyboardCode key, |
| 956 int flags) { | 978 int flags) { |
| 957 ui::KeyEvent key_down(ui::ET_KEY_PRESSED, key, flags); | 979 ui::KeyEvent key_down(ui::ET_KEY_PRESSED, key, flags); |
| 958 ui::KeyEvent key_up(ui::ET_KEY_RELEASED, key, flags); | 980 ui::KeyEvent key_up(ui::ET_KEY_RELEASED, key, flags); |
| 959 DispatchEvent(&key_down); | 981 DispatchEvent(&key_down); |
| 960 DispatchEvent(&key_up); | 982 DispatchEvent(&key_up); |
| 961 if (VLOG_on_) { | 983 if (VLOG_on_) { |
| 962 VLOG(0) << "\nKey down: key code : " << key_down.key_code() | 984 VLOG(0) << "\nKey down: key code : " << key_down.key_code() |
| 963 << ", flags: " << key_down.flags() | 985 << ", flags: " << key_down.flags() |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1115 case ONE_FINGER_PASSTHROUGH: | 1137 case ONE_FINGER_PASSTHROUGH: |
| 1116 return "ONE_FINGER_PASSTHROUGH"; | 1138 return "ONE_FINGER_PASSTHROUGH"; |
| 1117 case WAIT_FOR_NO_FINGERS: | 1139 case WAIT_FOR_NO_FINGERS: |
| 1118 return "WAIT_FOR_NO_FINGERS"; | 1140 return "WAIT_FOR_NO_FINGERS"; |
| 1119 case TWO_FINGER_TAP: | 1141 case TWO_FINGER_TAP: |
| 1120 return "TWO_FINGER_TAP"; | 1142 return "TWO_FINGER_TAP"; |
| 1121 } | 1143 } |
| 1122 return "Not a state"; | 1144 return "Not a state"; |
| 1123 } | 1145 } |
| 1124 | 1146 |
| 1125 // TODO(evy, lisayin) : Just call abstracted methods on the delegate (e.g. | |
| 1126 // Swipe(Direction direction, int num_fingers)), and add the DispatchXYZ | |
| 1127 // methods to the delegate. Avoid the middle step of dispatching keys at all, | |
| 1128 // and simply have ChromeVox/ChromeOS complete the required action. | |
| 1129 | |
| 1130 void TouchExplorationController::InitializeSwipeGestureMaps() { | |
| 1131 // Gestures with one finger are used for navigation. | |
| 1132 left_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_LEFT); | |
| 1133 right_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_RIGHT); | |
| 1134 up_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_UP); | |
| 1135 down_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_DOWN); | |
| 1136 | |
| 1137 // Gestures with two fingers. | |
| 1138 left_swipe_gestures_[2] = | |
| 1139 BindKeyEventWithFlags(ui::VKEY_BROWSER_BACK, ui::EF_NONE); | |
| 1140 right_swipe_gestures_[2] = | |
| 1141 BindKeyEventWithFlags(ui::VKEY_BROWSER_FORWARD, ui::EF_NONE); | |
| 1142 // Jump to top. | |
| 1143 up_swipe_gestures_[2] = BindShiftSearchKeyEvent(ui::VKEY_A); | |
| 1144 // Read from here. | |
| 1145 down_swipe_gestures_[2] = BindShiftSearchKeyEvent(ui::VKEY_R); | |
| 1146 | |
| 1147 // Gestures with three fingers switch tabs left/right and scroll up/down. | |
| 1148 left_swipe_gestures_[3] = BindKeyEventWithFlags( | |
| 1149 ui::VKEY_TAB, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN); | |
| 1150 right_swipe_gestures_[3] = | |
| 1151 BindKeyEventWithFlags(ui::VKEY_TAB, ui::EF_CONTROL_DOWN); | |
| 1152 up_swipe_gestures_[3] = BindKeyEventWithFlags(ui::VKEY_NEXT, ui::EF_NONE); | |
| 1153 down_swipe_gestures_[3] = BindKeyEventWithFlags(ui::VKEY_PRIOR, ui::EF_NONE); | |
| 1154 | |
| 1155 // Gestures with four fingers should probably eventually be used for rare | |
| 1156 // needs that are hard to access through menus. | |
| 1157 // Note that brightness levels are here because they can be important for low | |
| 1158 // vision users. However, none of these mappings are permanent. | |
| 1159 left_swipe_gestures_[4] = | |
| 1160 BindKeyEventWithFlags(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE); | |
| 1161 right_swipe_gestures_[4] = | |
| 1162 BindKeyEventWithFlags(VKEY_BRIGHTNESS_UP, ui::EF_NONE); | |
| 1163 up_swipe_gestures_[4] = BindKeyEventWithFlags(VKEY_BROWSER_HOME, ui::EF_NONE); | |
| 1164 down_swipe_gestures_[4] = | |
| 1165 BindKeyEventWithFlags(VKEY_BROWSER_REFRESH, ui::EF_NONE); | |
| 1166 } | |
| 1167 | |
| 1168 float TouchExplorationController::GetSplitTapTouchSlop() { | 1147 float TouchExplorationController::GetSplitTapTouchSlop() { |
| 1169 return gesture_detector_config_.touch_slop * 3; | 1148 return gesture_detector_config_.touch_slop * 3; |
| 1170 } | 1149 } |
| 1171 | 1150 |
| 1172 } // namespace ui | 1151 } // namespace ui |
| OLD | NEW |