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

Unified Diff: ui/chromeos/touch_accessibility_enabler.cc

Issue 2584063002: Re-land: Toggle spoken feedback if two fingers are held down. (Closed)
Patch Set: Only toggle spoken feedback on CFM devices Created 4 years 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_accessibility_enabler.h ('k') | ui/chromeos/touch_accessibility_enabler_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/chromeos/touch_accessibility_enabler.cc
diff --git a/ui/chromeos/touch_accessibility_enabler.cc b/ui/chromeos/touch_accessibility_enabler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..07d5c80005516624d0102259d5707ff9b41e162c
--- /dev/null
+++ b/ui/chromeos/touch_accessibility_enabler.cc
@@ -0,0 +1,158 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/chromeos/touch_accessibility_enabler.h"
+
+#include <math.h>
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/metrics/user_metrics.h"
+#include "base/time/default_tick_clock.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/event.h"
+#include "ui/events/event_processor.h"
+#include "ui/events/event_utils.h"
+
+namespace ui {
+
+namespace {
+
+// Delay between timer callbacks. Each one plays a tick sound.
+constexpr int kTimerDelayInMS = 500;
+
+// The number of ticks of the timer before the first sound is generated.
+constexpr int kTimerTicksOfFirstSoundFeedback = 6;
+
+// The number of ticks of the timer before toggling spoken feedback.
+constexpr int kTimerTicksToToggleSpokenFeedback = 10;
+
+} // namespace
+
+TouchAccessibilityEnabler::TouchAccessibilityEnabler(
+ aura::Window* root_window,
+ TouchAccessibilityEnablerDelegate* delegate)
+ : root_window_(root_window),
+ delegate_(delegate),
+ state_(NO_FINGERS_DOWN),
+ tick_clock_(NULL) {
+ DCHECK(root_window);
+ DCHECK(delegate);
+ root_window_->AddPreTargetHandler(this);
+}
+
+TouchAccessibilityEnabler::~TouchAccessibilityEnabler() {
+ root_window_->RemovePreTargetHandler(this);
+}
+
+void TouchAccessibilityEnabler::OnTouchEvent(ui::TouchEvent* event) {
+ // Skip events rewritten by TouchExplorationController, it will hand
+ // us the unrewritten events directly.
+ if (!(event->flags() & ui::EF_TOUCH_ACCESSIBILITY))
+ HandleTouchEvent(*event);
+}
+
+void TouchAccessibilityEnabler::HandleTouchEvent(const ui::TouchEvent& event) {
+ DCHECK(!(event.flags() & ui::EF_TOUCH_ACCESSIBILITY));
+ const ui::EventType type = event.type();
+ const gfx::PointF& location = event.location_f();
+ const int touch_id = event.touch_id();
+
+ if (type == ui::ET_TOUCH_PRESSED) {
+ touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location));
+ } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
+ auto iter = touch_locations_.find(touch_id);
+
+ // Can happen if this object is constructed while fingers were down.
+ if (iter == touch_locations_.end())
+ return;
+
+ touch_locations_.erase(touch_id);
+ } else if (type == ui::ET_TOUCH_MOVED) {
+ auto iter = touch_locations_.find(touch_id);
+
+ // Can happen if this object is constructed while fingers were down.
+ if (iter == touch_locations_.end())
+ return;
+
+ float delta = (location - iter->second).Length();
+ if (delta > gesture_detector_config_.double_tap_slop) {
+ state_ = WAIT_FOR_NO_FINGERS;
+ CancelTimer();
+ return;
+ }
+ } else {
+ NOTREACHED() << "Unexpected event type received: " << event.name();
+ return;
+ }
+
+ if (touch_locations_.size() == 0) {
+ state_ = NO_FINGERS_DOWN;
+ CancelTimer();
+ return;
+ }
+
+ if (touch_locations_.size() > 2) {
+ state_ = WAIT_FOR_NO_FINGERS;
+ CancelTimer();
+ return;
+ }
+
+ if (state_ == NO_FINGERS_DOWN && event.type() == ui::ET_TOUCH_PRESSED) {
+ state_ = ONE_FINGER_DOWN;
+ } else if (state_ == ONE_FINGER_DOWN &&
+ event.type() == ui::ET_TOUCH_PRESSED) {
+ state_ = TWO_FINGERS_DOWN;
+ two_finger_start_time_ = Now();
+ StartTimer();
+ }
+}
+
+base::TimeTicks TouchAccessibilityEnabler::Now() {
+ if (tick_clock_) {
+ // This is the same as what EventTimeForNow() does, but here we do it
+ // with a clock that can be replaced with a simulated clock for tests.
+ return tick_clock_->NowTicks();
+ }
+ return ui::EventTimeForNow();
+}
+
+void TouchAccessibilityEnabler::StartTimer() {
+ if (timer_.IsRunning())
+ return;
+
+ timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kTimerDelayInMS),
+ this, &ui::TouchAccessibilityEnabler::OnTimer);
+}
+
+void TouchAccessibilityEnabler::CancelTimer() {
+ if (timer_.IsRunning())
+ timer_.Stop();
+}
+
+void TouchAccessibilityEnabler::OnTimer() {
+ base::TimeTicks now = Now();
+ double tick_count_f =
+ (now - two_finger_start_time_).InMillisecondsF() / kTimerDelayInMS;
+ int tick_count = roundf(tick_count_f);
+
+ if (tick_count == kTimerTicksOfFirstSoundFeedback) {
+ base::RecordAction(
+ base::UserMetricsAction("Accessibility.TwoFingersHeldDown"));
+ }
+
+ if (tick_count >= kTimerTicksOfFirstSoundFeedback &&
+ tick_count < kTimerTicksToToggleSpokenFeedback) {
+ delegate_->PlaySpokenFeedbackToggleCountdown(tick_count);
+ }
+ if (tick_count == kTimerTicksToToggleSpokenFeedback) {
+ delegate_->ToggleSpokenFeedback();
+ state_ = WAIT_FOR_NO_FINGERS;
+ }
+}
+
+} // namespace ui
« no previous file with comments | « ui/chromeos/touch_accessibility_enabler.h ('k') | ui/chromeos/touch_accessibility_enabler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698