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

Unified 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: Fixed Memory leak 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 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 1a3b8fad4447ffd8eab56e8e7c1be57745109896..9e704c7e1fb02ef24095bf8b483bb5e75b7469c1 100644
--- a/ui/chromeos/touch_exploration_controller.cc
+++ b/ui/chromeos/touch_exploration_controller.cc
@@ -4,7 +4,6 @@
#include "ui/chromeos/touch_exploration_controller.h"
-#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/window.h"
@@ -12,6 +11,7 @@
#include "ui/aura/window_tree_host.h"
#include "ui/events/event.h"
#include "ui/events/event_processor.h"
+#include "ui/gfx/geometry/rect.h"
#define VLOG_STATE() if (VLOG_IS_ON(0)) VlogState(__func__)
#define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__)
@@ -19,13 +19,19 @@
namespace ui {
namespace {
+
+// Delay between adjustment sounds.
+const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150);
+
// In ChromeOS, VKEY_LWIN is synonymous for the search key.
const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN;
} // namespace
TouchExplorationController::TouchExplorationController(
- aura::Window* root_window)
+ aura::Window* root_window,
+ TouchExplorationControllerDelegate* delegate)
: root_window_(root_window),
+ delegate_(delegate),
state_(NO_FINGERS_DOWN),
event_handler_for_testing_(NULL),
gesture_provider_(this),
@@ -77,6 +83,15 @@ ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
current_touch_ids_.push_back(touch_id);
touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location));
} else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
+ // 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();
+ }
+
std::vector<int>::iterator it = std::find(
current_touch_ids_.begin(), current_touch_ids_.end(), touch_id);
@@ -121,6 +136,8 @@ ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
return InPassthrough(touch_event, rewritten_event);
case WAIT_FOR_RELEASE:
return InWaitForRelease(touch_event, rewritten_event);
+ case SLIDE_GESTURE:
+ return InSlideGesture(touch_event, rewritten_event);
}
NOTREACHED();
return ui::EVENT_REWRITE_CONTINUE;
@@ -191,6 +208,14 @@ ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed(
<< "\n Minimum swipe velocity: "
<< gesture_detector_config_.minimum_swipe_velocity;
+ // Change to slide gesture if the slide occurred at the right edge.
+ int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge);
+ if (edge & RIGHT_EDGE) {
+ state_ = SLIDE_GESTURE;
+ VLOG_STATE();
+ return InSlideGesture(event, rewritten_event);
+ }
+
// If the user moves fast enough from the initial touch location, start
// gesture detection. Otherwise, jump to the touch exploration mode early.
if (velocity > gesture_detector_config_.minimum_swipe_velocity) {
@@ -326,7 +351,7 @@ ui::EventRewriteStatus TouchExplorationController::InGestureInProgress(
if (tap_timer_.IsRunning())
tap_timer_.Stop();
// Discard any pending gestures.
- ignore_result(gesture_provider_.GetAndResetPendingGestures());
+ delete gesture_provider_.GetAndResetPendingGestures();
state_ = TWO_TO_ONE_FINGER;
last_two_to_one_.reset(new TouchEvent(event));
rewritten_event->reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
@@ -497,6 +522,69 @@ ui::EventRewriteStatus TouchExplorationController::InWaitForRelease(
return EVENT_REWRITE_DISCARD;
}
+void TouchExplorationController::PlaySoundForTimer() {
+ delegate_->PlayVolumeAdjustSound();
+}
+
+ui::EventRewriteStatus TouchExplorationController::InSlideGesture(
+ const ui::TouchEvent& event,
+ scoped_ptr<ui::Event>* rewritten_event) {
+ // The timer should not fire when sliding.
+ if (tap_timer_.IsRunning())
+ tap_timer_.Stop();
+
+ ui::EventType type = event.type();
+ // If additional fingers are added before a swipe gesture has been registered,
+ // then wait until all fingers have been lifted.
+ if (type == ui::ET_TOUCH_PRESSED ||
+ event.touch_id() != initial_press_->touch_id()) {
+ if (sound_timer_.IsRunning())
+ sound_timer_.Stop();
+ // Discard any pending gestures.
+ delete gesture_provider_.GetAndResetPendingGestures();
+ state_ = WAIT_FOR_RELEASE;
+ return EVENT_REWRITE_DISCARD;
+ }
+
+ // Allows user to return to the edge to adjust the sound if they have left the
+ // boundaries.
+ int edge = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge);
+ if (!(edge & RIGHT_EDGE) && (type != ui::ET_TOUCH_RELEASED)) {
+ if (sound_timer_.IsRunning()) {
+ sound_timer_.Stop();
+ }
+ return EVENT_REWRITE_DISCARD;
+ }
+
+ // This can occur if the user leaves the screen edge and then returns to it to
+ // continue adjusting the sound.
+ if (!sound_timer_.IsRunning()) {
+ sound_timer_.Start(FROM_HERE,
+ kSoundDelay,
+ this,
+ &ui::TouchExplorationController::PlaySoundForTimer);
+ delegate_->PlayVolumeAdjustSound();
+ }
+
+ // There should not be more than one finger down.
+ DCHECK(current_touch_ids_.size() <= 1);
+ if (type == ui::ET_TOUCH_MOVED) {
+ gesture_provider_.OnTouchEvent(event);
+ gesture_provider_.OnTouchEventAck(false);
+ }
+ if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
+ gesture_provider_.OnTouchEvent(event);
+ gesture_provider_.OnTouchEventAck(false);
+ delete gesture_provider_.GetAndResetPendingGestures();
+ if (current_touch_ids_.size() == 0)
+ ResetToNoFingersDown();
+ return ui::EVENT_REWRITE_DISCARD;
+ }
+
+ ProcessGestureEvents();
+ return ui::EVENT_REWRITE_DISCARD;
+}
+
void TouchExplorationController::OnTapTimerFired() {
switch (state_) {
case SINGLE_TAP_RELEASED:
@@ -509,7 +597,7 @@ void TouchExplorationController::OnTapTimerFired() {
case SINGLE_TAP_PRESSED:
case GESTURE_IN_PROGRESS:
// Discard any pending gestures.
- ignore_result(gesture_provider_.GetAndResetPendingGestures());
+ delete gesture_provider_.GetAndResetPendingGestures();
EnterTouchToMouseMode();
state_ = TOUCH_EXPLORATION;
VLOG_STATE();
@@ -521,7 +609,7 @@ void TouchExplorationController::OnTapTimerFired() {
CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags());
DispatchEvent(mouse_move.get());
last_touch_exploration_.reset(new TouchEvent(*initial_press_));
- }
+}
void TouchExplorationController::DispatchEvent(ui::Event* event) {
if (event_handler_for_testing_) {
@@ -532,12 +620,14 @@ void TouchExplorationController::DispatchEvent(ui::Event* event) {
root_window_->GetHost()->dispatcher()->OnEventFromSource(event);
}
-void TouchExplorationController::OnGestureEvent(ui::GestureEvent* gesture) {
+void TouchExplorationController::OnGestureEvent(
+ ui::GestureEvent* gesture) {
CHECK(gesture->IsGestureEvent());
+ ui::EventType type = gesture->type();
VLOG(0) << " \n Gesture Triggered: " << gesture->name();
- if (gesture->type() == ui::ET_GESTURE_SWIPE) {
- if (tap_timer_.IsRunning())
- tap_timer_.Stop();
+ if (type == ui::ET_GESTURE_SWIPE && state_ != SLIDE_GESTURE) {
+ VLOG(0) << "Swipe!";
+ delete gesture_provider_.GetAndResetPendingGestures();
OnSwipeEvent(gesture);
return;
}
@@ -550,11 +640,61 @@ void TouchExplorationController::ProcessGestureEvents() {
for (ScopedVector<GestureEvent>::iterator i = gestures->begin();
i != gestures->end();
++i) {
- OnGestureEvent(*i);
+ if (state_ == SLIDE_GESTURE)
+ SideSlideControl(*i);
+ else
+ OnGestureEvent(*i);
}
}
}
+void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) {
+ ui::EventType type = gesture->type();
+ if (!gesture->IsScrollGestureEvent())
+ return;
+
+ if (type == ET_GESTURE_SCROLL_BEGIN) {
+ delegate_->PlayVolumeAdjustSound();
+ }
+
+ if (type == ET_GESTURE_SCROLL_END) {
+ if (sound_timer_.IsRunning())
+ sound_timer_.Stop();
+ delegate_->PlayVolumeAdjustSound();
+ }
+
+ // If the user is in the corner of the right side of the screen, the volume
+ // will be automatically set to 100% or muted depending on which corner they
+ // are in. Otherwise, the user will be able to adjust the volume by sliding
+ // their finger along the right side of the screen. Volume is relative to
+ // where they are on the right side of the screen.
+ gfx::Point location = gesture->location();
+ int edge = FindEdgesWithinBounds(location, kSlopDistanceFromEdge);
+ if (!(edge & RIGHT_EDGE))
+ return;
+
+ if (edge & TOP_EDGE) {
+ delegate_->SetOutputLevel(100);
+ return;
+ }
+ if (edge & BOTTOM_EDGE) {
+ delegate_->SetOutputLevel(0);
+ return;
+ }
+
+ location = gesture->location();
+ root_window_->GetHost()->ConvertPointFromNativeScreen(&location);
+ float volume_adjust_height =
+ root_window_->bounds().height() - 2 * kMaxDistanceFromEdge;
+ float ratio = (location.y() - kMaxDistanceFromEdge) / volume_adjust_height;
+ float volume = 100 - 100 * ratio;
+ VLOG(0) << "\n Volume = " << volume << "\n Location = " << location.ToString()
+ << "\n Bounds = " << root_window_->bounds().right();
+
+ delegate_->SetOutputLevel(int(volume));
+}
+
+
void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) {
// A swipe gesture contains details for the direction in which the swipe
// occurred.
@@ -574,6 +714,34 @@ void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) {
}
}
+int TouchExplorationController::FindEdgesWithinBounds(gfx::Point point,
+ float bounds) {
+ // Since GetBoundsInScreen is in DIPs but point is not, then point needs to be
+ // converted.
+ root_window_->GetHost()->ConvertPointFromNativeScreen(&point);
+ gfx::Rect window = root_window_->GetBoundsInScreen();
+
+ float left_edge_limit = window.x() + bounds;
+ float right_edge_limit = window.right() - bounds;
+ float top_edge_limit = window.y() + bounds;
+ float bottom_edge_limit = window.bottom() - bounds;
+
+ // Bitwise manipulation in order to determine where on the screen the point
+ // lies. If more than one bit is turned on, then it is a corner where the two
+ // bit/edges intersect. Otherwise, if no bits are turned on, the point must be
+ // in the center of the screen.
+ int result = NO_EDGE;
+ if (point.x() < left_edge_limit)
+ result |= LEFT_EDGE;
+ if (point.x() > right_edge_limit)
+ result |= RIGHT_EDGE;
+ if (point.y() < top_edge_limit)
+ result |= TOP_EDGE;
+ if (point.y() > bottom_edge_limit)
+ result |= BOTTOM_EDGE;
+ return result;
+}
+
void TouchExplorationController::DispatchShiftSearchKeyEvent(
const ui::KeyboardCode direction) {
// In order to activate the shortcut shift+search+<arrow key>
@@ -623,6 +791,9 @@ void TouchExplorationController::EnterTouchToMouseMode() {
}
void TouchExplorationController::ResetToNoFingersDown() {
+ ProcessGestureEvents();
+ if (sound_timer_.IsRunning())
+ sound_timer_.Stop();
state_ = NO_FINGERS_DOWN;
VLOG_STATE();
if (tap_timer_.IsRunning())
@@ -694,6 +865,8 @@ const char* TouchExplorationController::EnumStateToString(State state) {
return "PASSTHROUGH";
case WAIT_FOR_RELEASE:
return "WAIT_FOR_RELEASE";
+ case SLIDE_GESTURE:
+ return "SLIDE_GESTURE";
}
return "Not a state";
}
« 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