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

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

Issue 385073009: Side Slide Gestures for Accessibility (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Separated CrosAcessibilityObserver into own files Created 6 years, 5 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 "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 const float kLeavingScreenEdge = 6;
35
36 // Swipe/scroll gestures within these bounds (in dips) will change preset
37 // settings.
38 const float kMaxDistanceFromEdge = 75;
39
40 // After a slide gesture has been triggered, if the finger is still within these
41 // bounds, the preset settings will still change.
42 const float kSlopDistanceFromEdge = kMaxDistanceFromEdge + 40;
43
22 // In ChromeOS, VKEY_LWIN is synonymous for the search key. 44 // In ChromeOS, VKEY_LWIN is synonymous for the search key.
23 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; 45 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN;
24 } // namespace 46 } // namespace
25 47
26 TouchExplorationController::TouchExplorationController( 48 TouchExplorationController::TouchExplorationController(
27 aura::Window* root_window) 49 aura::Window* root_window,
50 TouchExplorationControllerDelegate* delegate)
28 : root_window_(root_window), 51 : root_window_(root_window),
52 delegate_(delegate),
29 state_(NO_FINGERS_DOWN), 53 state_(NO_FINGERS_DOWN),
30 event_handler_for_testing_(NULL), 54 event_handler_for_testing_(NULL),
31 gesture_provider_(this), 55 gesture_provider_(this),
32 prev_state_(NO_FINGERS_DOWN), 56 prev_state_(NO_FINGERS_DOWN),
33 VLOG_on_(true) { 57 VLOG_on_(true) {
34 CHECK(root_window); 58 CHECK(root_window);
35 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); 59 root_window->GetHost()->GetEventSource()->AddEventRewriter(this);
36 } 60 }
37 61
38 62
(...skipping 21 matching lines...) Expand all
60 84
61 bool TouchExplorationController::IsInNoFingersDownStateForTesting() const { 85 bool TouchExplorationController::IsInNoFingersDownStateForTesting() const {
62 return state_ == NO_FINGERS_DOWN; 86 return state_ == NO_FINGERS_DOWN;
63 } 87 }
64 88
65 bool TouchExplorationController::IsInGestureInProgressStateForTesting() const { 89 bool TouchExplorationController::IsInGestureInProgressStateForTesting() const {
66 return state_ == GESTURE_IN_PROGRESS; 90 return state_ == GESTURE_IN_PROGRESS;
67 } 91 }
68 92
69 void TouchExplorationController::SuppressVLOGsForTesting(bool suppress) { 93 void TouchExplorationController::SuppressVLOGsForTesting(bool suppress) {
70 VLOG_on_ = !suppress; 94 VLOG_on_ = !suppress;
95 }
96
97 gfx::Rect TouchExplorationController::BoundsOfRootWindowInDIPForTesting() {
98 return root_window_->GetBoundsInScreen();
99 }
100
101 bool TouchExplorationController::IsInSlideGestureStateForTesting() const {
102 return state_ == SLIDE_GESTURE;
71 } 103 }
72 104
73 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( 105 ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
74 const ui::Event& event, 106 const ui::Event& event,
75 scoped_ptr<ui::Event>* rewritten_event) { 107 scoped_ptr<ui::Event>* rewritten_event) {
76 if (!event.IsTouchEvent()) { 108 if (!event.IsTouchEvent()) {
77 if (event.IsKeyEvent()) { 109 if (event.IsKeyEvent()) {
78 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); 110 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event);
79 VLOG(0) << "\nKeyboard event: " << key_event.name() 111 VLOG(0) << "\nKeyboard event: " << key_event.name()
80 << "\n Key code: " << key_event.key_code() 112 << "\n Key code: " << key_event.key_code()
(...skipping 20 matching lines...) Expand all
101 const ui::EventType type = touch_event.type(); 133 const ui::EventType type = touch_event.type();
102 const gfx::PointF& location = touch_event.location_f(); 134 const gfx::PointF& location = touch_event.location_f();
103 const int touch_id = touch_event.touch_id(); 135 const int touch_id = touch_event.touch_id();
104 136
105 // Always update touch ids and touch locations, so we can use those 137 // Always update touch ids and touch locations, so we can use those
106 // no matter what state we're in. 138 // no matter what state we're in.
107 if (type == ui::ET_TOUCH_PRESSED) { 139 if (type == ui::ET_TOUCH_PRESSED) {
108 current_touch_ids_.push_back(touch_id); 140 current_touch_ids_.push_back(touch_id);
109 touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location)); 141 touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location));
110 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 142 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
143 // If the release is too close to the edge.
144 TouchEvent touch_event = static_cast<const TouchEvent&>(event);
145 if (WithinBoundsOfEdge(touch_event.location(), kLeavingScreenEdge) !=
146 SCREEN_CENTER) {
147 if (current_touch_ids_.size() == 0)
148 ResetToNoFingersDown();
149 else
150 state_ = WAIT_FOR_RELEASE;
151 }
152
111 std::vector<int>::iterator it = std::find( 153 std::vector<int>::iterator it = std::find(
112 current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); 154 current_touch_ids_.begin(), current_touch_ids_.end(), touch_id);
113 155
114 // Can happen if touch exploration is enabled while fingers were down. 156 // Can happen if touch exploration is enabled while fingers were down.
115 if (it == current_touch_ids_.end()) 157 if (it == current_touch_ids_.end())
116 return ui::EVENT_REWRITE_CONTINUE; 158 return ui::EVENT_REWRITE_CONTINUE;
117 159
118 current_touch_ids_.erase(it); 160 current_touch_ids_.erase(it);
119 touch_locations_.erase(touch_id); 161 touch_locations_.erase(touch_id);
120 } else if (type == ui::ET_TOUCH_MOVED) { 162 } else if (type == ui::ET_TOUCH_MOVED) {
(...skipping 24 matching lines...) Expand all
145 case GESTURE_IN_PROGRESS: 187 case GESTURE_IN_PROGRESS:
146 return InGestureInProgress(touch_event, rewritten_event); 188 return InGestureInProgress(touch_event, rewritten_event);
147 case TOUCH_EXPLORE_SECOND_PRESS: 189 case TOUCH_EXPLORE_SECOND_PRESS:
148 return InTouchExploreSecondPress(touch_event, rewritten_event); 190 return InTouchExploreSecondPress(touch_event, rewritten_event);
149 case TWO_TO_ONE_FINGER: 191 case TWO_TO_ONE_FINGER:
150 return InTwoToOneFinger(touch_event, rewritten_event); 192 return InTwoToOneFinger(touch_event, rewritten_event);
151 case PASSTHROUGH: 193 case PASSTHROUGH:
152 return InPassthrough(touch_event, rewritten_event); 194 return InPassthrough(touch_event, rewritten_event);
153 case WAIT_FOR_RELEASE: 195 case WAIT_FOR_RELEASE:
154 return InWaitForRelease(touch_event, rewritten_event); 196 return InWaitForRelease(touch_event, rewritten_event);
197 case SLIDE_GESTURE:
198 return InSlideGesture(touch_event, rewritten_event);
155 } 199 }
156 NOTREACHED(); 200 NOTREACHED();
157 return ui::EVENT_REWRITE_CONTINUE; 201 return ui::EVENT_REWRITE_CONTINUE;
158 } 202 }
159 203
160 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( 204 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent(
161 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { 205 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) {
162 NOTREACHED(); 206 NOTREACHED();
163 return ui::EVENT_REWRITE_CONTINUE; 207 return ui::EVENT_REWRITE_CONTINUE;
164 } 208 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 259
216 float delta_time = 260 float delta_time =
217 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); 261 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF();
218 float velocity = distance / delta_time; 262 float velocity = distance / delta_time;
219 VLOG(0) << "\n Delta time: " << delta_time 263 VLOG(0) << "\n Delta time: " << delta_time
220 << "\n Distance: " << distance 264 << "\n Distance: " << distance
221 << "\n Velocity of click: " << velocity 265 << "\n Velocity of click: " << velocity
222 << "\n Minimum swipe velocity: " 266 << "\n Minimum swipe velocity: "
223 << gesture_detector_config_.minimum_swipe_velocity; 267 << gesture_detector_config_.minimum_swipe_velocity;
224 268
269 // Change to slide gesture if the slide occurred at the right edge.
270 int where = WithinBoundsOfEdge(event.location(), kMaxDistanceFromEdge);
271 if ((where | RIGHT_EDGE) == where) {
272 state_ = SLIDE_GESTURE;
273 VLOG_STATE();
274 return InSlideGesture(event, rewritten_event);
275 }
276
225 // If the user moves fast enough from the initial touch location, start 277 // If the user moves fast enough from the initial touch location, start
226 // gesture detection. Otherwise, jump to the touch exploration mode early. 278 // gesture detection. Otherwise, jump to the touch exploration mode early.
227 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { 279 if (velocity > gesture_detector_config_.minimum_swipe_velocity) {
228 state_ = GESTURE_IN_PROGRESS; 280 state_ = GESTURE_IN_PROGRESS;
229 VLOG_STATE(); 281 VLOG_STATE();
230 return InGestureInProgress(event, rewritten_event); 282 return InGestureInProgress(event, rewritten_event);
231 } 283 }
232 EnterTouchToMouseMode(); 284 EnterTouchToMouseMode();
233 state_ = TOUCH_EXPLORATION; 285 state_ = TOUCH_EXPLORATION;
234 VLOG_STATE(); 286 VLOG_STATE();
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 if (current_touch_ids_.size() != 1) 547 if (current_touch_ids_.size() != 1)
496 return EVENT_REWRITE_DISCARD; 548 return EVENT_REWRITE_DISCARD;
497 549
498 // Rewrite at location of last touch exploration. 550 // Rewrite at location of last touch exploration.
499 rewritten_event->reset( 551 rewritten_event->reset(
500 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, 552 new ui::TouchEvent(ui::ET_TOUCH_RELEASED,
501 last_touch_exploration_->location(), 553 last_touch_exploration_->location(),
502 initial_press_->touch_id(), 554 initial_press_->touch_id(),
503 event.time_stamp())); 555 event.time_stamp()));
504 (*rewritten_event)->set_flags(event.flags()); 556 (*rewritten_event)->set_flags(event.flags());
557 EnterTouchToMouseMode();
505 state_ = TOUCH_EXPLORATION; 558 state_ = TOUCH_EXPLORATION;
506 EnterTouchToMouseMode(); 559 EnterTouchToMouseMode();
507 VLOG_STATE(); 560 VLOG_STATE();
508 return ui::EVENT_REWRITE_REWRITTEN; 561 return ui::EVENT_REWRITE_REWRITTEN;
509 } 562 }
510 NOTREACHED() << "Unexpected event type received: " << event.name(); 563 NOTREACHED() << "Unexpected event type received: " << event.name();
511 return ui::EVENT_REWRITE_CONTINUE; 564 return ui::EVENT_REWRITE_CONTINUE;
512 } 565 }
513 566
514 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease( 567 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease(
515 const ui::TouchEvent& event, 568 const ui::TouchEvent& event,
516 scoped_ptr<ui::Event>* rewritten_event) { 569 scoped_ptr<ui::Event>* rewritten_event) {
517 ui::EventType type = event.type(); 570 ui::EventType type = event.type();
518 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || 571 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED ||
519 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { 572 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) {
520 NOTREACHED() << "Unexpected event type received: " << event.name(); 573 NOTREACHED() << "Unexpected event type received: " << event.name();
521 return ui::EVENT_REWRITE_CONTINUE; 574 return ui::EVENT_REWRITE_CONTINUE;
522 } 575 }
523 if (current_touch_ids_.size() == 0) { 576 if (current_touch_ids_.size() == 0) {
524 state_ = NO_FINGERS_DOWN; 577 state_ = NO_FINGERS_DOWN;
525 VLOG_STATE(); 578 VLOG_STATE();
526 ResetToNoFingersDown(); 579 ResetToNoFingersDown();
527 } 580 }
528 return EVENT_REWRITE_DISCARD; 581 return EVENT_REWRITE_DISCARD;
529 } 582 }
530 583
584 void TouchExplorationController::PlaySoundForTimer() {
585 delegate_->PlayVolumeAdjustSound();
586 }
587
588 ui::EventRewriteStatus TouchExplorationController::InSlideGesture(
589 const ui::TouchEvent& event,
590 scoped_ptr<ui::Event>* rewritten_event) {
591 ui::EventType type = event.type();
592 // If additional fingers are added before a swipe gesture has been registered,
593 // then go into two-to-one passthrough.
594 if (type == ui::ET_TOUCH_PRESSED ||
595 event.touch_id() != initial_press_->touch_id()) {
596 if (tap_timer_.IsRunning())
597 tap_timer_.Stop();
598 if (sound_timer_.IsRunning())
599 sound_timer_.Stop();
600 // Discard any pending gestures.
601 ignore_result(gesture_provider_.GetAndResetPendingGestures());
602 state_ = TWO_TO_ONE_FINGER;
603 last_two_to_one_.reset(new TouchEvent(event));
604 rewritten_event->reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
605 event.location(),
606 event.touch_id(),
607 event.time_stamp()));
608 (*rewritten_event)->set_flags(event.flags());
609 return EVENT_REWRITE_REWRITTEN;
610 }
611
612 VLOG(0) << "Location " << event.location().ToString();
613 // Allows user to return to the edge to adjust the sound if they have left the
614 // boundaries.
615 int where = WithinBoundsOfEdge(event.location(), kSlopDistanceFromEdge);
616 if (((where | RIGHT_EDGE) != where) && (type != ui::ET_TOUCH_RELEASED)) {
617 if (sound_timer_.IsRunning()) {
618 sound_timer_.Stop();
619 }
620 return EVENT_REWRITE_DISCARD;
621 }
622
623 // This can occur if the user leaves the screen edge and then returns to it to
624 // continue adjusting the sound.
625 if (!sound_timer_.IsRunning()) {
626 sound_timer_.Start(FROM_HERE,
627 kSoundDelay,
628 this,
629 &ui::TouchExplorationController::PlaySoundForTimer);
630 delegate_->PlayVolumeAdjustSound();
631 }
632 // The timer should not fire when sliding.
633 if (tap_timer_.IsRunning())
634 tap_timer_.Stop();
635
636 // There should not be more than one finger down.
637 DCHECK(current_touch_ids_.size() <= 1);
638 if (type == ui::ET_TOUCH_MOVED) {
639 gesture_provider_.OnTouchEvent(event);
640 gesture_provider_.OnTouchEventAck(false);
641 }
642 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
643 gesture_provider_.OnTouchEvent(event);
644 gesture_provider_.OnTouchEventAck(false);
645 ignore_result(gesture_provider_.GetAndResetPendingGestures());
646 if (current_touch_ids_.size() == 0)
647 ResetToNoFingersDown();
648 return ui::EVENT_REWRITE_DISCARD;
649 }
650
651 ProcessGestureEvents();
652 return ui::EVENT_REWRITE_DISCARD;
653 }
654
531 void TouchExplorationController::OnTapTimerFired() { 655 void TouchExplorationController::OnTapTimerFired() {
532 switch (state_) { 656 switch (state_) {
533 case SINGLE_TAP_RELEASED: 657 case SINGLE_TAP_RELEASED:
534 ResetToNoFingersDown(); 658 ResetToNoFingersDown();
535 break; 659 break;
536 case TOUCH_EXPLORE_RELEASED: 660 case TOUCH_EXPLORE_RELEASED:
537 ResetToNoFingersDown(); 661 ResetToNoFingersDown();
538 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); 662 last_touch_exploration_.reset(new TouchEvent(*initial_press_));
539 return; 663 return;
540 case SINGLE_TAP_PRESSED: 664 case SINGLE_TAP_PRESSED:
541 case GESTURE_IN_PROGRESS: 665 case GESTURE_IN_PROGRESS:
542 // Discard any pending gestures. 666 // Discard any pending gestures.
543 ignore_result(gesture_provider_.GetAndResetPendingGestures()); 667 ignore_result(gesture_provider_.GetAndResetPendingGestures());
544 EnterTouchToMouseMode(); 668 EnterTouchToMouseMode();
545 state_ = TOUCH_EXPLORATION; 669 state_ = TOUCH_EXPLORATION;
546 VLOG_STATE(); 670 VLOG_STATE();
547 break; 671 break;
548 default: 672 default:
549 return; 673 return;
550 } 674 }
551 scoped_ptr<ui::Event> mouse_move = 675 scoped_ptr<ui::Event> mouse_move =
552 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); 676 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags());
553 DispatchEvent(mouse_move.get()); 677 DispatchEvent(mouse_move.get());
554 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); 678 last_touch_exploration_.reset(new TouchEvent(*initial_press_));
555 } 679 }
556 680
557 void TouchExplorationController::DispatchEvent(ui::Event* event) { 681 void TouchExplorationController::DispatchEvent(ui::Event* event) {
558 if (event_handler_for_testing_) { 682 if (event_handler_for_testing_) {
559 event_handler_for_testing_->OnEvent(event); 683 event_handler_for_testing_->OnEvent(event);
560 return; 684 return;
561 } 685 }
562 ui::EventDispatchDetails result ALLOW_UNUSED = 686 ui::EventDispatchDetails result ALLOW_UNUSED =
563 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); 687 root_window_->GetHost()->dispatcher()->OnEventFromSource(event);
564 } 688 }
565 689
566 void TouchExplorationController::OnGestureEvent(ui::GestureEvent* gesture) { 690 void TouchExplorationController::OnGestureEvent(
691 ui::GestureEvent* gesture) {
567 CHECK(gesture->IsGestureEvent()); 692 CHECK(gesture->IsGestureEvent());
693 ui::EventType type = gesture->type();
568 VLOG(0) << " \n Gesture Triggered: " << gesture->name(); 694 VLOG(0) << " \n Gesture Triggered: " << gesture->name();
569 if (gesture->type() == ui::ET_GESTURE_SWIPE) { 695 if (type == ui::ET_GESTURE_SWIPE && state_ != SLIDE_GESTURE) {
570 if (tap_timer_.IsRunning()) 696 VLOG(0) << "Swipe!";
571 tap_timer_.Stop(); 697 ignore_result(gesture_provider_.GetAndResetPendingGestures());
572 OnSwipeEvent(gesture); 698 OnSwipeEvent(gesture);
573 return; 699 return;
574 } 700 }
575 } 701 }
576 702
577 void TouchExplorationController::ProcessGestureEvents() { 703 void TouchExplorationController::ProcessGestureEvents() {
578 scoped_ptr<ScopedVector<ui::GestureEvent> > gestures( 704 scoped_ptr<ScopedVector<ui::GestureEvent> > gestures(
579 gesture_provider_.GetAndResetPendingGestures()); 705 gesture_provider_.GetAndResetPendingGestures());
580 if (gestures) { 706 if (gestures) {
581 for (ScopedVector<GestureEvent>::iterator i = gestures->begin(); 707 for (ScopedVector<GestureEvent>::iterator i = gestures->begin();
582 i != gestures->end(); 708 i != gestures->end();
583 ++i) { 709 ++i) {
584 OnGestureEvent(*i); 710 if (state_ == SLIDE_GESTURE)
711 SideSlideControl(*i);
712 else
713 OnGestureEvent(*i);
585 } 714 }
586 } 715 }
587 } 716 }
588 717
718 void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) {
719 ui::EventType type = gesture->type();
720 if (!gesture->IsScrollGestureEvent())
721 return;
722
723 gfx::Point location = gesture->location();
724 VLOG(0) << "Location " << location.ToString();
725 root_window_->GetHost()->ConvertPointToNativeScreen(&location);
726 if (WithinBoundsOfEdge(location, kSlopDistanceFromEdge) == SCREEN_CENTER) {
727 VLOG(0) << "No more Slide gesture ";
728 // Discard any pending gestures.
729 ignore_result(gesture_provider_.GetAndResetPendingGestures());
730 if (current_touch_ids_.size() > 1) {
731 state_ = WAIT_FOR_RELEASE;
732 } else if (current_touch_ids_.size() == 0) {
733 ResetToNoFingersDown();
734 } else {
735 EnterTouchToMouseMode();
736 state_ = TOUCH_EXPLORATION;
737 }
738 VLOG_STATE();
739 return;
740 }
741
742 if (type == ET_GESTURE_SCROLL_BEGIN) {
743 delegate_->PlayVolumeAdjustSound();
744 }
745
746 if (type == ET_GESTURE_SCROLL_END) {
747 if (sound_timer_.IsRunning())
748 sound_timer_.Stop();
749 delegate_->PlayVolumeAdjustSound();
750 }
751
752 location = gesture->location();
753 int where = WithinBoundsOfEdge(location, kSlopDistanceFromEdge);
754
755 // If the user is in the corner of the right side of the screen, the volume
756 // will be automatically set to 100% or muted depending on which corner they
757 // are in. Otherwise, the user will be able to adjust the volume by sliding
758 // their finger along the right side of the screen. Volume is relative to
759 // where they are on the right side of the screen.
760 if ((where | RIGHT_EDGE) != where)
761 return;
762
763 if (where == RIGHT_EDGE) {
764 location = gesture->location();
765 root_window_->GetHost()->ConvertPointFromNativeScreen(&location);
766 float volume =
767 100 -
768 ((float)location.y() - kMaxDistanceFromEdge) /
769 (root_window_->bounds().bottom() - 2 * kMaxDistanceFromEdge) * 100;
770 VLOG(0) << "\n Volume = " << volume
771 << "\n Location = " << location.ToString()
772 << "\n Bounds = " << root_window_->bounds().right();
773
774 delegate_->AdjustSound(volume);
775 return;
776 }
777 else if ((where | TOP_EDGE) == where) {
778 delegate_->AdjustSound(100);
779 return;
780 } else if ((where | BOTTOM_EDGE) == where) {
781 delegate_->AdjustSound(0);
782 return;
783 }
784 NOTREACHED() << "Invalid location " << where;
785 }
786
787
589 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { 788 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) {
590 // A swipe gesture contains details for the direction in which the swipe 789 // A swipe gesture contains details for the direction in which the swipe
591 // occurred. 790 // occurred.
592 GestureEventDetails event_details = swipe_gesture->details(); 791 GestureEventDetails event_details = swipe_gesture->details();
593 if (event_details.swipe_left()) { 792 if (event_details.swipe_left()) {
594 DispatchShiftSearchKeyEvent(ui::VKEY_LEFT); 793 DispatchShiftSearchKeyEvent(ui::VKEY_LEFT);
595 return; 794 return;
596 } else if (event_details.swipe_right()) { 795 } else if (event_details.swipe_right()) {
597 DispatchShiftSearchKeyEvent(ui::VKEY_RIGHT); 796 DispatchShiftSearchKeyEvent(ui::VKEY_RIGHT);
598 return; 797 return;
599 } else if (event_details.swipe_up()) { 798 } else if (event_details.swipe_up()) {
600 DispatchShiftSearchKeyEvent(ui::VKEY_UP); 799 DispatchShiftSearchKeyEvent(ui::VKEY_UP);
601 return; 800 return;
602 } else if (event_details.swipe_down()) { 801 } else if (event_details.swipe_down()) {
603 DispatchShiftSearchKeyEvent(ui::VKEY_DOWN); 802 DispatchShiftSearchKeyEvent(ui::VKEY_DOWN);
604 return; 803 return;
605 } 804 }
606 } 805 }
607 806
807 int TouchExplorationController::WithinBoundsOfEdge(gfx::Point point,
808 float bounds) {
809 // Since GetBoundsInScreen is in DIPs but p is not, then p needs to be
810 // converted.
811 root_window_->GetHost()->ConvertPointFromNativeScreen(&point);
812 gfx::Rect window= root_window_->GetBoundsInScreen();
813
814 float left_edge_limit = window.x() + bounds;
815 float right_edge_limit = window.right() - bounds;
816 float top_edge_limit = window.y() + bounds;
817 float bottom_edge_limit = window.bottom() - bounds;
818
819 // Bitwise manipulation in order to determine where on the screen the point
820 // lies. If more than one bit is turned on, then it is a corner where the two
821 // bit/edges intersect. Otherwise, if no bits are turned on, the point must be
822 // in the center of the screen.
823 int result = SCREEN_CENTER;
824 if (point.x() < left_edge_limit)
825 result = result | LEFT_EDGE;
826 if (point.x() > right_edge_limit)
827 result = result | RIGHT_EDGE;
828 if (point.y() < top_edge_limit)
829 result = result | TOP_EDGE;
830 if (point.y() > bottom_edge_limit)
831 result = result | BOTTOM_EDGE;
832 return result;
833 }
834
608 void TouchExplorationController::DispatchShiftSearchKeyEvent( 835 void TouchExplorationController::DispatchShiftSearchKeyEvent(
609 const ui::KeyboardCode direction) { 836 const ui::KeyboardCode direction) {
610 // In order to activate the shortcut shift+search+<arrow key> 837 // In order to activate the shortcut shift+search+<arrow key>
611 // three KeyPressed events must be dispatched in succession along 838 // three KeyPressed events must be dispatched in succession along
612 // with three KeyReleased events. 839 // with three KeyReleased events.
613 ui::KeyEvent shift_down = ui::KeyEvent( 840 ui::KeyEvent shift_down = ui::KeyEvent(
614 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN, false); 841 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN, false);
615 ui::KeyEvent search_down = ui::KeyEvent( 842 ui::KeyEvent search_down = ui::KeyEvent(
616 ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false); 843 ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false);
617 ui::KeyEvent direction_down = 844 ui::KeyEvent direction_down =
(...skipping 29 matching lines...) Expand all
647 void TouchExplorationController::EnterTouchToMouseMode() { 874 void TouchExplorationController::EnterTouchToMouseMode() {
648 aura::client::CursorClient* cursor_client = 875 aura::client::CursorClient* cursor_client =
649 aura::client::GetCursorClient(root_window_); 876 aura::client::GetCursorClient(root_window_);
650 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) 877 if (cursor_client && !cursor_client->IsMouseEventsEnabled())
651 cursor_client->EnableMouseEvents(); 878 cursor_client->EnableMouseEvents();
652 if (cursor_client && cursor_client->IsCursorVisible()) 879 if (cursor_client && cursor_client->IsCursorVisible())
653 cursor_client->HideCursor(); 880 cursor_client->HideCursor();
654 } 881 }
655 882
656 void TouchExplorationController::ResetToNoFingersDown() { 883 void TouchExplorationController::ResetToNoFingersDown() {
884 ProcessGestureEvents();
885 if (sound_timer_.IsRunning())
886 sound_timer_.Stop();
657 state_ = NO_FINGERS_DOWN; 887 state_ = NO_FINGERS_DOWN;
658 VLOG_STATE(); 888 VLOG_STATE();
659 if (tap_timer_.IsRunning()) 889 if (tap_timer_.IsRunning())
660 tap_timer_.Stop(); 890 tap_timer_.Stop();
661 } 891 }
662 892
663 void TouchExplorationController::VlogState(const char* function_name) { 893 void TouchExplorationController::VlogState(const char* function_name) {
664 if (!VLOG_on_) 894 if (!VLOG_on_)
665 return; 895 return;
666 if (prev_state_ == state_) 896 if (prev_state_ == state_)
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 case GESTURE_IN_PROGRESS: 948 case GESTURE_IN_PROGRESS:
719 return "GESTURE_IN_PROGRESS"; 949 return "GESTURE_IN_PROGRESS";
720 case TOUCH_EXPLORE_SECOND_PRESS: 950 case TOUCH_EXPLORE_SECOND_PRESS:
721 return "TOUCH_EXPLORE_SECOND_PRESS"; 951 return "TOUCH_EXPLORE_SECOND_PRESS";
722 case TWO_TO_ONE_FINGER: 952 case TWO_TO_ONE_FINGER:
723 return "TWO_TO_ONE_FINGER"; 953 return "TWO_TO_ONE_FINGER";
724 case PASSTHROUGH: 954 case PASSTHROUGH:
725 return "PASSTHROUGH"; 955 return "PASSTHROUGH";
726 case WAIT_FOR_RELEASE: 956 case WAIT_FOR_RELEASE:
727 return "WAIT_FOR_RELEASE"; 957 return "WAIT_FOR_RELEASE";
958 case SLIDE_GESTURE:
959 return "SLIDE_GESTURE";
728 } 960 }
729 return "Not a state"; 961 return "Not a state";
730 } 962 }
731 963
732 } // namespace ui 964 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698