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

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

Issue 465543003: Modified state flow for touch explore released in touch_exploration_controller. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: corner passthrough can be entered from more states Created 6 years, 4 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
« no previous file with comments | « no previous file | ui/chromeos/touch_exploration_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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" 7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_number_conversions.h"
9 #include "base/time/default_tick_clock.h" 9 #include "base/time/default_tick_clock.h"
10 #include "ui/aura/client/cursor_client.h" 10 #include "ui/aura/client/cursor_client.h"
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 const ui::TouchEvent& event, 306 const ui::TouchEvent& event,
307 scoped_ptr<ui::Event>* rewritten_event) { 307 scoped_ptr<ui::Event>* rewritten_event) {
308 const ui::EventType type = event.type(); 308 const ui::EventType type = event.type();
309 // If there is more than one finger down, then discard to wait until no 309 // If there is more than one finger down, then discard to wait until no
310 // fingers are down. 310 // fingers are down.
311 if (current_touch_ids_.size() > 1) { 311 if (current_touch_ids_.size() > 1) {
312 SET_STATE(WAIT_FOR_NO_FINGERS); 312 SET_STATE(WAIT_FOR_NO_FINGERS);
313 return ui::EVENT_REWRITE_DISCARD; 313 return ui::EVENT_REWRITE_DISCARD;
314 } 314 }
315 if (type == ui::ET_TOUCH_PRESSED) { 315 if (type == ui::ET_TOUCH_PRESSED) {
316 // If there is no touch exploration yet, we can't send a click, so discard. 316 // If there is no touch exploration yet, we can't send a click, so discard
317 // and wait for no fingers.
317 if (!last_touch_exploration_) { 318 if (!last_touch_exploration_) {
318 tap_timer_.Stop(); 319 tap_timer_.Stop();
320 SET_STATE(WAIT_FOR_NO_FINGERS);
319 return ui::EVENT_REWRITE_DISCARD; 321 return ui::EVENT_REWRITE_DISCARD;
320 } 322 }
321 // This is the second tap in a double-tap (or double tap-hold). 323 if (state_ == SINGLE_TAP_RELEASED) {
dmazzoni 2014/08/15 15:34:01 This "if/else" block is now more than half of the
evy 2014/08/15 16:14:57 Done.
322 // We set the tap timer. If it fires before the user lifts their finger, 324 // This is the second tap in a double-tap (or double tap-hold).
323 // one-finger passthrough begins. Otherwise, there is a touch press and 325 // We set the passthrough timer. If it fires before the user lifts their
324 // release at the location of the last touch exploration. 326 // finger, one-finger passthrough begins. Otherwise, there is a touch
325 SET_STATE(DOUBLE_TAP_PENDING); 327 // press and release at the location of the last touch exploration.
326 // The old tap timer (from the initial click) is stopped if it is still 328 SET_STATE(DOUBLE_TAP_PENDING);
327 // going, and the new one is set. 329 // Initial press now holds the intial double tap press - this event.
328 tap_timer_.Stop(); 330 initial_press_.reset(new ui::TouchEvent(event));
329 StartTapTimer(); 331 // The old tap timer (from the initial click) is stopped if it is still
330 // This will update as the finger moves before a possible passthrough, and 332 // going, and the passthrough timer is set.
331 // will determine the offset. 333 tap_timer_.Stop();
332 last_unused_finger_event_.reset(new ui::TouchEvent(event)); 334 passthrough_timer_.Start(
333 return ui::EVENT_REWRITE_DISCARD; 335 FROM_HERE,
334 } else if (type == ui::ET_TOUCH_RELEASED && !last_touch_exploration_) { 336 gesture_detector_config_.longpress_timeout,
335 // If the previous press was discarded, we need to also handle its 337 this,
336 // release. 338 &TouchExplorationController::OnPassthroughTimerFired);
337 if (current_touch_ids_.size() == 0) { 339 // This will update as the finger moves before a possible passthrough, and
338 SET_STATE(NO_FINGERS_DOWN); 340 // will determine the offset.
341 last_unused_finger_event_.reset(new ui::TouchEvent(event));
342 return ui::EVENT_REWRITE_DISCARD;
343 } else if (state_ == TOUCH_EXPLORE_RELEASED) {
344 // This is the initial "press" (location, time, and touch id) of a single
345 // tap click.
346 initial_press_.reset(new ui::TouchEvent(event));
347 rewritten_event->reset(
348 new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
349 last_touch_exploration_->location(),
350 initial_press_->touch_id(),
351 event.time_stamp()));
352 (*rewritten_event)->set_flags(event.flags());
353 SET_STATE(TOUCH_RELEASE_PENDING);
354 return ui::EVENT_REWRITE_REWRITTEN;
339 } 355 }
340 return ui::EVENT_REWRITE_DISCARD;
341 } else if (type == ui::ET_TOUCH_MOVED) { 356 } else if (type == ui::ET_TOUCH_MOVED) {
342 return ui::EVENT_REWRITE_DISCARD; 357 return ui::EVENT_REWRITE_DISCARD;
343 } 358 }
344 NOTREACHED(); 359 NOTREACHED();
345 return ui::EVENT_REWRITE_CONTINUE; 360 return ui::EVENT_REWRITE_CONTINUE;
346 } 361 }
347 362
348 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPending( 363 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPending(
349 const ui::TouchEvent& event, 364 const ui::TouchEvent& event,
350 scoped_ptr<ui::Event>* rewritten_event) { 365 scoped_ptr<ui::Event>* rewritten_event) {
351 const ui::EventType type = event.type(); 366 const ui::EventType type = event.type();
352 if (type == ui::ET_TOUCH_PRESSED) { 367 if (type == ui::ET_TOUCH_PRESSED) {
353 return ui::EVENT_REWRITE_DISCARD; 368 return ui::EVENT_REWRITE_DISCARD;
354 } else if (type == ui::ET_TOUCH_MOVED) { 369 } else if (type == ui::ET_TOUCH_MOVED) {
355 // If the user moves far enough from the initial touch location (outside 370 // If the user moves far enough from the initial touch location (outside
356 // the "slop" region, jump to passthrough mode early. 371 // the "slop" region, jump to passthrough mode early.
357 float delta = (event.location() - initial_press_->location()).Length(); 372 float delta = (event.location() - initial_press_->location()).Length();
358 if (delta > gesture_detector_config_.touch_slop) { 373 if (delta > gesture_detector_config_.touch_slop) {
359 tap_timer_.Stop(); 374 passthrough_timer_.Stop();
360 OnTapTimerFired(); 375 if (VLOG_on_)
376 VLOG(0) << "Finger left slop and is entering passthrough";
377 OnPassthroughTimerFired();
361 } 378 }
362 return EVENT_REWRITE_DISCARD; 379 return EVENT_REWRITE_DISCARD;
363 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 380 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
364 if (current_touch_ids_.size() != 0) 381 if (current_touch_ids_.size() != 0)
365 return EVENT_REWRITE_DISCARD; 382 return EVENT_REWRITE_DISCARD;
366 383
384 // Now it is recognized that the user was doing a double tap to click.
385 // The passthrough timer is stopped and a touch press and release are
386 // dispatched.
387 passthrough_timer_.Stop();
388
367 scoped_ptr<ui::TouchEvent> touch_press; 389 scoped_ptr<ui::TouchEvent> touch_press;
368 touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, 390 touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
369 last_touch_exploration_->location(), 391 last_touch_exploration_->location(),
370 initial_press_->touch_id(), 392 initial_press_->touch_id(),
371 event.time_stamp())); 393 event.time_stamp()));
372 DispatchEvent(touch_press.get()); 394 DispatchEvent(touch_press.get());
373 395
374 rewritten_event->reset( 396 rewritten_event->reset(
375 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, 397 new ui::TouchEvent(ui::ET_TOUCH_RELEASED,
376 last_touch_exploration_->location(), 398 last_touch_exploration_->location(),
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 682
661 void TouchExplorationController::OnTapTimerFired() { 683 void TouchExplorationController::OnTapTimerFired() {
662 switch (state_) { 684 switch (state_) {
663 case SINGLE_TAP_RELEASED: 685 case SINGLE_TAP_RELEASED:
664 SET_STATE(NO_FINGERS_DOWN); 686 SET_STATE(NO_FINGERS_DOWN);
665 break; 687 break;
666 case TOUCH_EXPLORE_RELEASED: 688 case TOUCH_EXPLORE_RELEASED:
667 SET_STATE(NO_FINGERS_DOWN); 689 SET_STATE(NO_FINGERS_DOWN);
668 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); 690 last_touch_exploration_.reset(new TouchEvent(*initial_press_));
669 return; 691 return;
670 case DOUBLE_TAP_PENDING: {
671 SET_STATE(ONE_FINGER_PASSTHROUGH);
672 passthrough_offset_ = last_unused_finger_event_->location() -
673 last_touch_exploration_->location();
674 scoped_ptr<ui::TouchEvent> passthrough_press(
675 new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
676 last_touch_exploration_->location(),
677 last_unused_finger_event_->touch_id(),
678 Now()));
679 DispatchEvent(passthrough_press.get());
680 return;
681 }
682 case SINGLE_TAP_PRESSED: 692 case SINGLE_TAP_PRESSED:
683 if (passthrough_timer_.IsRunning()) 693 if (passthrough_timer_.IsRunning())
684 return; 694 return;
685 case GESTURE_IN_PROGRESS: 695 case GESTURE_IN_PROGRESS:
686 // If only one finger is down, go into touch exploration. 696 // If only one finger is down, go into touch exploration.
687 if (current_touch_ids_.size() == 1) { 697 if (current_touch_ids_.size() == 1) {
688 SET_STATE(TOUCH_EXPLORATION); 698 SET_STATE(TOUCH_EXPLORATION);
689 break; 699 break;
690 } 700 }
691 // Otherwise wait for all fingers to be lifted. 701 // Otherwise wait for all fingers to be lifted.
692 SET_STATE(WAIT_FOR_NO_FINGERS); 702 SET_STATE(WAIT_FOR_NO_FINGERS);
693 return; 703 return;
694 case TWO_FINGER_TAP: 704 case TWO_FINGER_TAP:
695 SET_STATE(WAIT_FOR_NO_FINGERS); 705 SET_STATE(WAIT_FOR_NO_FINGERS);
696 break; 706 break;
697 default: 707 default:
708 NOTREACHED() << "tap timer fired in unrecognized state";
698 return; 709 return;
699 } 710 }
700 EnterTouchToMouseMode(); 711 EnterTouchToMouseMode();
701 scoped_ptr<ui::Event> mouse_move = 712 scoped_ptr<ui::Event> mouse_move =
702 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); 713 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags());
703 DispatchEvent(mouse_move.get()); 714 DispatchEvent(mouse_move.get());
704 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); 715 last_touch_exploration_.reset(new TouchEvent(*initial_press_));
705 } 716 }
706 717
707 void TouchExplorationController::OnPassthroughTimerFired() { 718 void TouchExplorationController::OnPassthroughTimerFired() {
708 // The passthrough timer will only fire if if the user has held a finger in 719 switch (state_) {
709 // one of the passthrough corners for the duration of the passthrough timeout. 720 case SINGLE_TAP_PRESSED:
721 case TOUCH_EXPLORATION:
722 case GESTURE_IN_PROGRESS: {
723 // The timer will only fire in this state if if the user has held a finger
724 // in one of the passthrough corners for the duration of the passthrough
725 // timeout.
710 726
711 // Check that initial press isn't null. Also a check that if the initial 727 // Check that initial press isn't null. Also a check that if the initial
712 // corner press was released, then it should not be in corner passthrough. 728 // corner press was released, then it should not be in corner passthrough.
713 if (!initial_press_ || 729 if (!initial_press_ ||
714 touch_locations_.find(initial_press_->touch_id()) != 730 touch_locations_.find(initial_press_->touch_id()) !=
715 touch_locations_.end()) { 731 touch_locations_.end()) {
716 LOG(ERROR) << "No initial press or the initial press has been released."; 732 LOG(ERROR)
733 << "No initial press or the initial press has been released.";
734 }
735
736 gfx::Point location =
737 ToRoundedPoint(touch_locations_[initial_press_->touch_id()]);
738 int corner = FindEdgesWithinBounds(location, kSlopDistanceFromEdge);
739 if (corner != BOTTOM_LEFT_CORNER && corner != BOTTOM_RIGHT_CORNER)
740 return;
741
742 SET_STATE(CORNER_PASSTHROUGH);
743 break;
744 }
745 case DOUBLE_TAP_PENDING: {
746 // Enter one finger passthrough mode.
747 SET_STATE(ONE_FINGER_PASSTHROUGH);
748 passthrough_offset_ = last_unused_finger_event_->location() -
749 last_touch_exploration_->location();
750 scoped_ptr<ui::TouchEvent> passthrough_press(
751 new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
752 last_touch_exploration_->location(),
753 last_unused_finger_event_->touch_id(),
754 Now()));
755 DispatchEvent(passthrough_press.get());
756 break;
757 }
758 default:
759 NOTREACHED() << "passthrough timer fired in unrecognized state";
760 return;
717 } 761 }
718
719 gfx::Point location =
720 ToRoundedPoint(touch_locations_[initial_press_->touch_id()]);
721 int corner = FindEdgesWithinBounds(location, kSlopDistanceFromEdge);
722 if (corner != BOTTOM_LEFT_CORNER && corner != BOTTOM_RIGHT_CORNER)
723 return;
724
725 if (sound_timer_.IsRunning()) 762 if (sound_timer_.IsRunning())
726 sound_timer_.Stop(); 763 sound_timer_.Stop();
727 delegate_->PlayPassthroughEarcon(); 764 delegate_->PlayPassthroughEarcon();
728 SET_STATE(CORNER_PASSTHROUGH);
729 return;
730 } 765 }
731 766
732 void TouchExplorationController::DispatchEvent(ui::Event* event) { 767 void TouchExplorationController::DispatchEvent(ui::Event* event) {
733 ui::EventDispatchDetails result ALLOW_UNUSED = 768 ui::EventDispatchDetails result ALLOW_UNUSED =
734 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); 769 root_window_->GetHost()->dispatcher()->OnEventFromSource(event);
735 } 770 }
736 771
737 // This is an override for a function that is only called for timer-based events 772 // This is an override for a function that is only called for timer-based events
738 // like long press. Events that are created synchronously as a result of 773 // like long press. Events that are created synchronously as a result of
739 // certain touch events are added to the vector accessible via 774 // certain touch events are added to the vector accessible via
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
1105 left_swipe_gestures_[4] = 1140 left_swipe_gestures_[4] =
1106 BindKeyEventWithFlags(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE); 1141 BindKeyEventWithFlags(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
1107 right_swipe_gestures_[4] = 1142 right_swipe_gestures_[4] =
1108 BindKeyEventWithFlags(VKEY_BRIGHTNESS_UP, ui::EF_NONE); 1143 BindKeyEventWithFlags(VKEY_BRIGHTNESS_UP, ui::EF_NONE);
1109 up_swipe_gestures_[4] = BindKeyEventWithFlags(VKEY_BROWSER_HOME, ui::EF_NONE); 1144 up_swipe_gestures_[4] = BindKeyEventWithFlags(VKEY_BROWSER_HOME, ui::EF_NONE);
1110 down_swipe_gestures_[4] = 1145 down_swipe_gestures_[4] =
1111 BindKeyEventWithFlags(VKEY_BROWSER_REFRESH, ui::EF_NONE); 1146 BindKeyEventWithFlags(VKEY_BROWSER_REFRESH, ui::EF_NONE);
1112 } 1147 }
1113 1148
1114 } // namespace ui 1149 } // namespace ui
OLDNEW
« no previous file with comments | « no previous file | ui/chromeos/touch_exploration_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698