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 "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. | |
|
aboxhall
2014/08/07 22:45:19
Does this logic need extra testing?
lisayin
2014/08/08 02:12:24
Done.
| |
| 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); | |
| 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(); | |
| 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 |