| Index: athena/wm/bezel_controller.cc
|
| diff --git a/athena/wm/bezel_controller.cc b/athena/wm/bezel_controller.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fb6215533b87eacf8adeeed7695baaa98ba163d1
|
| --- /dev/null
|
| +++ b/athena/wm/bezel_controller.cc
|
| @@ -0,0 +1,171 @@
|
| +// Copyright 2014 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 "athena/wm/bezel_controller.h"
|
| +
|
| +#include "ui/aura/window.h"
|
| +#include "ui/events/event_handler.h"
|
| +
|
| +namespace athena {
|
| +namespace {
|
| +
|
| +// Using bezel swipes, the first touch that is registered is usually within
|
| +// 5-10 pixels from the edge, but sometimes as far as 29 pixels away.
|
| +// So setting this width fairly high for now.
|
| +const float kBezelWidth = 20.0f;
|
| +
|
| +const float kScrollPositionNone = -100;
|
| +
|
| +bool ShouldProcessGesture(ui::EventType event_type) {
|
| + return event_type == ui::ET_GESTURE_SCROLL_UPDATE ||
|
| + event_type == ui::ET_GESTURE_SCROLL_BEGIN ||
|
| + event_type == ui::ET_GESTURE_BEGIN ||
|
| + event_type == ui::ET_GESTURE_END;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +BezelController::BezelController(aura::Window* container)
|
| + : container_(container),
|
| + state_(NONE),
|
| + scroll_bezel_(BEZEL_NONE),
|
| + scroll_target_(NULL),
|
| + left_right_delegate_(NULL) {
|
| +}
|
| +
|
| +float BezelController::GetDistance(const gfx::PointF& position,
|
| + BezelController::Bezel bezel) {
|
| + DCHECK(bezel == BEZEL_LEFT || bezel == BEZEL_RIGHT);
|
| + return bezel == BEZEL_LEFT
|
| + ? position.x()
|
| + : position.x() - container_->GetBoundsInScreen().width();
|
| +}
|
| +
|
| +void BezelController::SetState(BezelController::State state,
|
| + const gfx::PointF& scroll_position) {
|
| + if (!left_right_delegate_ || state == state_)
|
| + return;
|
| +
|
| + if (state == BEZEL_SCROLLING_TWO_FINGERS) {
|
| + float delta = GetDistance(scroll_position, scroll_bezel_);
|
| + left_right_delegate_->ScrollBegin(scroll_bezel_, delta);
|
| + } else if (state_ == BEZEL_SCROLLING_TWO_FINGERS) {
|
| + left_right_delegate_->ScrollEnd();
|
| + }
|
| + state_ = state;
|
| + if (state == NONE) {
|
| + scroll_bezel_ = BEZEL_NONE;
|
| + scroll_target_ = NULL;
|
| + }
|
| +}
|
| +
|
| +// Only implemented for LEFT and RIGHT bezels ATM.
|
| +BezelController::Bezel BezelController::GetBezel(const gfx::PointF& location) {
|
| + if (location.x() < kBezelWidth) {
|
| + return BEZEL_LEFT;
|
| + } else if (location.x() >
|
| + container_->GetBoundsInScreen().width() - kBezelWidth) {
|
| + return BEZEL_RIGHT;
|
| + } else {
|
| + return BEZEL_NONE;
|
| + }
|
| +}
|
| +
|
| +void BezelController::OnGestureEvent(ui::GestureEvent* event) {
|
| + // TODO (mfomitchev): Currently we aren't retargetting or consuming any of the
|
| + // touch events. This means that content can prevent the generation of gesture
|
| + // events and two-finger scroll won't work. Possible solution to this problem
|
| + // is hosting our own gesture recognizer or retargetting touch events at the
|
| + // bezel.
|
| +
|
| + if (!left_right_delegate_)
|
| + return;
|
| +
|
| + ui::EventType type = event->type();
|
| + if (!ShouldProcessGesture(type))
|
| + return;
|
| +
|
| + if (scroll_target_ && event->target() != scroll_target_)
|
| + return;
|
| +
|
| + const gfx::PointF& event_location = event->location_f();
|
| + const ui::GestureEventDetails& event_details = event->details();
|
| + int num_touch_points = event_details.touch_points();
|
| +
|
| + if (type == ui::ET_GESTURE_BEGIN) {
|
| + if (num_touch_points > 2) {
|
| + SetState(IGNORE_CURRENT_SCROLL,
|
| + gfx::Point(kScrollPositionNone, kScrollPositionNone));
|
| + return;
|
| + }
|
| + BezelController::Bezel event_bezel = GetBezel(event->location_f());
|
| + switch (state_) {
|
| + case NONE:
|
| + scroll_bezel_ = event_bezel;
|
| + scroll_target_ = event->target();
|
| + if (event_bezel != BEZEL_LEFT && event_bezel != BEZEL_RIGHT) {
|
| + SetState(IGNORE_CURRENT_SCROLL,
|
| + gfx::Point(kScrollPositionNone, kScrollPositionNone));
|
| + } else {
|
| + SetState(BEZEL_GESTURE_STARTED, event_location);
|
| + }
|
| + break;
|
| + case IGNORE_CURRENT_SCROLL:
|
| + break;
|
| + case BEZEL_GESTURE_STARTED:
|
| + case BEZEL_SCROLLING_ONE_FINGER:
|
| + DCHECK_EQ(num_touch_points, 2);
|
| + DCHECK(scroll_target_);
|
| + DCHECK_NE(scroll_bezel_, BEZEL_NONE);
|
| +
|
| + if (event_bezel != scroll_bezel_) {
|
| + SetState(IGNORE_CURRENT_SCROLL,
|
| + gfx::Point(kScrollPositionNone, kScrollPositionNone));
|
| + return;
|
| + }
|
| + if (state_ == BEZEL_SCROLLING_ONE_FINGER)
|
| + SetState(BEZEL_SCROLLING_TWO_FINGERS, event_location);
|
| + break;
|
| + case BEZEL_SCROLLING_TWO_FINGERS:
|
| + // Should've exited above
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| + } else if (type == ui::ET_GESTURE_END) {
|
| + if (state_ == NONE)
|
| + return;
|
| +
|
| + CHECK(scroll_target_);
|
| + if (num_touch_points == 1) {
|
| + SetState(NONE, gfx::Point(kScrollPositionNone, kScrollPositionNone));
|
| + } else {
|
| + SetState(IGNORE_CURRENT_SCROLL,
|
| + gfx::Point(kScrollPositionNone, kScrollPositionNone));
|
| + }
|
| + } else if (type == ui::ET_GESTURE_SCROLL_BEGIN) {
|
| + DCHECK(state_ == IGNORE_CURRENT_SCROLL || state_ == BEZEL_GESTURE_STARTED);
|
| + if (state_ != BEZEL_GESTURE_STARTED)
|
| + return;
|
| +
|
| + if (num_touch_points == 1) {
|
| + SetState(BEZEL_SCROLLING_ONE_FINGER, event_location);
|
| + return;
|
| + }
|
| +
|
| + DCHECK_EQ(num_touch_points, 2);
|
| + SetState(BEZEL_SCROLLING_TWO_FINGERS, event_location);
|
| + if (left_right_delegate_->CanScroll())
|
| + event->SetHandled();
|
| + } else if (type == ui::ET_GESTURE_SCROLL_UPDATE) {
|
| + if (state_ != BEZEL_SCROLLING_TWO_FINGERS)
|
| + return;
|
| +
|
| + float scroll_delta = GetDistance(event_location, scroll_bezel_);
|
| + left_right_delegate_->ScrollUpdate(scroll_delta);
|
| + if (left_right_delegate_->CanScroll())
|
| + event->SetHandled();
|
| + }
|
| +}
|
| +
|
| +} // namespace athena
|
|
|