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

Unified Diff: ui/chromeos/touch_exploration_controller.cc

Issue 410783002: Corner Passthrough for Accessibility (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@side-gestures
Patch Set: Addressed Alice's Comments 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/chromeos/touch_exploration_controller.h ('k') | ui/chromeos/touch_exploration_controller_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/chromeos/touch_exploration_controller.cc
diff --git a/ui/chromeos/touch_exploration_controller.cc b/ui/chromeos/touch_exploration_controller.cc
index 3670f1e948f213908d1884d9f844eacf35916a5c..4b31d4c56bc87843274c8aff8e7bd250a44f2311 100644
--- a/ui/chromeos/touch_exploration_controller.cc
+++ b/ui/chromeos/touch_exploration_controller.cc
@@ -25,6 +25,10 @@ namespace {
// Delay between adjustment sounds.
const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150);
+// Delay before corner passthrough activates.
+const base::TimeDelta kCornerPassthroughDelay =
+ base::TimeDelta::FromMilliseconds(700);
+
// In ChromeOS, VKEY_LWIN is synonymous for the search key.
const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN;
} // namespace
@@ -68,6 +72,13 @@ ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
// this event under this new state.
}
+ if (passthrough_timer_.IsRunning() &&
+ event.time_stamp() - initial_press_->time_stamp() >
+ gesture_detector_config_.longpress_timeout) {
+ passthrough_timer_.Stop();
+ OnPassthroughTimerFired();
+ }
+
const ui::EventType type = touch_event.type();
const gfx::PointF& location = touch_event.location_f();
const int touch_id = touch_event.touch_id();
@@ -81,11 +92,14 @@ ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
// In order to avoid accidentally double tapping when moving off the edge of
// the screen, the state will be rewritten to NoFingersDown.
TouchEvent touch_event = static_cast<const TouchEvent&>(event);
- if (FindEdgesWithinBounds(touch_event.location(), kLeavingScreenEdge) !=
- NO_EDGE) {
- if (current_touch_ids_.size() == 0) {
- ResetToNoFingersDown();
- }
+ gfx::Point edges = touch_event.location();
+ if (FindEdgesWithinBounds(edges, kLeavingScreenEdge) != NO_EDGE) {
+ // Indicates to the user that they are leaving the screen.
+ if (VLOG_on_)
+ VLOG(0) << "Leaving the Screen";
+ delegate_->PlayExitScreenEarcon();
+ if (current_touch_ids_.size() == 0)
+ ResetToNoFingersDown();
}
std::vector<int>::iterator it = std::find(
@@ -128,6 +142,8 @@ ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
return InGestureInProgress(touch_event, rewritten_event);
case TOUCH_EXPLORE_SECOND_PRESS:
return InTouchExploreSecondPress(touch_event, rewritten_event);
+ case CORNER_PASSTHROUGH:
+ return InCornerPassthrough(touch_event, rewritten_event);
case SLIDE_GESTURE:
return InSlideGesture(touch_event, rewritten_event);
case ONE_FINGER_PASSTHROUGH:
@@ -148,25 +164,65 @@ ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent(
ui::EventRewriteStatus TouchExplorationController::InNoFingersDown(
const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) {
const ui::EventType type = event.type();
- if (type == ui::ET_TOUCH_PRESSED) {
- initial_press_.reset(new TouchEvent(event));
- last_unused_finger_event_.reset(new TouchEvent(event));
- StartTapTimer();
- gesture_provider_.OnTouchEvent(event);
- gesture_provider_.OnTouchEventAck(false);
- ProcessGestureEvents();
- state_ = SINGLE_TAP_PRESSED;
- VLOG_STATE();
- return ui::EVENT_REWRITE_DISCARD;
+ if (type != ui::ET_TOUCH_PRESSED) {
+ NOTREACHED() << "Unexpected event type received: " << event.name();
+ return ui::EVENT_REWRITE_CONTINUE;
}
- NOTREACHED() << "Unexpected event type received: " << event.name();
- return ui::EVENT_REWRITE_CONTINUE;
+
+ // If the user enters the screen from the edge then send an earcon.
+ int edge = FindEdgesWithinBounds(event.location(), kLeavingScreenEdge);
+ if (edge != NO_EDGE)
+ delegate_->PlayEnterScreenEarcon();
+
+ int location = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge);
+ // If the press was at a corner, the user might go into corner passthrough
+ // instead.
+ bool in_a_bottom_corner =
+ (BOTTOM_LEFT_CORNER == location) || (BOTTOM_RIGHT_CORNER == location);
+ if (in_a_bottom_corner) {
+ passthrough_timer_.Start(
+ FROM_HERE,
+ gesture_detector_config_.longpress_timeout,
+ this,
+ &TouchExplorationController::OnPassthroughTimerFired);
+ }
+
+ tap_timer_.Start(FROM_HERE,
+ gesture_detector_config_.double_tap_timeout,
+ this,
+ &TouchExplorationController::OnTapTimerFired);
+ initial_press_.reset(new TouchEvent(event));
+ last_unused_finger_event_.reset(new TouchEvent(event));
+ gesture_provider_.OnTouchEvent(event);
+ gesture_provider_.OnTouchEventAck(false);
+ ProcessGestureEvents();
+ state_ = SINGLE_TAP_PRESSED;
+ VLOG_STATE();
+ return ui::EVENT_REWRITE_DISCARD;
}
ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed(
const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) {
const ui::EventType type = event.type();
+ int location = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge);
+ bool in_a_bottom_corner =
+ (location == BOTTOM_LEFT_CORNER) || (location == BOTTOM_RIGHT_CORNER);
+ // If the event is from the initial press and the location is no longer in the
+ // corner, then we are not waiting for a corner passthrough anymore.
+ if (event.touch_id() == initial_press_->touch_id() && !in_a_bottom_corner) {
+ if (passthrough_timer_.IsRunning()) {
+ passthrough_timer_.Stop();
+ // Since the long press timer has been running, it is possible that the
+ // tap timer has timed out before the long press timer has. If the tap
+ // timer timeout has elapsed, then fire the tap timer.
+ if (event.time_stamp() - initial_press_->time_stamp() >
+ gesture_detector_config_.double_tap_timeout) {
+ OnTapTimerFired();
+ }
+ }
+ }
+
if (type == ui::ET_TOUCH_PRESSED) {
// TODO (evy, lisayin) : add support for multifinger swipes.
// For now, we wait for there to be only one finger down again.
@@ -200,7 +256,7 @@ ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed(
}
// Change to slide gesture if the slide occurred at the right edge.
int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge);
- if (edge & RIGHT_EDGE) {
+ if (edge & RIGHT_EDGE && edge != BOTTOM_RIGHT_CORNER) {
state_ = SLIDE_GESTURE;
VLOG_STATE();
return InSlideGesture(event, rewritten_event);
@@ -393,6 +449,39 @@ ui::EventRewriteStatus TouchExplorationController::InGestureInProgress(
return ui::EVENT_REWRITE_DISCARD;
}
+ui::EventRewriteStatus TouchExplorationController::InCornerPassthrough(
+ const ui::TouchEvent& event,
+ scoped_ptr<ui::Event>* rewritten_event) {
+ ui::EventType type = event.type();
+
+ // If the first finger has left the corner, then exit passthrough.
+ if (event.touch_id() == initial_press_->touch_id()) {
+ int edges = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge);
+ bool in_a_bottom_corner = (edges == BOTTOM_LEFT_CORNER) ||
+ (edges == BOTTOM_RIGHT_CORNER);
+ if (type == ui::ET_TOUCH_MOVED && in_a_bottom_corner)
+ return ui::EVENT_REWRITE_DISCARD;
+
+ if (current_touch_ids_.size() == 0) {
+ ResetToNoFingersDown();
+ return ui::EVENT_REWRITE_DISCARD;
+ }
+
+ state_ = WAIT_FOR_ONE_FINGER;
+ VLOG_STATE();
+ return ui::EVENT_REWRITE_DISCARD;
+ }
+
+ rewritten_event->reset(new ui::TouchEvent(
+ type, event.location(), event.touch_id(), event.time_stamp()));
+ (*rewritten_event)->set_flags(event.flags());
+
+ if (current_touch_ids_.size() == 0)
+ ResetToNoFingersDown();
+
+ return ui::EVENT_REWRITE_REWRITTEN;
+}
+
ui::EventRewriteStatus TouchExplorationController::InOneFingerPassthrough(
const ui::TouchEvent& event,
scoped_ptr<ui::Event>* rewritten_event) {
@@ -486,7 +575,7 @@ ui::EventRewriteStatus TouchExplorationController::InWaitForOneFinger(
}
void TouchExplorationController::PlaySoundForTimer() {
- delegate_->PlayVolumeAdjustSound();
+ delegate_->PlayVolumeAdjustEarcon();
}
ui::EventRewriteStatus TouchExplorationController::InSlideGesture(
@@ -526,7 +615,7 @@ ui::EventRewriteStatus TouchExplorationController::InSlideGesture(
kSoundDelay,
this,
&ui::TouchExplorationController::PlaySoundForTimer);
- delegate_->PlayVolumeAdjustSound();
+ delegate_->PlayVolumeAdjustEarcon();
}
// There should not be more than one finger down.
@@ -589,6 +678,8 @@ void TouchExplorationController::OnTapTimerFired() {
return;
}
case SINGLE_TAP_PRESSED:
+ if (passthrough_timer_.IsRunning())
+ return;
case GESTURE_IN_PROGRESS:
// Discard any pending gestures.
delete gesture_provider_.GetAndResetPendingGestures();
@@ -605,6 +696,32 @@ void TouchExplorationController::OnTapTimerFired() {
last_touch_exploration_.reset(new TouchEvent(*initial_press_));
}
+void TouchExplorationController::OnPassthroughTimerFired() {
+ // The long press timer should only be running if one finger is in the corner
aboxhall 2014/08/06 21:03:12 I see why this comment was added, but I think it's
lisayin 2014/08/06 21:48:23 Done.
+ // ready for corner passthrough
+
+ // Check that initial press isn't null and that the id of the initial press
+ // still exists in touch_locations_.
+ if (!initial_press_ ||
+ touch_locations_.end() ==
+ touch_locations_.find(initial_press_->touch_id()))
+ return;
aboxhall 2014/08/06 21:03:12 Is this an error/shouldn't happen condition? Also,
lisayin 2014/08/06 21:48:22 Done.
+
+ gfx::Point location =
+ ToRoundedPoint(touch_locations_[initial_press_->touch_id()]);
+ int corner = FindEdgesWithinBounds(location, kSlopDistanceFromEdge);
+ if (corner != BOTTOM_LEFT_CORNER && corner != BOTTOM_RIGHT_CORNER)
+ return;
+
+ if (sound_timer_.IsRunning())
+ sound_timer_.Stop();
+ delegate_->PlayPassthroughEarcon();
+ delete gesture_provider_.GetAndResetPendingGestures();
+ state_ = CORNER_PASSTHROUGH;
+ VLOG_STATE();
+ return;
+}
+
void TouchExplorationController::DispatchEvent(ui::Event* event) {
ui::EventDispatchDetails result ALLOW_UNUSED =
root_window_->GetHost()->dispatcher()->OnEventFromSource(event);
@@ -646,13 +763,13 @@ void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) {
return;
if (type == ET_GESTURE_SCROLL_BEGIN) {
- delegate_->PlayVolumeAdjustSound();
+ delegate_->PlayVolumeAdjustEarcon();
}
if (type == ET_GESTURE_SCROLL_END) {
if (sound_timer_.IsRunning())
sound_timer_.Stop();
- delegate_->PlayVolumeAdjustSound();
+ delegate_->PlayVolumeAdjustEarcon();
}
// If the user is in the corner of the right side of the screen, the volume
@@ -799,13 +916,16 @@ void TouchExplorationController::EnterTouchToMouseMode() {
}
void TouchExplorationController::ResetToNoFingersDown() {
- ProcessGestureEvents();
+ if (passthrough_timer_.IsRunning())
aboxhall 2014/08/06 21:03:12 Note that in each of these cases, the IsRunning()
lisayin 2014/08/06 21:48:23 Done.
+ passthrough_timer_.Stop();
if (sound_timer_.IsRunning())
sound_timer_.Stop();
- state_ = NO_FINGERS_DOWN;
- VLOG_STATE();
if (tap_timer_.IsRunning())
tap_timer_.Stop();
+ ProcessGestureEvents();
+ state_ = NO_FINGERS_DOWN;
+ VLOG_STATE();
+
}
void TouchExplorationController::VlogState(const char* function_name) {
@@ -869,6 +989,8 @@ const char* TouchExplorationController::EnumStateToString(State state) {
return "GESTURE_IN_PROGRESS";
case TOUCH_EXPLORE_SECOND_PRESS:
return "TOUCH_EXPLORE_SECOND_PRESS";
+ case CORNER_PASSTHROUGH:
+ return "CORNER_PASSTHROUGH";
case SLIDE_GESTURE:
return "SLIDE_GESTURE";
case ONE_FINGER_PASSTHROUGH:
« no previous file with comments | « ui/chromeos/touch_exploration_controller.h ('k') | ui/chromeos/touch_exploration_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698