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" | |
8 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
9 #include "ui/aura/client/cursor_client.h" | 8 #include "ui/aura/client/cursor_client.h" |
10 #include "ui/aura/window.h" | 9 #include "ui/aura/window.h" |
11 #include "ui/aura/window_event_dispatcher.h" | 10 #include "ui/aura/window_event_dispatcher.h" |
12 #include "ui/aura/window_tree_host.h" | 11 #include "ui/aura/window_tree_host.h" |
13 #include "ui/events/event.h" | 12 #include "ui/events/event.h" |
14 #include "ui/events/event_processor.h" | 13 #include "ui/events/event_processor.h" |
14 #include "ui/gfx/geometry/rect.h" | |
15 | 15 |
16 #define VLOG_STATE() if (VLOG_IS_ON(0)) VlogState(__func__) | 16 #define VLOG_STATE() if (VLOG_IS_ON(0)) VlogState(__func__) |
17 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) | 17 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) |
18 | 18 |
19 namespace ui { | 19 namespace ui { |
20 | 20 |
21 namespace { | 21 namespace { |
22 int SignOf(float number) { | |
23 if (number == 0) | |
24 return 0; | |
25 return number > 0 ? 1 : -1; | |
26 } | |
27 | |
28 // Delay between adjustment sounds. | |
29 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); | |
30 | |
31 // Minimum Volume adjustment. | |
32 const float kMinPercentVolumeChange = 1; | |
33 | |
34 // Swipe/scroll gestures within these bounds (in dips) will change preset | |
35 // settings. | |
36 const float kMaxDistanceFromEdge = 75; | |
37 | |
38 // After a slide gesture has been triggered, if the finger is still within these | |
39 // bounds, the preset settings will still change. | |
40 const float kSlopDistanceFromEdge = kMaxDistanceFromEdge + 40; | |
41 | |
22 // In ChromeOS, VKEY_LWIN is synonymous for the search key. | 42 // In ChromeOS, VKEY_LWIN is synonymous for the search key. |
23 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; | 43 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; |
24 } // namespace | 44 } // namespace |
25 | 45 |
26 TouchExplorationController::TouchExplorationController( | 46 TouchExplorationController::TouchExplorationController( |
27 aura::Window* root_window) | 47 aura::Window* root_window, |
48 TouchExplorationControllerDelegate* delegate) | |
28 : root_window_(root_window), | 49 : root_window_(root_window), |
29 state_(NO_FINGERS_DOWN), | 50 state_(NO_FINGERS_DOWN), |
30 event_handler_for_testing_(NULL), | 51 event_handler_for_testing_(NULL), |
31 gesture_provider_(this), | 52 gesture_provider_(this), |
32 prev_state_(NO_FINGERS_DOWN), | 53 prev_state_(NO_FINGERS_DOWN), |
33 VLOG_on_(true) { | 54 VLOG_on_(true) { |
34 CHECK(root_window); | 55 CHECK(root_window); |
35 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); | 56 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); |
57 delegate_.reset(delegate); | |
dmazzoni
2014/07/14 18:00:34
Do this as an initializer before the initial {, as
lisayin
2014/07/14 22:38:38
Done.
| |
36 } | 58 } |
37 | 59 |
38 | 60 |
39 TouchExplorationController::~TouchExplorationController() { | 61 TouchExplorationController::~TouchExplorationController() { |
40 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); | 62 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); |
41 } | 63 } |
42 | 64 |
43 void TouchExplorationController::CallTapTimerNowForTesting() { | 65 void TouchExplorationController::CallTapTimerNowForTesting() { |
44 DCHECK(tap_timer_.IsRunning()); | 66 DCHECK(tap_timer_.IsRunning()); |
45 tap_timer_.Stop(); | 67 tap_timer_.Stop(); |
(...skipping 14 matching lines...) Expand all Loading... | |
60 | 82 |
61 bool TouchExplorationController::IsInNoFingersDownStateForTesting() const { | 83 bool TouchExplorationController::IsInNoFingersDownStateForTesting() const { |
62 return state_ == NO_FINGERS_DOWN; | 84 return state_ == NO_FINGERS_DOWN; |
63 } | 85 } |
64 | 86 |
65 bool TouchExplorationController::IsInGestureInProgressStateForTesting() const { | 87 bool TouchExplorationController::IsInGestureInProgressStateForTesting() const { |
66 return state_ == GESTURE_IN_PROGRESS; | 88 return state_ == GESTURE_IN_PROGRESS; |
67 } | 89 } |
68 | 90 |
69 void TouchExplorationController::SuppressVLOGsForTesting(bool suppress) { | 91 void TouchExplorationController::SuppressVLOGsForTesting(bool suppress) { |
70 VLOG_on_ = !suppress; | 92 VLOG_on_ = !suppress; |
93 } | |
94 | |
95 gfx::Rect TouchExplorationController::BoundsOfWindowInDIPForTesting() { | |
dmazzoni
2014/07/14 18:00:33
This should be BoundsOfRootWindow...?
lisayin
2014/07/14 22:38:38
Done.
| |
96 return root_window_->GetBoundsInScreen(); | |
97 } | |
98 | |
99 bool TouchExplorationController::IsInSlideGestureStateForTesting() const { | |
100 return state_ == SLIDE_GESTURE; | |
71 } | 101 } |
72 | 102 |
73 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( | 103 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
74 const ui::Event& event, | 104 const ui::Event& event, |
75 scoped_ptr<ui::Event>* rewritten_event) { | 105 scoped_ptr<ui::Event>* rewritten_event) { |
76 if (!event.IsTouchEvent()) { | 106 if (!event.IsTouchEvent()) { |
77 if (event.IsKeyEvent()) { | 107 if (event.IsKeyEvent()) { |
78 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); | 108 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); |
79 VLOG(0) << "\nKeyboard event: " << key_event.name() | 109 VLOG(0) << "\nKeyboard event: " << key_event.name() |
80 << "\n Key code: " << key_event.key_code() | 110 << "\n Key code: " << key_event.key_code() |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 case GESTURE_IN_PROGRESS: | 175 case GESTURE_IN_PROGRESS: |
146 return InGestureInProgress(touch_event, rewritten_event); | 176 return InGestureInProgress(touch_event, rewritten_event); |
147 case TOUCH_EXPLORE_SECOND_PRESS: | 177 case TOUCH_EXPLORE_SECOND_PRESS: |
148 return InTouchExploreSecondPress(touch_event, rewritten_event); | 178 return InTouchExploreSecondPress(touch_event, rewritten_event); |
149 case TWO_TO_ONE_FINGER: | 179 case TWO_TO_ONE_FINGER: |
150 return InTwoToOneFinger(touch_event, rewritten_event); | 180 return InTwoToOneFinger(touch_event, rewritten_event); |
151 case PASSTHROUGH: | 181 case PASSTHROUGH: |
152 return InPassthrough(touch_event, rewritten_event); | 182 return InPassthrough(touch_event, rewritten_event); |
153 case WAIT_FOR_RELEASE: | 183 case WAIT_FOR_RELEASE: |
154 return InWaitForRelease(touch_event, rewritten_event); | 184 return InWaitForRelease(touch_event, rewritten_event); |
185 case SLIDE_GESTURE: | |
186 return InSlideGesture(touch_event, rewritten_event); | |
155 } | 187 } |
156 NOTREACHED(); | 188 NOTREACHED(); |
157 return ui::EVENT_REWRITE_CONTINUE; | 189 return ui::EVENT_REWRITE_CONTINUE; |
158 } | 190 } |
159 | 191 |
160 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( | 192 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( |
161 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { | 193 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { |
162 NOTREACHED(); | 194 NOTREACHED(); |
163 return ui::EVENT_REWRITE_CONTINUE; | 195 return ui::EVENT_REWRITE_CONTINUE; |
164 } | 196 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 | 247 |
216 float delta_time = | 248 float delta_time = |
217 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); | 249 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); |
218 float velocity = distance / delta_time; | 250 float velocity = distance / delta_time; |
219 VLOG(0) << "\n Delta time: " << delta_time | 251 VLOG(0) << "\n Delta time: " << delta_time |
220 << "\n Distance: " << distance | 252 << "\n Distance: " << distance |
221 << "\n Velocity of click: " << velocity | 253 << "\n Velocity of click: " << velocity |
222 << "\n Minimum swipe velocity: " | 254 << "\n Minimum swipe velocity: " |
223 << gesture_detector_config_.minimum_swipe_velocity; | 255 << gesture_detector_config_.minimum_swipe_velocity; |
224 | 256 |
257 // Change to slide gesture if the slide occurred at the right edge. | |
258 int where = WithinBoundsOfEdge(event.location(), kMaxDistanceFromEdge); | |
259 if ((where | RIGHT_EDGE) == where) { | |
260 state_ = SLIDE_GESTURE; | |
261 VLOG_STATE(); | |
262 return InSlideGesture(event, rewritten_event); | |
263 } | |
264 | |
225 // If the user moves fast enough from the initial touch location, start | 265 // If the user moves fast enough from the initial touch location, start |
226 // gesture detection. Otherwise, jump to the touch exploration mode early. | 266 // gesture detection. Otherwise, jump to the touch exploration mode early. |
227 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { | 267 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { |
228 state_ = GESTURE_IN_PROGRESS; | 268 state_ = GESTURE_IN_PROGRESS; |
229 VLOG_STATE(); | 269 VLOG_STATE(); |
230 return InGestureInProgress(event, rewritten_event); | 270 return InGestureInProgress(event, rewritten_event); |
231 } | 271 } |
232 EnterTouchToMouseMode(); | 272 EnterTouchToMouseMode(); |
233 state_ = TOUCH_EXPLORATION; | 273 state_ = TOUCH_EXPLORATION; |
234 VLOG_STATE(); | 274 VLOG_STATE(); |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
495 if (current_touch_ids_.size() != 1) | 535 if (current_touch_ids_.size() != 1) |
496 return EVENT_REWRITE_DISCARD; | 536 return EVENT_REWRITE_DISCARD; |
497 | 537 |
498 // Rewrite at location of last touch exploration. | 538 // Rewrite at location of last touch exploration. |
499 rewritten_event->reset( | 539 rewritten_event->reset( |
500 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, | 540 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, |
501 last_touch_exploration_->location(), | 541 last_touch_exploration_->location(), |
502 initial_press_->touch_id(), | 542 initial_press_->touch_id(), |
503 event.time_stamp())); | 543 event.time_stamp())); |
504 (*rewritten_event)->set_flags(event.flags()); | 544 (*rewritten_event)->set_flags(event.flags()); |
545 EnterTouchToMouseMode(); | |
505 state_ = TOUCH_EXPLORATION; | 546 state_ = TOUCH_EXPLORATION; |
506 EnterTouchToMouseMode(); | 547 EnterTouchToMouseMode(); |
507 VLOG_STATE(); | 548 VLOG_STATE(); |
508 return ui::EVENT_REWRITE_REWRITTEN; | 549 return ui::EVENT_REWRITE_REWRITTEN; |
509 } | 550 } |
510 NOTREACHED() << "Unexpected event type received: " << event.name(); | 551 NOTREACHED() << "Unexpected event type received: " << event.name(); |
511 return ui::EVENT_REWRITE_CONTINUE; | 552 return ui::EVENT_REWRITE_CONTINUE; |
512 } | 553 } |
513 | 554 |
514 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease( | 555 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease( |
515 const ui::TouchEvent& event, | 556 const ui::TouchEvent& event, |
516 scoped_ptr<ui::Event>* rewritten_event) { | 557 scoped_ptr<ui::Event>* rewritten_event) { |
517 ui::EventType type = event.type(); | 558 ui::EventType type = event.type(); |
518 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || | 559 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || |
519 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { | 560 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { |
520 NOTREACHED() << "Unexpected event type received: " << event.name(); | 561 NOTREACHED() << "Unexpected event type received: " << event.name(); |
521 return ui::EVENT_REWRITE_CONTINUE; | 562 return ui::EVENT_REWRITE_CONTINUE; |
522 } | 563 } |
523 if (current_touch_ids_.size() == 0) { | 564 if (current_touch_ids_.size() == 0) { |
524 state_ = NO_FINGERS_DOWN; | 565 state_ = NO_FINGERS_DOWN; |
525 VLOG_STATE(); | 566 VLOG_STATE(); |
526 ResetToNoFingersDown(); | 567 ResetToNoFingersDown(); |
527 } | 568 } |
528 return EVENT_REWRITE_DISCARD; | 569 return EVENT_REWRITE_DISCARD; |
529 } | 570 } |
530 | 571 |
572 void TouchExplorationController::PlaySoundForTimer() { | |
573 delegate_->PlayVolumeAdjustSound(); | |
574 } | |
575 | |
576 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( | |
577 const ui::TouchEvent& event, | |
578 scoped_ptr<ui::Event>* rewritten_event) { | |
579 ui::EventType type = event.type(); | |
580 // If additional fingers are added before a swipe gesture has been registered, | |
581 // then wait until all fingers have been released. | |
dmazzoni
2014/07/14 18:00:34
This comment doesn't seem to describe what the cod
lisayin
2014/07/14 22:38:38
Done.
| |
582 if (type == ui::ET_TOUCH_PRESSED || | |
583 event.touch_id() != initial_press_->touch_id()) { | |
584 if (tap_timer_.IsRunning()) | |
585 tap_timer_.Stop(); | |
586 // Discard any pending gestures. | |
587 ignore_result(gesture_provider_.GetAndResetPendingGestures()); | |
588 state_ = TWO_TO_ONE_FINGER; | |
589 last_two_to_one_.reset(new TouchEvent(event)); | |
590 rewritten_event->reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, | |
591 event.location(), | |
592 event.touch_id(), | |
593 event.time_stamp())); | |
594 (*rewritten_event)->set_flags(event.flags()); | |
595 return EVENT_REWRITE_REWRITTEN; | |
596 } | |
597 | |
598 VLOG(0) << "Location " << event.location().ToString(); | |
599 // Allows user to return to the edge to adjust the sound if they have left the | |
600 // boundaries. | |
601 int where = WithinBoundsOfEdge(event.location(), kSlopDistanceFromEdge); | |
602 if (((where | RIGHT_EDGE) != where) && (type != ui::ET_TOUCH_RELEASED)) { | |
603 if (sound_timer_.IsRunning()) { | |
604 sound_timer_.Stop(); | |
605 } | |
606 return EVENT_REWRITE_DISCARD; | |
607 } | |
608 | |
609 // This can occur if the user leaves the screen edge and then returns to it to | |
610 // continue adjusting the sound. | |
611 if (!sound_timer_.IsRunning()) { | |
612 sound_timer_.Start(FROM_HERE, | |
613 kSoundDelay, | |
614 this, | |
615 &ui::TouchExplorationController::PlaySoundForTimer); | |
616 delegate_->PlayVolumeAdjustSound(); | |
617 } | |
618 // The timer should not fire when sliding. | |
619 if (tap_timer_.IsRunning()) | |
620 tap_timer_.Stop(); | |
621 | |
622 // There should not be more than one finger down. | |
623 DCHECK(current_touch_ids_.size() <= 1); | |
624 if (type == ui::ET_TOUCH_MOVED) { | |
625 gesture_provider_.OnTouchEvent(event); | |
626 gesture_provider_.OnTouchEventAck(false); | |
627 } | |
628 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | |
629 gesture_provider_.OnTouchEvent(event); | |
630 gesture_provider_.OnTouchEventAck(false); | |
631 ignore_result(gesture_provider_.GetAndResetPendingGestures()); | |
632 if (current_touch_ids_.size() == 0) | |
633 ResetToNoFingersDown(); | |
634 return ui::EVENT_REWRITE_DISCARD; | |
635 } | |
636 | |
637 ProcessGestureEvents(); | |
638 return ui::EVENT_REWRITE_DISCARD; | |
639 } | |
640 | |
531 void TouchExplorationController::OnTapTimerFired() { | 641 void TouchExplorationController::OnTapTimerFired() { |
532 switch (state_) { | 642 switch (state_) { |
533 case SINGLE_TAP_RELEASED: | 643 case SINGLE_TAP_RELEASED: |
534 ResetToNoFingersDown(); | 644 ResetToNoFingersDown(); |
535 break; | 645 break; |
536 case TOUCH_EXPLORE_RELEASED: | 646 case TOUCH_EXPLORE_RELEASED: |
537 ResetToNoFingersDown(); | 647 ResetToNoFingersDown(); |
538 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 648 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
539 return; | 649 return; |
540 case SINGLE_TAP_PRESSED: | 650 case SINGLE_TAP_PRESSED: |
541 case GESTURE_IN_PROGRESS: | 651 case GESTURE_IN_PROGRESS: |
542 // Discard any pending gestures. | 652 // Discard any pending gestures. |
543 ignore_result(gesture_provider_.GetAndResetPendingGestures()); | 653 ignore_result(gesture_provider_.GetAndResetPendingGestures()); |
544 EnterTouchToMouseMode(); | 654 EnterTouchToMouseMode(); |
545 state_ = TOUCH_EXPLORATION; | 655 state_ = TOUCH_EXPLORATION; |
546 VLOG_STATE(); | 656 VLOG_STATE(); |
547 break; | 657 break; |
548 default: | 658 default: |
549 return; | 659 return; |
550 } | 660 } |
551 scoped_ptr<ui::Event> mouse_move = | 661 scoped_ptr<ui::Event> mouse_move = |
552 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); | 662 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); |
553 DispatchEvent(mouse_move.get()); | 663 DispatchEvent(mouse_move.get()); |
554 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 664 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
555 } | 665 } |
556 | 666 |
557 void TouchExplorationController::DispatchEvent(ui::Event* event) { | 667 void TouchExplorationController::DispatchEvent(ui::Event* event) { |
558 if (event_handler_for_testing_) { | 668 if (event_handler_for_testing_) { |
559 event_handler_for_testing_->OnEvent(event); | 669 event_handler_for_testing_->OnEvent(event); |
560 return; | 670 return; |
561 } | 671 } |
562 ui::EventDispatchDetails result ALLOW_UNUSED = | 672 ui::EventDispatchDetails result ALLOW_UNUSED = |
563 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); | 673 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); |
564 } | 674 } |
565 | 675 |
566 void TouchExplorationController::OnGestureEvent(ui::GestureEvent* gesture) { | 676 void TouchExplorationController::OnGestureEvent( |
677 ui::GestureEvent* gesture) { | |
567 CHECK(gesture->IsGestureEvent()); | 678 CHECK(gesture->IsGestureEvent()); |
679 ui::EventType type = gesture->type(); | |
568 VLOG(0) << " \n Gesture Triggered: " << gesture->name(); | 680 VLOG(0) << " \n Gesture Triggered: " << gesture->name(); |
569 if (gesture->type() == ui::ET_GESTURE_SWIPE) { | 681 if (type == ui::ET_GESTURE_SWIPE && state_ != SLIDE_GESTURE) { |
570 if (tap_timer_.IsRunning()) | 682 VLOG(0) << "Swipe!"; |
571 tap_timer_.Stop(); | 683 ignore_result(gesture_provider_.GetAndResetPendingGestures()); |
572 OnSwipeEvent(gesture); | 684 OnSwipeEvent(gesture); |
573 return; | 685 return; |
574 } | 686 } |
687 if (gesture->IsScrollGestureEvent() && state_ == SLIDE_GESTURE) { | |
688 SideSlideControl(gesture); | |
dmazzoni
2014/07/14 18:00:33
Why are you using the gesture detector for slides?
lisayin
2014/07/14 22:38:38
Done.
| |
689 VLOG(0) << "Sliding"; | |
690 return; | |
691 } | |
575 } | 692 } |
576 | 693 |
577 void TouchExplorationController::ProcessGestureEvents() { | 694 void TouchExplorationController::ProcessGestureEvents() { |
578 scoped_ptr<ScopedVector<ui::GestureEvent> > gestures( | 695 scoped_ptr<ScopedVector<ui::GestureEvent> > gestures( |
579 gesture_provider_.GetAndResetPendingGestures()); | 696 gesture_provider_.GetAndResetPendingGestures()); |
580 if (gestures) { | 697 if (gestures) { |
581 for (ScopedVector<GestureEvent>::iterator i = gestures->begin(); | 698 for (ScopedVector<GestureEvent>::iterator i = gestures->begin(); |
582 i != gestures->end(); | 699 i != gestures->end(); |
583 ++i) { | 700 ++i) { |
584 OnGestureEvent(*i); | 701 OnGestureEvent(*i); |
585 } | 702 } |
586 } | 703 } |
587 } | 704 } |
588 | 705 |
706 void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) { | |
707 ui::EventType type = gesture->type(); | |
708 gfx::Point location = gesture->location(); | |
709 VLOG(0) << "Location " << location.ToString(); | |
710 root_window_->GetHost()->ConvertPointToNativeScreen(&location); | |
711 if (WithinBoundsOfEdge(location, kSlopDistanceFromEdge) == SCREEN_CENTER) { | |
712 VLOG(0) << "No more Slide gesture "; | |
713 // Discard any pending gestures. | |
714 ignore_result(gesture_provider_.GetAndResetPendingGestures()); | |
715 if (current_touch_ids_.size() > 1) { | |
716 state_ = WAIT_FOR_RELEASE; | |
717 } else if (current_touch_ids_.size() == 0) { | |
718 ResetToNoFingersDown(); | |
719 } else { | |
720 EnterTouchToMouseMode(); | |
721 state_ = TOUCH_EXPLORATION; | |
722 } | |
723 VLOG_STATE(); | |
724 return; | |
725 } | |
726 | |
727 if (type == ET_GESTURE_SCROLL_BEGIN) { | |
728 delegate_->PlayVolumeAdjustSound(); | |
729 } | |
730 | |
731 if (type == ET_GESTURE_SCROLL_END) { | |
732 if (sound_timer_.IsRunning()) | |
733 sound_timer_.Stop(); | |
734 delegate_->PlayVolumeAdjustSound(); | |
735 } | |
736 | |
737 location = gesture->location(); | |
738 int where = WithinBoundsOfEdge(location, kSlopDistanceFromEdge); | |
739 | |
740 // If the user is in the corner of the right side of the screen, the volume | |
741 // will be automatically set to 100% or muted depending on which corner they | |
742 // are in. Otherwise, the user will be able to adjust the volume by sliding | |
743 // their finger along the right side of the screen. Volume is relative to | |
744 // where they are on the right side of the screen. | |
745 if ((where | RIGHT_EDGE) != where) | |
746 return; | |
747 | |
748 if (where == RIGHT_EDGE) { | |
749 location = gesture->location(); | |
750 root_window_->GetHost()->ConvertPointFromNativeScreen(&location); | |
751 float volume = | |
752 100 - | |
753 ((float)location.y() - kMaxDistanceFromEdge) / | |
754 (root_window_->bounds().bottom() - 2 * kMaxDistanceFromEdge) * 100; | |
755 VLOG(0) << "\n Volume = " << volume | |
756 << "\n Location = " << location.ToString() | |
757 << "\n Bounds = " << root_window_->bounds().right(); | |
758 | |
759 delegate_->AdjustSound(volume); | |
760 return; | |
761 } | |
762 else if ((where | TOP_EDGE) == where) { | |
763 delegate_->AdjustSound(100); | |
764 return; | |
765 } else if ((where | BOTTOM_EDGE) == where) { | |
766 delegate_->AdjustSound(0); | |
767 return; | |
768 } | |
769 NOTREACHED() << "Invalid location " << where; | |
770 } | |
771 | |
772 | |
589 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { | 773 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { |
590 // A swipe gesture contains details for the direction in which the swipe | 774 // A swipe gesture contains details for the direction in which the swipe |
591 // occurred. | 775 // occurred. |
592 GestureEventDetails event_details = swipe_gesture->details(); | 776 GestureEventDetails event_details = swipe_gesture->details(); |
593 if (event_details.swipe_left()) { | 777 if (event_details.swipe_left()) { |
594 DispatchShiftSearchKeyEvent(ui::VKEY_LEFT); | 778 DispatchShiftSearchKeyEvent(ui::VKEY_LEFT); |
595 return; | 779 return; |
596 } else if (event_details.swipe_right()) { | 780 } else if (event_details.swipe_right()) { |
597 DispatchShiftSearchKeyEvent(ui::VKEY_RIGHT); | 781 DispatchShiftSearchKeyEvent(ui::VKEY_RIGHT); |
598 return; | 782 return; |
599 } else if (event_details.swipe_up()) { | 783 } else if (event_details.swipe_up()) { |
600 DispatchShiftSearchKeyEvent(ui::VKEY_UP); | 784 DispatchShiftSearchKeyEvent(ui::VKEY_UP); |
601 return; | 785 return; |
602 } else if (event_details.swipe_down()) { | 786 } else if (event_details.swipe_down()) { |
603 DispatchShiftSearchKeyEvent(ui::VKEY_DOWN); | 787 DispatchShiftSearchKeyEvent(ui::VKEY_DOWN); |
604 return; | 788 return; |
605 } | 789 } |
606 } | 790 } |
607 | 791 |
792 int TouchExplorationController::WithinBoundsOfEdge(gfx::Point point, | |
793 float bounds) { | |
794 // Since GetBoundsInScreen is in DIPs but p is not, then p needs to be | |
795 // converted. | |
796 root_window_->GetHost()->ConvertPointFromNativeScreen(&point); | |
797 gfx::Rect window= root_window_->GetBoundsInScreen(); | |
798 | |
799 float left_edge_limit = window.x() + bounds; | |
800 float right_edge_limit = window.right() - bounds; | |
801 float top_edge_limit = window.y() + bounds; | |
802 float bottom_edge_limit = window.bottom() - bounds; | |
803 | |
804 // Bitwise manipulation in order to determine where on the screen the point | |
805 // lies. If more than one bit is turned on, then it is a corner where the two | |
806 // bit/edges intersect. Otherwise, if no bits are turned on, the point must be | |
807 // in the center of the screen. | |
808 int result = SCREEN_CENTER; | |
809 if (point.x() < left_edge_limit) | |
810 result = result | LEFT_EDGE; | |
811 if (point.x() > right_edge_limit) | |
812 result = result | RIGHT_EDGE; | |
813 if (point.y() < top_edge_limit) | |
814 result = result | TOP_EDGE; | |
815 if (point.y() > bottom_edge_limit) | |
816 result = result | BOTTOM_EDGE; | |
817 return result; | |
818 } | |
819 | |
608 void TouchExplorationController::DispatchShiftSearchKeyEvent( | 820 void TouchExplorationController::DispatchShiftSearchKeyEvent( |
609 const ui::KeyboardCode direction) { | 821 const ui::KeyboardCode direction) { |
610 // In order to activate the shortcut shift+search+<arrow key> | 822 // In order to activate the shortcut shift+search+<arrow key> |
611 // three KeyPressed events must be dispatched in succession along | 823 // three KeyPressed events must be dispatched in succession along |
612 // with three KeyReleased events. | 824 // with three KeyReleased events. |
613 ui::KeyEvent shift_down = ui::KeyEvent( | 825 ui::KeyEvent shift_down = ui::KeyEvent( |
614 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN, false); | 826 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN, false); |
615 ui::KeyEvent search_down = ui::KeyEvent( | 827 ui::KeyEvent search_down = ui::KeyEvent( |
616 ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false); | 828 ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false); |
617 ui::KeyEvent direction_down = | 829 ui::KeyEvent direction_down = |
(...skipping 29 matching lines...) Expand all Loading... | |
647 void TouchExplorationController::EnterTouchToMouseMode() { | 859 void TouchExplorationController::EnterTouchToMouseMode() { |
648 aura::client::CursorClient* cursor_client = | 860 aura::client::CursorClient* cursor_client = |
649 aura::client::GetCursorClient(root_window_); | 861 aura::client::GetCursorClient(root_window_); |
650 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) | 862 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) |
651 cursor_client->EnableMouseEvents(); | 863 cursor_client->EnableMouseEvents(); |
652 if (cursor_client && cursor_client->IsCursorVisible()) | 864 if (cursor_client && cursor_client->IsCursorVisible()) |
653 cursor_client->HideCursor(); | 865 cursor_client->HideCursor(); |
654 } | 866 } |
655 | 867 |
656 void TouchExplorationController::ResetToNoFingersDown() { | 868 void TouchExplorationController::ResetToNoFingersDown() { |
869 ProcessGestureEvents(); | |
870 if (sound_timer_.IsRunning()) | |
871 sound_timer_.Stop(); | |
657 state_ = NO_FINGERS_DOWN; | 872 state_ = NO_FINGERS_DOWN; |
658 VLOG_STATE(); | 873 VLOG_STATE(); |
659 if (tap_timer_.IsRunning()) | 874 if (tap_timer_.IsRunning()) |
660 tap_timer_.Stop(); | 875 tap_timer_.Stop(); |
661 } | 876 } |
662 | 877 |
663 void TouchExplorationController::VlogState(const char* function_name) { | 878 void TouchExplorationController::VlogState(const char* function_name) { |
664 if (!VLOG_on_) | 879 if (!VLOG_on_) |
665 return; | 880 return; |
666 if (prev_state_ == state_) | 881 if (prev_state_ == state_) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
718 case GESTURE_IN_PROGRESS: | 933 case GESTURE_IN_PROGRESS: |
719 return "GESTURE_IN_PROGRESS"; | 934 return "GESTURE_IN_PROGRESS"; |
720 case TOUCH_EXPLORE_SECOND_PRESS: | 935 case TOUCH_EXPLORE_SECOND_PRESS: |
721 return "TOUCH_EXPLORE_SECOND_PRESS"; | 936 return "TOUCH_EXPLORE_SECOND_PRESS"; |
722 case TWO_TO_ONE_FINGER: | 937 case TWO_TO_ONE_FINGER: |
723 return "TWO_TO_ONE_FINGER"; | 938 return "TWO_TO_ONE_FINGER"; |
724 case PASSTHROUGH: | 939 case PASSTHROUGH: |
725 return "PASSTHROUGH"; | 940 return "PASSTHROUGH"; |
726 case WAIT_FOR_RELEASE: | 941 case WAIT_FOR_RELEASE: |
727 return "WAIT_FOR_RELEASE"; | 942 return "WAIT_FOR_RELEASE"; |
943 case SLIDE_GESTURE: | |
944 return "SLIDE_GESTURE"; | |
728 } | 945 } |
729 return "Not a state"; | 946 return "Not a state"; |
730 } | 947 } |
731 | 948 |
732 } // namespace ui | 949 } // namespace ui |
OLD | NEW |