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/logging.h" | 7 #include "base/logging.h" |
8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
9 #include "ui/aura/client/cursor_client.h" | 9 #include "ui/aura/client/cursor_client.h" |
10 #include "ui/aura/window.h" | 10 #include "ui/aura/window.h" |
11 #include "ui/aura/window_event_dispatcher.h" | 11 #include "ui/aura/window_event_dispatcher.h" |
12 #include "ui/aura/window_tree_host.h" | 12 #include "ui/aura/window_tree_host.h" |
13 #include "ui/events/event.h" | 13 #include "ui/events/event.h" |
14 #include "ui/events/event_processor.h" | 14 #include "ui/events/event_processor.h" |
15 #include "ui/events/event_utils.h" | 15 #include "ui/events/event_utils.h" |
16 #include "ui/gfx/geometry/rect.h" | 16 #include "ui/gfx/geometry/rect.h" |
17 | 17 |
18 #define VLOG_STATE() if (VLOG_IS_ON(0)) VlogState(__func__) | 18 #define VLOG_STATE() if (VLOG_IS_ON(0)) VlogState(__func__) |
19 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) | 19 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) |
20 | 20 |
21 namespace ui { | 21 namespace ui { |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 // Delay between adjustment sounds. | 25 // Delay between adjustment sounds. |
26 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); | 26 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); |
27 | 27 |
28 // In ChromeOS, VKEY_LWIN is synonymous for the search key. | 28 // In ChromeOS, VKEY_LWIN is synonymous for the search key. |
29 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; | 29 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; |
30 | |
31 // Delay to indicate that a two finger tap has occured. | |
32 const base::TimeDelta kTwoFingerTap = base::TimeDelta::FromMilliseconds(50); | |
33 | |
30 } // namespace | 34 } // namespace |
31 | 35 |
32 TouchExplorationController::TouchExplorationController( | 36 TouchExplorationController::TouchExplorationController( |
33 aura::Window* root_window, | 37 aura::Window* root_window, |
34 TouchExplorationControllerDelegate* delegate) | 38 TouchExplorationControllerDelegate* delegate) |
35 : root_window_(root_window), | 39 : root_window_(root_window), |
36 delegate_(delegate), | 40 delegate_(delegate), |
37 state_(NO_FINGERS_DOWN), | 41 state_(NO_FINGERS_DOWN), |
38 gesture_provider_(this), | 42 gesture_provider_(this), |
39 prev_state_(NO_FINGERS_DOWN), | 43 prev_state_(NO_FINGERS_DOWN), |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
127 case GESTURE_IN_PROGRESS: | 131 case GESTURE_IN_PROGRESS: |
128 return InGestureInProgress(touch_event, rewritten_event); | 132 return InGestureInProgress(touch_event, rewritten_event); |
129 case TOUCH_EXPLORE_SECOND_PRESS: | 133 case TOUCH_EXPLORE_SECOND_PRESS: |
130 return InTouchExploreSecondPress(touch_event, rewritten_event); | 134 return InTouchExploreSecondPress(touch_event, rewritten_event); |
131 case SLIDE_GESTURE: | 135 case SLIDE_GESTURE: |
132 return InSlideGesture(touch_event, rewritten_event); | 136 return InSlideGesture(touch_event, rewritten_event); |
133 case ONE_FINGER_PASSTHROUGH: | 137 case ONE_FINGER_PASSTHROUGH: |
134 return InOneFingerPassthrough(touch_event, rewritten_event); | 138 return InOneFingerPassthrough(touch_event, rewritten_event); |
135 case WAIT_FOR_ONE_FINGER: | 139 case WAIT_FOR_ONE_FINGER: |
136 return InWaitForOneFinger(touch_event, rewritten_event); | 140 return InWaitForOneFinger(touch_event, rewritten_event); |
141 case TWO_FINGER_TAP: | |
142 return InTwoFingerTap(touch_event, rewritten_event); | |
137 } | 143 } |
138 NOTREACHED(); | 144 NOTREACHED(); |
139 return ui::EVENT_REWRITE_CONTINUE; | 145 return ui::EVENT_REWRITE_CONTINUE; |
140 } | 146 } |
141 | 147 |
142 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( | 148 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( |
143 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { | 149 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { |
144 NOTREACHED(); | 150 NOTREACHED(); |
145 return ui::EVENT_REWRITE_CONTINUE; | 151 return ui::EVENT_REWRITE_CONTINUE; |
146 } | 152 } |
147 | 153 |
148 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( | 154 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( |
149 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 155 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
150 const ui::EventType type = event.type(); | 156 const ui::EventType type = event.type(); |
151 if (type == ui::ET_TOUCH_PRESSED) { | 157 if (type != ui::ET_TOUCH_PRESSED) { |
152 initial_press_.reset(new TouchEvent(event)); | 158 NOTREACHED() << "Unexpected event type received: " << event.name(); |
153 last_unused_finger_event_.reset(new TouchEvent(event)); | 159 return ui::EVENT_REWRITE_CONTINUE; |
154 StartTapTimer(); | |
155 gesture_provider_.OnTouchEvent(event); | |
156 gesture_provider_.OnTouchEventAck(false); | |
157 ProcessGestureEvents(); | |
158 state_ = SINGLE_TAP_PRESSED; | |
159 VLOG_STATE(); | |
160 return ui::EVENT_REWRITE_DISCARD; | |
161 } | 160 } |
162 NOTREACHED() << "Unexpected event type received: " << event.name(); | 161 initial_press_.reset(new TouchEvent(event)); |
163 return ui::EVENT_REWRITE_CONTINUE; | 162 initial_presses_[event.touch_id()] = event.location(); |
163 last_unused_finger_event_.reset(new TouchEvent(event)); | |
164 StartTapTimer(); | |
165 gesture_provider_.OnTouchEvent(event); | |
166 gesture_provider_.OnTouchEventAck(false); | |
167 ProcessGestureEvents(); | |
168 state_ = SINGLE_TAP_PRESSED; | |
169 VLOG_STATE(); | |
170 return ui::EVENT_REWRITE_DISCARD; | |
164 } | 171 } |
165 | 172 |
166 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( | 173 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
167 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 174 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
168 const ui::EventType type = event.type(); | 175 const ui::EventType type = event.type(); |
169 | 176 |
170 if (type == ui::ET_TOUCH_PRESSED) { | 177 if (type == ui::ET_TOUCH_PRESSED) { |
171 // TODO (evy, lisayin) : add support for multifinger swipes. | 178 initial_presses_[event.touch_id()] = event.location(); |
179 if ((event.time_stamp() - initial_press_->time_stamp()) < kTwoFingerTap) { | |
180 state_ = TWO_FINGER_TAP; | |
181 VLOG_STATE(); | |
182 return EVENT_REWRITE_DISCARD; | |
183 } | |
172 // For now, we wait for there to be only one finger down again. | 184 // For now, we wait for there to be only one finger down again. |
173 state_ = WAIT_FOR_ONE_FINGER; | 185 state_ = WAIT_FOR_ONE_FINGER; |
174 return EVENT_REWRITE_DISCARD; | 186 return EVENT_REWRITE_DISCARD; |
175 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 187 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
176 if (current_touch_ids_.size() == 0 && | 188 if (current_touch_ids_.size() == 0 && |
177 event.touch_id() == initial_press_->touch_id()) { | 189 event.touch_id() == initial_press_->touch_id()) { |
178 state_ = SINGLE_TAP_RELEASED; | 190 state_ = SINGLE_TAP_RELEASED; |
179 VLOG_STATE(); | 191 VLOG_STATE(); |
180 } else if (current_touch_ids_.size() == 0) { | 192 } else if (current_touch_ids_.size() == 0) { |
181 ResetToNoFingersDown(); | 193 ResetToNoFingersDown(); |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
542 if (current_touch_ids_.size() == 0) { | 554 if (current_touch_ids_.size() == 0) { |
543 ResetToNoFingersDown(); | 555 ResetToNoFingersDown(); |
544 } | 556 } |
545 return ui::EVENT_REWRITE_DISCARD; | 557 return ui::EVENT_REWRITE_DISCARD; |
546 } | 558 } |
547 | 559 |
548 ProcessGestureEvents(); | 560 ProcessGestureEvents(); |
549 return ui::EVENT_REWRITE_DISCARD; | 561 return ui::EVENT_REWRITE_DISCARD; |
550 } | 562 } |
551 | 563 |
564 ui::EventRewriteStatus TouchExplorationController::InTwoFingerTap( | |
565 const ui::TouchEvent& event, | |
566 scoped_ptr<ui::Event>* rewritten_event) { | |
567 ui::EventType type = event.type(); | |
568 if (type == ui::ET_TOUCH_PRESSED) { | |
569 // TODO(evy): Process three finger gestures here. | |
570 state_ = WAIT_FOR_ONE_FINGER; | |
571 VLOG_STATE(); | |
572 return ui::EVENT_REWRITE_DISCARD; | |
573 } | |
574 | |
575 if (type == ui::ET_TOUCH_MOVED) { | |
576 // Determine if it was a swipe. | |
577 gfx::Point original_location = initial_presses_[event.touch_id()]; | |
578 float distance = (event.location() - original_location).Length(); | |
579 // If the user moves too far from the original position, consider the | |
580 // movement a swipe. | |
581 // TODO(evy, lisayin): Add multifinger swipe processing. | |
582 if (distance > gesture_detector_config_.touch_slop) { | |
583 state_ = WAIT_FOR_ONE_FINGER; | |
584 } | |
585 return ui::EVENT_REWRITE_DISCARD; | |
586 } | |
587 | |
588 if (current_touch_ids_.size() != 0) | |
589 return ui::EVENT_REWRITE_DISCARD; | |
590 | |
591 if (type == ui::ET_TOUCH_RELEASED) { | |
592 ui::KeyEvent control_down( | |
593 ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN); | |
594 ui::KeyEvent control_up(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, ui::EF_NONE); | |
595 | |
596 DispatchEvent(&control_down); | |
James Cook
2014/08/08 18:06:30
I'm not that familiar with a11y -- maybe a comment
lisayin
2014/08/08 19:06:15
Done.
| |
597 DispatchEvent(&control_up); | |
598 | |
599 ResetToNoFingersDown(); | |
600 return ui::EVENT_REWRITE_DISCARD; | |
601 } | |
602 return ui::EVENT_REWRITE_DISCARD; | |
603 } | |
604 | |
552 base::TimeDelta TouchExplorationController::Now() { | 605 base::TimeDelta TouchExplorationController::Now() { |
553 if (tick_clock_) { | 606 if (tick_clock_) { |
554 // This is the same as what EventTimeForNow() does, but here we do it | 607 // This is the same as what EventTimeForNow() does, but here we do it |
555 // with a clock that can be replaced with a simulated clock for tests. | 608 // with a clock that can be replaced with a simulated clock for tests. |
556 return base::TimeDelta::FromInternalValue( | 609 return base::TimeDelta::FromInternalValue( |
557 tick_clock_->NowTicks().ToInternalValue()); | 610 tick_clock_->NowTicks().ToInternalValue()); |
558 } | 611 } |
559 return ui::EventTimeForNow(); | 612 return ui::EventTimeForNow(); |
560 } | 613 } |
561 | 614 |
(...skipping 26 matching lines...) Expand all Loading... | |
588 DispatchEvent(passthrough_press.get()); | 641 DispatchEvent(passthrough_press.get()); |
589 return; | 642 return; |
590 } | 643 } |
591 case SINGLE_TAP_PRESSED: | 644 case SINGLE_TAP_PRESSED: |
592 case GESTURE_IN_PROGRESS: | 645 case GESTURE_IN_PROGRESS: |
593 // Discard any pending gestures. | 646 // Discard any pending gestures. |
594 delete gesture_provider_.GetAndResetPendingGestures(); | 647 delete gesture_provider_.GetAndResetPendingGestures(); |
595 state_ = TOUCH_EXPLORATION; | 648 state_ = TOUCH_EXPLORATION; |
596 VLOG_STATE(); | 649 VLOG_STATE(); |
597 break; | 650 break; |
651 case TWO_FINGER_TAP: | |
652 state_ = WAIT_FOR_ONE_FINGER; | |
653 VLOG_STATE(); | |
654 break; | |
598 default: | 655 default: |
599 return; | 656 return; |
600 } | 657 } |
601 EnterTouchToMouseMode(); | 658 EnterTouchToMouseMode(); |
602 scoped_ptr<ui::Event> mouse_move = | 659 scoped_ptr<ui::Event> mouse_move = |
603 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); | 660 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); |
604 DispatchEvent(mouse_move.get()); | 661 DispatchEvent(mouse_move.get()); |
605 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 662 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
606 } | 663 } |
607 | 664 |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
793 aura::client::CursorClient* cursor_client = | 850 aura::client::CursorClient* cursor_client = |
794 aura::client::GetCursorClient(root_window_); | 851 aura::client::GetCursorClient(root_window_); |
795 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) | 852 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) |
796 cursor_client->EnableMouseEvents(); | 853 cursor_client->EnableMouseEvents(); |
797 if (cursor_client && cursor_client->IsCursorVisible()) | 854 if (cursor_client && cursor_client->IsCursorVisible()) |
798 cursor_client->HideCursor(); | 855 cursor_client->HideCursor(); |
799 } | 856 } |
800 | 857 |
801 void TouchExplorationController::ResetToNoFingersDown() { | 858 void TouchExplorationController::ResetToNoFingersDown() { |
802 ProcessGestureEvents(); | 859 ProcessGestureEvents(); |
860 initial_presses_.clear(); | |
James Cook
2014/08/08 18:06:30
Hooray for clearing out data structures!
lisayin
2014/08/08 19:06:15
:)
| |
803 if (sound_timer_.IsRunning()) | 861 if (sound_timer_.IsRunning()) |
804 sound_timer_.Stop(); | 862 sound_timer_.Stop(); |
805 state_ = NO_FINGERS_DOWN; | 863 state_ = NO_FINGERS_DOWN; |
806 VLOG_STATE(); | 864 VLOG_STATE(); |
807 if (tap_timer_.IsRunning()) | 865 if (tap_timer_.IsRunning()) |
808 tap_timer_.Stop(); | 866 tap_timer_.Stop(); |
809 } | 867 } |
810 | 868 |
811 void TouchExplorationController::VlogState(const char* function_name) { | 869 void TouchExplorationController::VlogState(const char* function_name) { |
812 if (!VLOG_on_) | 870 if (!VLOG_on_) |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
868 case GESTURE_IN_PROGRESS: | 926 case GESTURE_IN_PROGRESS: |
869 return "GESTURE_IN_PROGRESS"; | 927 return "GESTURE_IN_PROGRESS"; |
870 case TOUCH_EXPLORE_SECOND_PRESS: | 928 case TOUCH_EXPLORE_SECOND_PRESS: |
871 return "TOUCH_EXPLORE_SECOND_PRESS"; | 929 return "TOUCH_EXPLORE_SECOND_PRESS"; |
872 case SLIDE_GESTURE: | 930 case SLIDE_GESTURE: |
873 return "SLIDE_GESTURE"; | 931 return "SLIDE_GESTURE"; |
874 case ONE_FINGER_PASSTHROUGH: | 932 case ONE_FINGER_PASSTHROUGH: |
875 return "ONE_FINGER_PASSTHROUGH"; | 933 return "ONE_FINGER_PASSTHROUGH"; |
876 case WAIT_FOR_ONE_FINGER: | 934 case WAIT_FOR_ONE_FINGER: |
877 return "WAIT_FOR_ONE_FINGER"; | 935 return "WAIT_FOR_ONE_FINGER"; |
936 case TWO_FINGER_TAP: | |
937 return "TWO_FINGER_TAP"; | |
878 } | 938 } |
879 return "Not a state"; | 939 return "Not a state"; |
880 } | 940 } |
881 | 941 |
882 } // namespace ui | 942 } // namespace ui |
OLD | NEW |