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

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: split functions and rebased 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
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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 ProcessGestureEvents(); 154 ProcessGestureEvents();
155 } 155 }
156 156
157 // The rest of the processing depends on what state we're in. 157 // The rest of the processing depends on what state we're in.
158 switch (state_) { 158 switch (state_) {
159 case NO_FINGERS_DOWN: 159 case NO_FINGERS_DOWN:
160 return InNoFingersDown(touch_event, rewritten_event); 160 return InNoFingersDown(touch_event, rewritten_event);
161 case SINGLE_TAP_PRESSED: 161 case SINGLE_TAP_PRESSED:
162 return InSingleTapPressed(touch_event, rewritten_event); 162 return InSingleTapPressed(touch_event, rewritten_event);
163 case SINGLE_TAP_RELEASED: 163 case SINGLE_TAP_RELEASED:
164 return InSingleTapReleased(touch_event, rewritten_event);
164 case TOUCH_EXPLORE_RELEASED: 165 case TOUCH_EXPLORE_RELEASED:
165 return InSingleTapOrTouchExploreReleased(touch_event, rewritten_event); 166 return InTouchExploreReleased(touch_event, rewritten_event);
166 case DOUBLE_TAP_PENDING: 167 case DOUBLE_TAP_PENDING:
167 return InDoubleTapPending(touch_event, rewritten_event); 168 return InDoubleTapPending(touch_event, rewritten_event);
168 case TOUCH_RELEASE_PENDING: 169 case TOUCH_RELEASE_PENDING:
169 return InTouchReleasePending(touch_event, rewritten_event); 170 return InTouchReleasePending(touch_event, rewritten_event);
170 case TOUCH_EXPLORATION: 171 case TOUCH_EXPLORATION:
171 return InTouchExploration(touch_event, rewritten_event); 172 return InTouchExploration(touch_event, rewritten_event);
172 case GESTURE_IN_PROGRESS: 173 case GESTURE_IN_PROGRESS:
173 return InGestureInProgress(touch_event, rewritten_event); 174 return InGestureInProgress(touch_event, rewritten_event);
174 case TOUCH_EXPLORE_SECOND_PRESS: 175 case TOUCH_EXPLORE_SECOND_PRESS:
175 return InTouchExploreSecondPress(touch_event, rewritten_event); 176 return InTouchExploreSecondPress(touch_event, rewritten_event);
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 } 296 }
296 EnterTouchToMouseMode(); 297 EnterTouchToMouseMode();
297 SET_STATE(TOUCH_EXPLORATION); 298 SET_STATE(TOUCH_EXPLORATION);
298 return InTouchExploration(event, rewritten_event); 299 return InTouchExploration(event, rewritten_event);
299 } 300 }
300 NOTREACHED(); 301 NOTREACHED();
301 return ui::EVENT_REWRITE_CONTINUE; 302 return ui::EVENT_REWRITE_CONTINUE;
302 } 303 }
303 304
304 ui::EventRewriteStatus 305 ui::EventRewriteStatus
305 TouchExplorationController::InSingleTapOrTouchExploreReleased( 306 TouchExplorationController::InSingleTapReleased(
306 const ui::TouchEvent& event, 307 const ui::TouchEvent& event,
307 scoped_ptr<ui::Event>* rewritten_event) { 308 scoped_ptr<ui::Event>* rewritten_event) {
308 const ui::EventType type = event.type(); 309 const ui::EventType type = event.type();
309 // If there is more than one finger down, then discard to wait until no 310 // If there is more than one finger down, then discard to wait until no
310 // fingers are down. 311 // fingers are down.
311 if (current_touch_ids_.size() > 1) { 312 if (current_touch_ids_.size() > 1) {
312 SET_STATE(WAIT_FOR_NO_FINGERS); 313 SET_STATE(WAIT_FOR_NO_FINGERS);
313 return ui::EVENT_REWRITE_DISCARD; 314 return ui::EVENT_REWRITE_DISCARD;
314 } 315 }
315 if (type == ui::ET_TOUCH_PRESSED) { 316 if (type == ui::ET_TOUCH_PRESSED) {
316 // If there is no touch exploration yet, we can't send a click, so discard. 317 // If there is no touch exploration yet, we can't send a click, so discard
318 // and wait for no fingers.
317 if (!last_touch_exploration_) { 319 if (!last_touch_exploration_) {
318 tap_timer_.Stop(); 320 tap_timer_.Stop();
321 SET_STATE(WAIT_FOR_NO_FINGERS);
319 return ui::EVENT_REWRITE_DISCARD; 322 return ui::EVENT_REWRITE_DISCARD;
320 } 323 }
321 // This is the second tap in a double-tap (or double tap-hold). 324 // This is the second tap in a double-tap (or double tap-hold).
322 // We set the tap timer. If it fires before the user lifts their finger, 325 // We set the passthrough timer. If it fires before the user lifts their
323 // one-finger passthrough begins. Otherwise, there is a touch press and 326 // finger, one-finger passthrough begins. Otherwise, there is a touch
324 // release at the location of the last touch exploration. 327 // press and release at the location of the last touch exploration.
325 SET_STATE(DOUBLE_TAP_PENDING); 328 SET_STATE(DOUBLE_TAP_PENDING);
329 // Initial press now holds the intial double tap press - this event.
330 initial_press_.reset(new ui::TouchEvent(event));
326 // The old tap timer (from the initial click) is stopped if it is still 331 // The old tap timer (from the initial click) is stopped if it is still
327 // going, and the new one is set. 332 // going, and the passthrough timer is set.
328 tap_timer_.Stop(); 333 tap_timer_.Stop();
329 StartTapTimer(); 334 passthrough_timer_.Start(
335 FROM_HERE,
336 gesture_detector_config_.longpress_timeout,
337 this,
338 &TouchExplorationController::OnPassthroughTimerFired);
330 // This will update as the finger moves before a possible passthrough, and 339 // This will update as the finger moves before a possible passthrough, and
331 // will determine the offset. 340 // will determine the offset.
332 last_unused_finger_event_.reset(new ui::TouchEvent(event)); 341 last_unused_finger_event_.reset(new ui::TouchEvent(event));
333 return ui::EVENT_REWRITE_DISCARD; 342 return ui::EVENT_REWRITE_DISCARD;
334 } else if (type == ui::ET_TOUCH_RELEASED && !last_touch_exploration_) {
335 // If the previous press was discarded, we need to also handle its
336 // release.
337 if (current_touch_ids_.size() == 0) {
338 SET_STATE(NO_FINGERS_DOWN);
339 }
340 return ui::EVENT_REWRITE_DISCARD;
341 } else if (type == ui::ET_TOUCH_MOVED) { 343 } else if (type == ui::ET_TOUCH_MOVED) {
342 return ui::EVENT_REWRITE_DISCARD; 344 return ui::EVENT_REWRITE_DISCARD;
343 } 345 }
346 NOTREACHED();
347 return ui::EVENT_REWRITE_CONTINUE;
348 }
349
350 ui::EventRewriteStatus
351 TouchExplorationController::InTouchExploreReleased(
352 const ui::TouchEvent& event,
353 scoped_ptr<ui::Event>* rewritten_event) {
354 const ui::EventType type = event.type();
355 // If there is more than one finger down, then discard to wait until no
356 // fingers are down.
357 if (current_touch_ids_.size() > 1) {
358 SET_STATE(WAIT_FOR_NO_FINGERS);
359 return ui::EVENT_REWRITE_DISCARD;
360 }
361 if (type == ui::ET_TOUCH_PRESSED) {
362 // This is the initial "press" (location, time, and touch id) of a single
363 // tap click.
364 initial_press_.reset(new ui::TouchEvent(event));
365 rewritten_event->reset(
366 new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
367 last_touch_exploration_->location(),
368 initial_press_->touch_id(),
369 event.time_stamp()));
370 (*rewritten_event)->set_flags(event.flags());
371 SET_STATE(TOUCH_RELEASE_PENDING);
372 return ui::EVENT_REWRITE_REWRITTEN;
373 } else if (type == ui::ET_TOUCH_MOVED) {
374 return ui::EVENT_REWRITE_DISCARD;
375 }
344 NOTREACHED(); 376 NOTREACHED();
345 return ui::EVENT_REWRITE_CONTINUE; 377 return ui::EVENT_REWRITE_CONTINUE;
346 } 378 }
347 379
348 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPending( 380 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPending(
349 const ui::TouchEvent& event, 381 const ui::TouchEvent& event,
350 scoped_ptr<ui::Event>* rewritten_event) { 382 scoped_ptr<ui::Event>* rewritten_event) {
351 const ui::EventType type = event.type(); 383 const ui::EventType type = event.type();
352 if (type == ui::ET_TOUCH_PRESSED) { 384 if (type == ui::ET_TOUCH_PRESSED) {
353 return ui::EVENT_REWRITE_DISCARD; 385 return ui::EVENT_REWRITE_DISCARD;
354 } else if (type == ui::ET_TOUCH_MOVED) { 386 } else if (type == ui::ET_TOUCH_MOVED) {
355 // If the user moves far enough from the initial touch location (outside 387 // If the user moves far enough from the initial touch location (outside
356 // the "slop" region, jump to passthrough mode early. 388 // the "slop" region, jump to passthrough mode early.
357 float delta = (event.location() - initial_press_->location()).Length(); 389 float delta = (event.location() - initial_press_->location()).Length();
358 if (delta > gesture_detector_config_.touch_slop) { 390 if (delta > gesture_detector_config_.touch_slop) {
359 tap_timer_.Stop(); 391 passthrough_timer_.Stop();
360 OnTapTimerFired(); 392 if (VLOG_on_)
393 VLOG(0) << "Finger left slop and is entering passthrough";
394 OnPassthroughTimerFired();
361 } 395 }
362 return EVENT_REWRITE_DISCARD; 396 return EVENT_REWRITE_DISCARD;
363 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 397 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
364 if (current_touch_ids_.size() != 0) 398 if (current_touch_ids_.size() != 0)
365 return EVENT_REWRITE_DISCARD; 399 return EVENT_REWRITE_DISCARD;
366 400
401 // Now it is recognized that the user was doing a double tap to click.
402 // The passthrough timer is stopped and a touch press and release are
403 // dispatched.
404 passthrough_timer_.Stop();
405
367 scoped_ptr<ui::TouchEvent> touch_press; 406 scoped_ptr<ui::TouchEvent> touch_press;
368 touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, 407 touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
369 last_touch_exploration_->location(), 408 last_touch_exploration_->location(),
370 initial_press_->touch_id(), 409 initial_press_->touch_id(),
371 event.time_stamp())); 410 event.time_stamp()));
372 DispatchEvent(touch_press.get()); 411 DispatchEvent(touch_press.get());
373 412
374 rewritten_event->reset( 413 rewritten_event->reset(
375 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, 414 new ui::TouchEvent(ui::ET_TOUCH_RELEASED,
376 last_touch_exploration_->location(), 415 last_touch_exploration_->location(),
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 736
698 void TouchExplorationController::OnTapTimerFired() { 737 void TouchExplorationController::OnTapTimerFired() {
699 switch (state_) { 738 switch (state_) {
700 case SINGLE_TAP_RELEASED: 739 case SINGLE_TAP_RELEASED:
701 SET_STATE(NO_FINGERS_DOWN); 740 SET_STATE(NO_FINGERS_DOWN);
702 break; 741 break;
703 case TOUCH_EXPLORE_RELEASED: 742 case TOUCH_EXPLORE_RELEASED:
704 SET_STATE(NO_FINGERS_DOWN); 743 SET_STATE(NO_FINGERS_DOWN);
705 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); 744 last_touch_exploration_.reset(new TouchEvent(*initial_press_));
706 return; 745 return;
707 case DOUBLE_TAP_PENDING: {
708 SET_STATE(ONE_FINGER_PASSTHROUGH);
709 passthrough_offset_ = last_unused_finger_event_->location() -
710 last_touch_exploration_->location();
711 scoped_ptr<ui::TouchEvent> passthrough_press(
712 new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
713 last_touch_exploration_->location(),
714 last_unused_finger_event_->touch_id(),
715 Now()));
716 DispatchEvent(passthrough_press.get());
717 return;
718 }
719 case SINGLE_TAP_PRESSED: 746 case SINGLE_TAP_PRESSED:
720 if (passthrough_timer_.IsRunning()) 747 if (passthrough_timer_.IsRunning())
721 return; 748 return;
722 case GESTURE_IN_PROGRESS: 749 case GESTURE_IN_PROGRESS:
723 // If only one finger is down, go into touch exploration. 750 // If only one finger is down, go into touch exploration.
724 if (current_touch_ids_.size() == 1) { 751 if (current_touch_ids_.size() == 1) {
725 EnterTouchToMouseMode(); 752 EnterTouchToMouseMode();
726 SET_STATE(TOUCH_EXPLORATION); 753 SET_STATE(TOUCH_EXPLORATION);
727 break; 754 break;
728 } 755 }
729 // Otherwise wait for all fingers to be lifted. 756 // Otherwise wait for all fingers to be lifted.
730 SET_STATE(WAIT_FOR_NO_FINGERS); 757 SET_STATE(WAIT_FOR_NO_FINGERS);
731 return; 758 return;
732 case TWO_FINGER_TAP: 759 case TWO_FINGER_TAP:
733 SET_STATE(WAIT_FOR_NO_FINGERS); 760 SET_STATE(WAIT_FOR_NO_FINGERS);
734 break; 761 break;
735 default: 762 default:
763 NOTREACHED() << "tap timer fired in unrecognized state";
aboxhall 2014/08/15 18:30:32 Suggestion: log the state?
evy 2014/08/15 18:39:12 Done.
736 return; 764 return;
737 } 765 }
738 EnterTouchToMouseMode(); 766 EnterTouchToMouseMode();
739 scoped_ptr<ui::Event> mouse_move = 767 scoped_ptr<ui::Event> mouse_move =
740 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); 768 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags());
741 DispatchEvent(mouse_move.get()); 769 DispatchEvent(mouse_move.get());
742 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); 770 last_touch_exploration_.reset(new TouchEvent(*initial_press_));
743 } 771 }
744 772
745 void TouchExplorationController::OnPassthroughTimerFired() { 773 void TouchExplorationController::OnPassthroughTimerFired() {
746 // The passthrough timer will only fire if if the user has held a finger in 774 switch (state_) {
747 // one of the passthrough corners for the duration of the passthrough timeout. 775 case SINGLE_TAP_PRESSED:
776 case TOUCH_EXPLORATION:
777 case GESTURE_IN_PROGRESS: {
778 // The timer will only fire in this state if if the user has held a finger
779 // in one of the passthrough corners for the duration of the passthrough
780 // timeout.
748 781
749 // Check that initial press isn't null. Also a check that if the initial 782 // Check that initial press isn't null. Also a check that if the initial
750 // corner press was released, then it should not be in corner passthrough. 783 // corner press was released, then it should not be in corner passthrough.
751 if (!initial_press_ || 784 if (!initial_press_ ||
752 touch_locations_.find(initial_press_->touch_id()) != 785 touch_locations_.find(initial_press_->touch_id()) !=
753 touch_locations_.end()) { 786 touch_locations_.end()) {
754 LOG(ERROR) << "No initial press or the initial press has been released."; 787 LOG(ERROR)
788 << "No initial press or the initial press has been released.";
789 }
790
791 gfx::Point location =
792 ToRoundedPoint(touch_locations_[initial_press_->touch_id()]);
793 int corner = FindEdgesWithinBounds(location, kSlopDistanceFromEdge);
794 if (corner != BOTTOM_LEFT_CORNER && corner != BOTTOM_RIGHT_CORNER)
795 return;
796
797 SET_STATE(CORNER_PASSTHROUGH);
798 break;
799 }
800 case DOUBLE_TAP_PENDING: {
dmazzoni 2014/08/15 16:54:45 Nit: I don't think you need { } in this case. You
evy 2014/08/15 17:03:03 I declare passthrough_press
dmazzoni 2014/08/15 17:29:05 Oh, of course. Nevermind, this is fine.
801 // Enter one finger passthrough mode.
802 SET_STATE(ONE_FINGER_PASSTHROUGH);
803 passthrough_offset_ = last_unused_finger_event_->location() -
804 last_touch_exploration_->location();
805 scoped_ptr<ui::TouchEvent> passthrough_press(
806 new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
807 last_touch_exploration_->location(),
808 last_unused_finger_event_->touch_id(),
809 Now()));
810 DispatchEvent(passthrough_press.get());
811 break;
812 }
813 default:
814 NOTREACHED() << "passthrough timer fired in unrecognized state";
aboxhall 2014/08/15 18:30:32 Similarly, maybe log state?
evy 2014/08/15 18:39:12 Done.
815 return;
755 } 816 }
756
757 gfx::Point location =
758 ToRoundedPoint(touch_locations_[initial_press_->touch_id()]);
759 int corner = FindEdgesWithinBounds(location, kSlopDistanceFromEdge);
760 if (corner != BOTTOM_LEFT_CORNER && corner != BOTTOM_RIGHT_CORNER)
761 return;
762
763 if (sound_timer_.IsRunning()) 817 if (sound_timer_.IsRunning())
764 sound_timer_.Stop(); 818 sound_timer_.Stop();
765 delegate_->PlayPassthroughEarcon(); 819 delegate_->PlayPassthroughEarcon();
766 SET_STATE(CORNER_PASSTHROUGH);
767 return;
768 } 820 }
769 821
770 void TouchExplorationController::DispatchEvent(ui::Event* event) { 822 void TouchExplorationController::DispatchEvent(ui::Event* event) {
771 ui::EventDispatchDetails result ALLOW_UNUSED = 823 ui::EventDispatchDetails result ALLOW_UNUSED =
772 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); 824 root_window_->GetHost()->dispatcher()->OnEventFromSource(event);
773 } 825 }
774 826
775 // This is an override for a function that is only called for timer-based events 827 // This is an override for a function that is only called for timer-based events
776 // like long press. Events that are created synchronously as a result of 828 // like long press. Events that are created synchronously as a result of
777 // certain touch events are added to the vector accessible via 829 // certain touch events are added to the vector accessible via
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 up_swipe_gestures_[4] = BindKeyEventWithFlags(VKEY_BROWSER_HOME, ui::EF_NONE); 1199 up_swipe_gestures_[4] = BindKeyEventWithFlags(VKEY_BROWSER_HOME, ui::EF_NONE);
1148 down_swipe_gestures_[4] = 1200 down_swipe_gestures_[4] =
1149 BindKeyEventWithFlags(VKEY_BROWSER_REFRESH, ui::EF_NONE); 1201 BindKeyEventWithFlags(VKEY_BROWSER_REFRESH, ui::EF_NONE);
1150 } 1202 }
1151 1203
1152 const float TouchExplorationController::GetSplitTapTouchSlop() { 1204 const float TouchExplorationController::GetSplitTapTouchSlop() {
1153 return gesture_detector_config_.touch_slop * 3; 1205 return gesture_detector_config_.touch_slop * 3;
1154 } 1206 }
1155 1207
1156 } // namespace ui 1208 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698