Skip to content

Commit

Permalink
This adds a gesture handler for touch events that start near the bord…
Browse files Browse the repository at this point in the history
…ers 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
  • Loading branch information
rharrison@chromium.org committed Apr 4, 2013
1 parent fca4da9 commit bda506c
Show file tree
Hide file tree
Showing 7 changed files with 331 additions and 19 deletions.
2 changes: 2 additions & 0 deletions ash/ash.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
39 changes: 28 additions & 11 deletions ash/wm/gestures/bezel_gesture_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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_ =
Expand All @@ -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;
Expand All @@ -97,6 +110,8 @@ void BezelGestureHandler::ProcessGestureEvent(aura::Window* target,
default:
break;
}

return true;
}

bool BezelGestureHandler::HandleDeviceControl(
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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.
Expand All @@ -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 {
Expand Down
16 changes: 10 additions & 6 deletions ash/wm/gestures/bezel_gesture_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -33,18 +35,20 @@ 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 {
public:
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
Expand Down Expand Up @@ -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_;
Expand Down
192 changes: 192 additions & 0 deletions ash/wm/gestures/edge_gesture_handler.cc
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit bda506c

Please sign in to comment.