diff options
author | rharrison@chromium.org <rharrison@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-04 08:32:21 +0000 |
---|---|---|
committer | rharrison@chromium.org <rharrison@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-04 08:32:21 +0000 |
commit | bda506cad679d2a9800f5a8eb41da9fb676ee1b9 (patch) | |
tree | 80791b1210b5f443c779d0fbcadd5073910f1dad | |
parent | fca4da9db9bde9992c6a4ba0c49946f8fc8a8eba (diff) | |
download | chromium_src-bda506cad679d2a9800f5a8eb41da9fb676ee1b9.zip chromium_src-bda506cad679d2a9800f5a8eb41da9fb676ee1b9.tar.gz chromium_src-bda506cad679d2a9800f5a8eb41da9fb676ee1b9.tar.bz2 |
This adds a gesture handler for touch events that start near the borders of the
display area. This allows us to support situations where there is no bezel
sensor present or if part of the bezel sensor is turned off.
Currently there is one gesture implemented, swiping in from the edge to raise
the shelf/launcher. This is intended to be part of implementing side launchers.
BUG=chromium:173296
TEST=Confirmed the dragging and flicking shelf from the left works.
Confirmed the dragging and flicking shelf from the right works.
Currently when there is a window on the edge of the screen of the gesture
that consumes touch events the edge gesture does not work. This is filed as
crbug.com/223666.
There are some painting/animation issues, but these are not due to my CL
since they exist in ToT and outside the scope of this bug.
Review URL: https://chromiumcodereview.appspot.com/12529026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192239 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ash/ash.gyp | 2 | ||||
-rw-r--r-- | ash/wm/gestures/bezel_gesture_handler.cc | 39 | ||||
-rw-r--r-- | ash/wm/gestures/bezel_gesture_handler.h | 16 | ||||
-rw-r--r-- | ash/wm/gestures/edge_gesture_handler.cc | 192 | ||||
-rw-r--r-- | ash/wm/gestures/edge_gesture_handler.h | 89 | ||||
-rw-r--r-- | ash/wm/system_gesture_event_filter.cc | 10 | ||||
-rw-r--r-- | ash/wm/system_gesture_event_filter.h | 2 |
7 files changed, 331 insertions, 19 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index 0cecb89..8ec5bce 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -365,6 +365,8 @@ 'wm/frame_painter.h', 'wm/gestures/bezel_gesture_handler.cc', 'wm/gestures/bezel_gesture_handler.h', + 'wm/gestures/edge_gesture_handler.cc', + 'wm/gestures/edge_gesture_handler.h', 'wm/gestures/long_press_affordance_handler.cc', 'wm/gestures/long_press_affordance_handler.h', 'wm/gestures/shelf_gesture_handler.cc', diff --git a/ash/wm/gestures/bezel_gesture_handler.cc b/ash/wm/gestures/bezel_gesture_handler.cc index 4d5dadf..9ccebc1 100644 --- a/ash/wm/gestures/bezel_gesture_handler.cc +++ b/ash/wm/gestures/bezel_gesture_handler.cc @@ -9,6 +9,8 @@ #include "ash/ash_switches.h" #include "ash/launcher/launcher.h" #include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_types.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/system/brightness/brightness_control_delegate.h" @@ -56,7 +58,7 @@ namespace internal { BezelGestureHandler::BezelGestureHandler() : overlap_percent_(0), start_location_(BEZEL_START_UNSET), - orientation_(SCROLL_ORIENTATION_UNSET), + orientation_(BEZEL_SCROLL_ORIENTATION_UNSET), is_scrubbing_(false), initiation_delay_events_(0) { enable_bezel_device_control_ = @@ -67,16 +69,27 @@ BezelGestureHandler::BezelGestureHandler() BezelGestureHandler::~BezelGestureHandler() { } -void BezelGestureHandler::ProcessGestureEvent(aura::Window* target, +bool BezelGestureHandler::ProcessGestureEvent(aura::Window* target, const ui::GestureEvent& event) { + if (target && target != target->GetRootWindow()) + return false; + + // TODO(crbug.com/222746): Rewrite this code to determine at runtime what + // bezels are present and process events along those + // edges. + ShelfLayoutManager* shelf = + Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); + if (shelf->GetAlignment() != SHELF_ALIGNMENT_BOTTOM) + return false; + switch (event.type()) { case ui::ET_GESTURE_SCROLL_BEGIN: HandleBezelGestureStart(target, event); - // TODO(sad|skuhne): Fix the bezel gestures for when the shelf is on the - // left/right of the screen. Also fix the - // overlay_percent_ at that time (currently just set to - // 0 because left/right bezel gestures dont work). + // TODO(rharrison): Fix the bezel gestures for when the shelf is on the + // left/right of the screen. Also fix the + // overlay_percent_ at that time (currently just set to + // 0 because left/right bezel gestures dont work). if (start_location_ == BEZEL_START_BOTTOM) shelf_handler_.ProcessGestureEvent(event); break; @@ -97,6 +110,8 @@ void BezelGestureHandler::ProcessGestureEvent(aura::Window* target, default: break; } + + return true; } bool BezelGestureHandler::HandleDeviceControl( @@ -158,7 +173,7 @@ void BezelGestureHandler::HandleBezelGestureStart( gfx::Rect screen = Shell::GetScreen()->GetDisplayNearestWindow(target).bounds(); int overlap_area = screen.width() * overlap_percent_ / 100; - orientation_ = SCROLL_ORIENTATION_UNSET; + orientation_ = BEZEL_SCROLL_ORIENTATION_UNSET; if (event.x() <= screen.x() + overlap_area) { start_location_ = BEZEL_START_LEFT; @@ -171,7 +186,7 @@ void BezelGestureHandler::HandleBezelGestureStart( bool BezelGestureHandler::DetermineGestureOrientation( const ui::GestureEvent& event) { - if (orientation_ == SCROLL_ORIENTATION_UNSET) { + if (orientation_ == BEZEL_SCROLL_ORIENTATION_UNSET) { if (!event.details().scroll_x() && !event.details().scroll_y()) return false; @@ -181,11 +196,13 @@ bool BezelGestureHandler::DetermineGestureOrientation( start_location_ == BEZEL_START_RIGHT) { orientation_ = abs(event.details().scroll_y()) > abs(event.details().scroll_x()) * 3 ? - SCROLL_ORIENTATION_VERTICAL : SCROLL_ORIENTATION_HORIZONTAL; + BEZEL_SCROLL_ORIENTATION_VERTICAL : + BEZEL_SCROLL_ORIENTATION_HORIZONTAL; } else { orientation_ = abs(event.details().scroll_y()) > abs(event.details().scroll_x()) ? - SCROLL_ORIENTATION_VERTICAL : SCROLL_ORIENTATION_HORIZONTAL; + BEZEL_SCROLL_ORIENTATION_VERTICAL : + BEZEL_SCROLL_ORIENTATION_HORIZONTAL; } // Reset the delay counter for noise event filtering. @@ -197,7 +214,7 @@ bool BezelGestureHandler::DetermineGestureOrientation( void BezelGestureHandler::HandleBezelGestureUpdate( aura::Window* target, const ui::GestureEvent& event) { - if (orientation_ == SCROLL_ORIENTATION_HORIZONTAL) { + if (orientation_ == BEZEL_SCROLL_ORIENTATION_HORIZONTAL) { if (HandleApplicationControl(event)) start_location_ = BEZEL_START_UNSET; } else { diff --git a/ash/wm/gestures/bezel_gesture_handler.h b/ash/wm/gestures/bezel_gesture_handler.h index db8163e..965edb7 100644 --- a/ash/wm/gestures/bezel_gesture_handler.h +++ b/ash/wm/gestures/bezel_gesture_handler.h @@ -25,6 +25,8 @@ class GestureEvent; namespace ash { namespace internal { +// TODO(rharrison): Unify the enums here and in the edge handler into common +// area. enum BezelStart { BEZEL_START_UNSET = 0, BEZEL_START_TOP, @@ -33,10 +35,10 @@ enum BezelStart { BEZEL_START_BOTTOM }; -enum ScrollOrientation { - SCROLL_ORIENTATION_UNSET = 0, - SCROLL_ORIENTATION_HORIZONTAL, - SCROLL_ORIENTATION_VERTICAL +enum BezelScrollOrientation { + BEZEL_SCROLL_ORIENTATION_UNSET = 0, + BEZEL_SCROLL_ORIENTATION_HORIZONTAL, + BEZEL_SCROLL_ORIENTATION_VERTICAL }; class BezelGestureHandler { @@ -44,7 +46,9 @@ class BezelGestureHandler { BezelGestureHandler(); virtual ~BezelGestureHandler(); - void ProcessGestureEvent(aura::Window* target, const ui::GestureEvent& event); + // Returns true of the gesture has been handled and it should not be processed + // any farther, false otherwise. + bool ProcessGestureEvent(aura::Window* target, const ui::GestureEvent& event); private: // Handle events meant for volume / brightness. Returns true when no further @@ -103,7 +107,7 @@ class BezelGestureHandler { BezelStart start_location_; // Which orientation are we moving. - ScrollOrientation orientation_; + BezelScrollOrientation orientation_; // A device swipe gesture is in progress. bool is_scrubbing_; diff --git a/ash/wm/gestures/edge_gesture_handler.cc b/ash/wm/gestures/edge_gesture_handler.cc new file mode 100644 index 0000000..9ba7ff3 --- /dev/null +++ b/ash/wm/gestures/edge_gesture_handler.cc @@ -0,0 +1,192 @@ +// Copyright (c) 2013 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 "ash/wm/gestures/edge_gesture_handler.h" + +#include "ash/root_window_controller.h" +#include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_types.h" +#include "ash/shelf/shelf_widget.h" +#include "ash/shell.h" +#include "ui/base/events/event.h" +#include "ui/gfx/screen.h" + +namespace { +const int kBottomEdgeGestureThreshold = 10; +const int kLeftEdgeGestureThreshold = 10; +const int kRightEdgeGestureThreshold = 10; +const int kTopEdgeGestureThreshold = 10; + +// Bit positions of edge start flags +enum EdgeStart { + EDGE_START_TOP = 0, + EDGE_START_LEFT = 1, + EDGE_START_RIGHT = 2, + EDGE_START_BOTTOM = 3 +}; + +// Helpers for manipulating edge start flags +#define CLEAR_FLAGS(FLAGS) (FLAGS = 0) +#define SET_FLAG(FLAGS, FLAG_POS) (FLAGS |= 1 << FLAG_POS) +#define IS_FLAG_SET(FLAGS, FLAG_POS) (0 != (FLAGS & (1 << FLAG_POS))) +#define ANY_FLAGS_SET(FLAGS) (FLAGS != 0) +} // namespace + +namespace ash { +namespace internal { + +EdgeGestureHandler::EdgeGestureHandler() : + orientation_(EDGE_SCROLL_ORIENTATION_UNSET) { + CLEAR_FLAGS(start_location_); +} + +EdgeGestureHandler::~EdgeGestureHandler() { +} + +bool EdgeGestureHandler::ProcessGestureEvent(aura::Window* target, + const ui::GestureEvent& event) { + // TODO(crbug.com/222746): Rewrite this code to ignore events that are for + // edges that a bezel is present for instead of hardcoding the layout of edge + // v bezel. + switch (event.type()) { + case ui::ET_GESTURE_SCROLL_BEGIN: + return HandleEdgeGestureStart(target, event); + case ui::ET_GESTURE_SCROLL_UPDATE: + if (ANY_FLAGS_SET(start_location_)) { + if (DetermineGestureOrientation(event)) { + return HandleEdgeGestureUpdate(target, event); + } + } + break; + case ui::ET_GESTURE_SCROLL_END: + case ui::ET_SCROLL_FLING_START: + return HandleEdgeGestureEnd(target, event); + default: + break; + } + return false; +} + +bool EdgeGestureHandler::HandleLauncherControl(const ui::GestureEvent& event) { + ShelfLayoutManager* shelf = + Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); + // If visible then let the shelf handle it as a normal widget. + if (shelf->IsVisible()) + return false; + + switch (shelf->GetAlignment()) { + case SHELF_ALIGNMENT_LEFT: + if (IS_FLAG_SET(start_location_, EDGE_START_LEFT)) + return shelf_handler_.ProcessGestureEvent(event); + break; + case SHELF_ALIGNMENT_RIGHT: + if (IS_FLAG_SET(start_location_, EDGE_START_RIGHT)) + return shelf_handler_.ProcessGestureEvent(event); + break; + // Let the BezelGestureHandler handle gestures on the bottom edge of the + // screen and there are no implemented gestures for the top edge at the + // moment. + case SHELF_ALIGNMENT_BOTTOM: + case SHELF_ALIGNMENT_TOP: + default: + break; + } + return false; +} + +bool EdgeGestureHandler::HandleEdgeGestureStart( + aura::Window* target, + const ui::GestureEvent& event) { + gfx::Rect screen = + Shell::GetScreen()->GetDisplayNearestWindow(target).bounds(); + + orientation_ = EDGE_SCROLL_ORIENTATION_UNSET; + if (GestureStartInEdgeArea(screen, event)) + return HandleLauncherControl(event); + return false; +} + +bool EdgeGestureHandler::DetermineGestureOrientation( + const ui::GestureEvent& event) { + if (orientation_ == EDGE_SCROLL_ORIENTATION_UNSET) { + if (!event.details().scroll_x() && !event.details().scroll_y()) + return false; + orientation_ = abs(event.details().scroll_y()) > + abs(event.details().scroll_x()) ? + EDGE_SCROLL_ORIENTATION_VERTICAL : EDGE_SCROLL_ORIENTATION_HORIZONTAL; + } + return true; +} + +bool EdgeGestureHandler::HandleEdgeGestureUpdate( + aura::Window* target, + const ui::GestureEvent& event) { + if (IsGestureInLauncherOrientation(event)) + return HandleLauncherControl(event); + return false; +} + +bool EdgeGestureHandler::HandleEdgeGestureEnd(aura::Window* target, + const ui::GestureEvent& event) { + bool ret_val = HandleLauncherControl(event); + CLEAR_FLAGS(start_location_); + return ret_val; +} + +bool EdgeGestureHandler::GestureStartInEdgeArea( + const gfx::Rect& screen, + const ui::GestureEvent& event) { + CLEAR_FLAGS(start_location_); + + if (abs(event.y() - screen.y()) < kTopEdgeGestureThreshold && + event.y() >= 0) + SET_FLAG(start_location_, EDGE_START_TOP); + if (abs(event.x() - screen.x()) < kLeftEdgeGestureThreshold && + event.x() >= 0) + SET_FLAG(start_location_, EDGE_START_LEFT); + if (abs(event.x() - screen.right()) < kRightEdgeGestureThreshold && + event.x() >= 0) + SET_FLAG(start_location_, EDGE_START_RIGHT); + if (abs(event.y() - screen.bottom()) < kBottomEdgeGestureThreshold && + event.y() >= 0) + SET_FLAG(start_location_, EDGE_START_BOTTOM); + return ANY_FLAGS_SET(start_location_); +} + +bool EdgeGestureHandler::IsGestureInLauncherOrientation( + const ui::GestureEvent& event) { + EdgeScrollOrientation new_orientation = abs(event.details().scroll_y()) > + abs(event.details().scroll_x()) ? + EDGE_SCROLL_ORIENTATION_VERTICAL : EDGE_SCROLL_ORIENTATION_HORIZONTAL; + + if (new_orientation != orientation_) + return false; + + ShelfLayoutManager* shelf = + Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); + switch (shelf->GetAlignment()) { + case SHELF_ALIGNMENT_BOTTOM: + if (orientation_ == EDGE_SCROLL_ORIENTATION_VERTICAL) + return true; + break; + case SHELF_ALIGNMENT_LEFT: + if (orientation_ == EDGE_SCROLL_ORIENTATION_HORIZONTAL) + return true; + break; + case SHELF_ALIGNMENT_RIGHT: + if (orientation_ == EDGE_SCROLL_ORIENTATION_HORIZONTAL) + return true; + break; + case SHELF_ALIGNMENT_TOP: + if (orientation_ == EDGE_SCROLL_ORIENTATION_VERTICAL) + return true; + break; + default: + break; + } + return false; +} + +} // namespace internal +} // namespace ash diff --git a/ash/wm/gestures/edge_gesture_handler.h b/ash/wm/gestures/edge_gesture_handler.h new file mode 100644 index 0000000..9eaa422 --- /dev/null +++ b/ash/wm/gestures/edge_gesture_handler.h @@ -0,0 +1,89 @@ +// Copyright (c) 2013 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. + +#ifndef ASH_WM_GESTURES_EDGE_GESTURE_HANDLER_H_ +#define ASH_WM_GESTURES_EDGE_GESTURE_HANDLER_H_ + +#include "ash/shelf/shelf_types.h" +#include "ash/wm/gestures/shelf_gesture_handler.h" +#include "base/basictypes.h" + +namespace aura { +class Window; +} + +namespace gfx { +class Point; +class Rect; +} + +namespace ui { +class GestureEvent; +} + +namespace ash { +namespace internal { + +enum EdgeScrollOrientation { + EDGE_SCROLL_ORIENTATION_UNSET = 0, + EDGE_SCROLL_ORIENTATION_HORIZONTAL, + EDGE_SCROLL_ORIENTATION_VERTICAL +}; + +// Handles touch gestures that occur at the edge of the screen without the aid +// of a bezel sensor and might have actions associated with them. +class EdgeGestureHandler { + public: + EdgeGestureHandler(); + virtual ~EdgeGestureHandler(); + + // Returns true of the gesture has been handled and it should not be processed + // any farther, false otherwise. + bool ProcessGestureEvent(aura::Window* target, const ui::GestureEvent& event); + + private: + // Handle events meant for showing the launcher. Returns true when no further + // events from this gesture should be sent. + bool HandleLauncherControl(const ui::GestureEvent& event); + + bool HandleEdgeGestureStart(aura::Window* target, + const ui::GestureEvent& event); + + // Determine the gesture orientation (if not yet done). + // Returns true when the orientation has been successfully determined. + bool DetermineGestureOrientation(const ui::GestureEvent& event); + + // Handles a gesture update once the orientation has been found. + bool HandleEdgeGestureUpdate(aura::Window* target, + const ui::GestureEvent& event); + + bool HandleEdgeGestureEnd(aura::Window* target, + const ui::GestureEvent& event); + + // Check that gesture starts near enough to the edge of the screen to be + // handled here. If so, set |start_location_| and return true, otherwise + // return false. + bool GestureStartInEdgeArea(const gfx::Rect& screen, + const ui::GestureEvent& event); + + // Test if the gesture orientation makes sense to be dragging in or out the + // launcher. + bool IsGestureInLauncherOrientation(const ui::GestureEvent& event); + + // Bit flags for which edges the gesture is close to. In the case that a + // gesture begins in a corner of the screen more then one flag may be set and + // the orientation of the gesture will be needed to disambiguate. + unsigned int start_location_; + + // Orientation relative to the screen that the gesture is moving in + EdgeScrollOrientation orientation_; + ShelfGestureHandler shelf_handler_; + + DISALLOW_COPY_AND_ASSIGN(EdgeGestureHandler); +}; + +} // namespace internal +} // namespace ash + +#endif // ASH_WM_GESTURES_EDGE_GESTURE_HANDLER_H_ diff --git a/ash/wm/system_gesture_event_filter.cc b/ash/wm/system_gesture_event_filter.cc index 8dceaa0..0808695 100644 --- a/ash/wm/system_gesture_event_filter.cc +++ b/ash/wm/system_gesture_event_filter.cc @@ -12,6 +12,7 @@ #include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" #include "ash/wm/gestures/bezel_gesture_handler.h" +#include "ash/wm/gestures/edge_gesture_handler.h" #include "ash/wm/gestures/long_press_affordance_handler.h" #include "ash/wm/gestures/system_pinch_handler.h" #include "ash/wm/gestures/two_finger_drag_handler.h" @@ -46,6 +47,7 @@ SystemGestureEventFilter::SystemGestureEventFilter() : system_gestures_enabled_(CommandLine::ForCurrentProcess()-> HasSwitch(ash::switches::kAshEnableAdvancedGestures)), bezel_gestures_(new BezelGestureHandler), + edge_gestures_(new EdgeGestureHandler), long_press_affordance_(new LongPressAffordanceHandler), two_finger_drag_(new TwoFingerDragHandler) { } @@ -76,8 +78,12 @@ void SystemGestureEventFilter::OnGestureEvent(ui::GestureEvent* event) { long_press_affordance_->ProcessEvent(target, event, event->GetLowestTouchId()); - if (!target || target == target->GetRootWindow()) { - bezel_gestures_->ProcessGestureEvent(target, *event); + if (bezel_gestures_->ProcessGestureEvent(target, *event)) { + event->StopPropagation(); + return; + } + + if (edge_gestures_->ProcessGestureEvent(target, *event)) { event->StopPropagation(); return; } diff --git a/ash/wm/system_gesture_event_filter.h b/ash/wm/system_gesture_event_filter.h index ee3b786..c848c2b57 100644 --- a/ash/wm/system_gesture_event_filter.h +++ b/ash/wm/system_gesture_event_filter.h @@ -32,6 +32,7 @@ class SystemGestureEventFilterTest; namespace internal { class BezelGestureHandler; +class EdgeGestureHandler; class LongPressAffordanceHandler; class SystemPinchHandler; class TouchUMA; @@ -68,6 +69,7 @@ class SystemGestureEventFilter : public ui::EventHandler, bool system_gestures_enabled_; scoped_ptr<BezelGestureHandler> bezel_gestures_; + scoped_ptr<EdgeGestureHandler> edge_gestures_; scoped_ptr<LongPressAffordanceHandler> long_press_affordance_; scoped_ptr<TwoFingerDragHandler> two_finger_drag_; |