Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: ui/chromeos/touch_exploration_controller.cc

Issue 1953613002: Make touch accessibility gestures work with ChromeVox Next (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 if (it == current_touch_ids_.end()) 111 if (it == current_touch_ids_.end())
115 return ui::EVENT_REWRITE_CONTINUE; 112 return ui::EVENT_REWRITE_CONTINUE;
116 113
117 touch_locations_[*it] = location; 114 touch_locations_[*it] = location;
118 } else { 115 } else {
119 NOTREACHED() << "Unexpected event type received: " << event.name(); 116 NOTREACHED() << "Unexpected event type received: " << event.name();
120 return ui::EVENT_REWRITE_CONTINUE; 117 return ui::EVENT_REWRITE_CONTINUE;
121 } 118 }
122 VLOG_EVENT(touch_event); 119 VLOG_EVENT(touch_event);
123 120
121 /**
David Tseng 2016/05/05 22:30:39 nit: remove
dmazzoni 2016/05/06 19:06:09 Done.
124 // In order to avoid accidentally double tapping when moving off the edge 122 // In order to avoid accidentally double tapping when moving off the edge
125 // of the screen, the state will be rewritten to NoFingersDown. 123 // of the screen, the state will be rewritten to NoFingersDown.
126 if ((type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) && 124 if ((type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) &&
127 FindEdgesWithinBounds(touch_event.location(), kLeavingScreenEdge) != 125 FindEdgesWithinBounds(touch_event.location(), kLeavingScreenEdge) !=
128 NO_EDGE) { 126 NO_EDGE) {
129 if (VLOG_on_) 127 if (VLOG_on_)
130 VLOG(0) << "Leaving screen"; 128 VLOG(0) << "Leaving screen";
131 129
132 // Indicates to the user that they are leaving the screen. 130 // Indicates to the user that they are leaving the screen.
133 delegate_->PlayExitScreenEarcon(); 131 delegate_->PlayExitScreenEarcon();
134 132
135 if (current_touch_ids_.size() == 0) { 133 if (current_touch_ids_.size() == 0) {
136 SET_STATE(NO_FINGERS_DOWN); 134 SET_STATE(NO_FINGERS_DOWN);
137 if (VLOG_on_) { 135 if (VLOG_on_) {
138 VLOG(0) << "Reset to no fingers in Rewrite event because the touch " 136 VLOG(0) << "Reset to no fingers in Rewrite event because the touch "
139 "release or cancel was on the edge of the screen."; 137 "release or cancel was on the edge of the screen.";
140 } 138 }
141 return ui::EVENT_REWRITE_DISCARD; 139 return ui::EVENT_REWRITE_DISCARD;
142 } 140 }
143 } 141 }
142 **/
David Tseng 2016/05/05 22:30:39 nit: remove?
dmazzoni 2016/05/06 19:06:09 Done.
144 143
145 // If the user is in a gesture state, or if there is a possiblity that the 144 // If the user is in a gesture state, or if there is a possiblity that the
146 // user will enter it in the future, we send the event to the gesture 145 // user will enter it in the future, we send the event to the gesture
147 // provider so it can keep track of the state of the fingers. When the user 146 // provider so it can keep track of the state of the fingers. When the user
148 // leaves one of these states, SET_STATE will set the gesture provider to 147 // leaves one of these states, SET_STATE will set the gesture provider to
149 // NULL. 148 // NULL.
150 if (gesture_provider_.get()) { 149 if (gesture_provider_.get()) {
151 ui::TouchEvent mutable_touch_event = touch_event; 150 ui::TouchEvent mutable_touch_event = touch_event;
152 if (gesture_provider_->OnTouchEvent(&mutable_touch_event)) { 151 if (gesture_provider_->OnTouchEvent(&mutable_touch_event)) {
153 gesture_provider_->OnTouchEventAck(mutable_touch_event.unique_event_id(), 152 gesture_provider_->OnTouchEventAck(mutable_touch_event.unique_event_id(),
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 787
789 // This is an override for a function that is only called for timer-based events 788 // This is an override for a function that is only called for timer-based events
790 // like long press. Events that are created synchronously as a result of 789 // like long press. Events that are created synchronously as a result of
791 // certain touch events are added to the vector accessible via 790 // certain touch events are added to the vector accessible via
792 // GetAndResetPendingGestures(). We only care about swipes (which are created 791 // GetAndResetPendingGestures(). We only care about swipes (which are created
793 // synchronously), so we ignore this callback. 792 // synchronously), so we ignore this callback.
794 void TouchExplorationController::OnGestureEvent(ui::GestureConsumer* consumer, 793 void TouchExplorationController::OnGestureEvent(ui::GestureConsumer* consumer,
795 ui::GestureEvent* gesture) {} 794 ui::GestureEvent* gesture) {}
796 795
797 void TouchExplorationController::ProcessGestureEvents() { 796 void TouchExplorationController::ProcessGestureEvents() {
797 LOG(ERROR) << "ProcessGestureEvents";
David Tseng 2016/05/05 22:30:39 nit: remove
dmazzoni 2016/05/06 19:06:09 Done.
798 std::unique_ptr<ScopedVector<ui::GestureEvent>> gestures( 798 std::unique_ptr<ScopedVector<ui::GestureEvent>> gestures(
799 gesture_provider_->GetAndResetPendingGestures()); 799 gesture_provider_->GetAndResetPendingGestures());
800 if (gestures) { 800 if (gestures) {
801 for (ScopedVector<GestureEvent>::iterator i = gestures->begin(); 801 for (ScopedVector<GestureEvent>::iterator i = gestures->begin();
802 i != gestures->end(); 802 i != gestures->end();
803 ++i) { 803 ++i) {
804 if ((*i)->type() == ui::ET_GESTURE_SWIPE && 804 if ((*i)->type() == ui::ET_GESTURE_SWIPE &&
805 state_ == GESTURE_IN_PROGRESS) { 805 state_ == GESTURE_IN_PROGRESS) {
806 OnSwipeEvent(*i); 806 OnSwipeEvent(*i);
807 // The tap timer to leave gesture state is ended, and we now wait for 807 // The tap timer to leave gesture state is ended, and we now wait for
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { 866 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) {
867 // A swipe gesture contains details for the direction in which the swipe 867 // A swipe gesture contains details for the direction in which the swipe
868 // occurred. TODO(evy) : Research which swipe results users most want and 868 // occurred. TODO(evy) : Research which swipe results users most want and
869 // remap these swipes to the best events. Hopefully in the near future 869 // 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. 870 // there will also be a menu for users to pick custom mappings.
871 GestureEventDetails event_details = swipe_gesture->details(); 871 GestureEventDetails event_details = swipe_gesture->details();
872 int num_fingers = event_details.touch_points(); 872 int num_fingers = event_details.touch_points();
873 if (VLOG_on_) 873 if (VLOG_on_)
874 VLOG(0) << "\nSwipe with " << num_fingers << " fingers."; 874 VLOG(0) << "\nSwipe with " << num_fingers << " fingers.";
875 875
876 if (num_fingers > 4) 876 ui::AXGesture gesture = ui::AX_GESTURE_NONE;
877 return; 877 if (event_details.swipe_left()) {
878 switch (num_fingers) {
879 case 1: gesture = ui::AX_GESTURE_SWIPE_LEFT_1; break;
880 case 2: gesture = ui::AX_GESTURE_SWIPE_LEFT_2; break;
881 case 3: gesture = ui::AX_GESTURE_SWIPE_LEFT_3; break;
882 case 4: gesture = ui::AX_GESTURE_SWIPE_LEFT_4; break;
883 default: break;
884 }
885 } else if (event_details.swipe_up()) {
886 switch (num_fingers) {
887 case 1: gesture = ui::AX_GESTURE_SWIPE_UP_1; break;
888 case 2: gesture = ui::AX_GESTURE_SWIPE_UP_2; break;
889 case 3: gesture = ui::AX_GESTURE_SWIPE_UP_3; break;
890 case 4: gesture = ui::AX_GESTURE_SWIPE_UP_4; break;
891 default: break;
892 }
893 } else if (event_details.swipe_right()) {
894 switch (num_fingers) {
895 case 1: gesture = ui::AX_GESTURE_SWIPE_RIGHT_1; break;
896 case 2: gesture = ui::AX_GESTURE_SWIPE_RIGHT_2; break;
897 case 3: gesture = ui::AX_GESTURE_SWIPE_RIGHT_3; break;
898 case 4: gesture = ui::AX_GESTURE_SWIPE_RIGHT_4; break;
899 default: break;
900 }
901 } else if (event_details.swipe_down()) {
902 switch (num_fingers) {
903 case 1: gesture = ui::AX_GESTURE_SWIPE_DOWN_1; break;
904 case 2: gesture = ui::AX_GESTURE_SWIPE_DOWN_2; break;
905 case 3: gesture = ui::AX_GESTURE_SWIPE_DOWN_3; break;
906 case 4: gesture = ui::AX_GESTURE_SWIPE_DOWN_4; break;
907 default: break;
908 }
909 }
878 910
879 if (event_details.swipe_left() && 911 if (gesture != ui::AX_GESTURE_NONE)
880 !left_swipe_gestures_[num_fingers].is_null()) { 912 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 } 913 }
893 914
894 int TouchExplorationController::FindEdgesWithinBounds(gfx::Point point, 915 int TouchExplorationController::FindEdgesWithinBounds(gfx::Point point,
895 float bounds) { 916 float bounds) {
896 // Since GetBoundsInScreen is in DIPs but point is not, then point needs to be 917 // Since GetBoundsInScreen is in DIPs but point is not, then point needs to be
897 // converted. 918 // converted.
898 root_window_->GetHost()->ConvertPointFromNativeScreen(&point); 919 root_window_->GetHost()->ConvertPointFromNativeScreen(&point);
899 gfx::Rect window = root_window_->GetBoundsInScreen(); 920 gfx::Rect window = root_window_->GetBoundsInScreen();
900 921
901 float left_edge_limit = window.x() + bounds; 922 float left_edge_limit = window.x() + bounds;
(...skipping 10 matching lines...) Expand all
912 result |= LEFT_EDGE; 933 result |= LEFT_EDGE;
913 if (point.x() > right_edge_limit) 934 if (point.x() > right_edge_limit)
914 result |= RIGHT_EDGE; 935 result |= RIGHT_EDGE;
915 if (point.y() < top_edge_limit) 936 if (point.y() < top_edge_limit)
916 result |= TOP_EDGE; 937 result |= TOP_EDGE;
917 if (point.y() > bottom_edge_limit) 938 if (point.y() > bottom_edge_limit)
918 result |= BOTTOM_EDGE; 939 result |= BOTTOM_EDGE;
919 return result; 940 return result;
920 } 941 }
921 942
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( 943 void TouchExplorationController::DispatchKeyWithFlags(
955 const ui::KeyboardCode key, 944 const ui::KeyboardCode key,
956 int flags) { 945 int flags) {
957 ui::KeyEvent key_down(ui::ET_KEY_PRESSED, key, flags); 946 ui::KeyEvent key_down(ui::ET_KEY_PRESSED, key, flags);
958 ui::KeyEvent key_up(ui::ET_KEY_RELEASED, key, flags); 947 ui::KeyEvent key_up(ui::ET_KEY_RELEASED, key, flags);
959 DispatchEvent(&key_down); 948 DispatchEvent(&key_down);
960 DispatchEvent(&key_up); 949 DispatchEvent(&key_up);
961 if (VLOG_on_) { 950 if (VLOG_on_) {
962 VLOG(0) << "\nKey down: key code : " << key_down.key_code() 951 VLOG(0) << "\nKey down: key code : " << key_down.key_code()
963 << ", flags: " << key_down.flags() 952 << ", flags: " << key_down.flags()
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 case ONE_FINGER_PASSTHROUGH: 1104 case ONE_FINGER_PASSTHROUGH:
1116 return "ONE_FINGER_PASSTHROUGH"; 1105 return "ONE_FINGER_PASSTHROUGH";
1117 case WAIT_FOR_NO_FINGERS: 1106 case WAIT_FOR_NO_FINGERS:
1118 return "WAIT_FOR_NO_FINGERS"; 1107 return "WAIT_FOR_NO_FINGERS";
1119 case TWO_FINGER_TAP: 1108 case TWO_FINGER_TAP:
1120 return "TWO_FINGER_TAP"; 1109 return "TWO_FINGER_TAP";
1121 } 1110 }
1122 return "Not a state"; 1111 return "Not a state";
1123 } 1112 }
1124 1113
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() { 1114 float TouchExplorationController::GetSplitTapTouchSlop() {
1169 return gesture_detector_config_.touch_slop * 3; 1115 return gesture_detector_config_.touch_slop * 3;
1170 } 1116 }
1171 1117
1172 } // namespace ui 1118 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698