Chromium Code Reviews| 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..ef7577225821a1b82deda73accb81f355e44b268 |
| --- /dev/null |
| +++ b/athena/wm/bezel_controller.cc |
| @@ -0,0 +1,167 @@ |
| +// 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 { |
| + |
| +// static |
| +// Using bezel swipes on Nexus 10, the first touch that is registered is |
|
oshima
2014/07/22 17:56:11
please remove the reference to specific hw
mfomitchev
2014/07/22 19:20:22
Done.
|
| +// usually within 5-10 pixels from the edge, but sometimes as far as 29 |
| +// pixels away. So setting this width fairly high. |
| +const float BezelController::kBezelWidth = 20.0f; |
| + |
| +// static |
| +const gfx::PointF& BezelController::kScrollPositionNone = |
| + gfx::PointF(-100, -100); |
|
oshima
2014/07/22 17:56:11
won't this create static initializer?
mfomitchev
2014/07/22 19:20:22
Done. Just constructing gfx::Point when I need it
|
| + |
| +BezelController::BezelController(aura::Window* container) |
| + : container_(container), |
| + num_fingers_down_(0), |
| + state_(NO_FINGERS_DOWN), |
| + scroll_bezel_(BEZEL_NONE), |
| + 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_) { |
| + if (state != state_) { |
| + 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_ == IGNORE || state == NO_FINGERS_DOWN) { |
| + scroll_bezel_ = BEZEL_NONE; |
| + } |
|
oshima
2014/07/22 17:56:12
nuke {}
mfomitchev
2014/07/22 19:20:22
Done.
|
| +} |
| + |
| +// 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; |
| + } |
| +} |
| + |
| +bool BezelController::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; |
| +} |
| + |
| +void BezelController::OnTouchEvent(ui::TouchEvent* event) { |
| + if (!left_right_delegate_) |
| + return; |
| + |
| + // 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. |
| + |
| + ui::EventType type = event->type(); |
| + if (type == ui::ET_TOUCH_PRESSED) { |
| + num_fingers_down_++; |
| + BezelController::Bezel event_bezel = |
| + GetBezel(gfx::PointF(event->x(), event->y())); |
| + |
| + if (num_fingers_down_ > 2 || |
| + (event_bezel != BEZEL_LEFT && event_bezel != BEZEL_RIGHT)) { |
| + SetState(IGNORE, kScrollPositionNone); |
| + return; |
| + } |
| + |
| + switch (state_) { |
| + case NO_FINGERS_DOWN: |
| + SetState(BEZEL_GESTURE_STARTED, kScrollPositionNone); |
| + scroll_bezel_ = event_bezel; |
| + return; |
| + case IGNORE: |
| + case BEZEL_GESTURE_STARTED: |
| + return; |
| + case BEZEL_SCROLLING_ONE_FINGER: |
| + if (event_bezel != scroll_bezel_) |
| + SetState(IGNORE, kScrollPositionNone); |
| + return; |
| + case BEZEL_SCROLLING_TWO_FINGERS: |
| + // Should've exited above |
| + NOTREACHED(); |
| + return; |
| + }; |
| + } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| + num_fingers_down_--; |
| + DCHECK_NE(state_, NO_FINGERS_DOWN); |
| + // The finger beeing lifted gets counted for touch_points. |
| + if (num_fingers_down_ == 0) { |
| + SetState(NO_FINGERS_DOWN, kScrollPositionNone); |
| + } else { |
| + // Lifting fingers means the user is doing a gesture other than 2-finger |
| + // scrolling. |
| + SetState(IGNORE, kScrollPositionNone); |
| + } |
| + } |
| +} |
| + |
| +void BezelController::OnGestureEvent(ui::GestureEvent* event) { |
| + if (!left_right_delegate_) |
| + return; |
| + |
| + ui::EventType type = event->type(); |
| + if (!ShouldProcessGesture(type)) |
| + return; |
| + |
| + gfx::PointF event_location = event->location_f(); |
| + const ui::GestureEventDetails& event_details = event->details(); |
| + |
| + if (type == ui::ET_GESTURE_BEGIN && event_details.touch_points() == 2 && |
| + state_ == BEZEL_SCROLLING_ONE_FINGER) { |
| + SetState(BEZEL_SCROLLING_TWO_FINGERS, event_location); |
| + } else if (type == ui::ET_GESTURE_SCROLL_BEGIN) { |
| + DCHECK(state_ == IGNORE || state_ == BEZEL_GESTURE_STARTED); |
| + if (state_ == BEZEL_GESTURE_STARTED) { |
| + if (num_fingers_down_ == 1) { |
| + SetState(BEZEL_SCROLLING_ONE_FINGER, event_location); |
| + } else { |
| + DCHECK_EQ(num_fingers_down_, 2); |
| + SetState(BEZEL_SCROLLING_TWO_FINGERS, event_location); |
| + if (left_right_delegate_->CanScroll()) { |
| + event->SetHandled(); |
| + event->StopPropagation(); |
| + } |
| + } |
| + } |
| + } else if (type == ui::ET_GESTURE_SCROLL_UPDATE) { |
| + if (state_ == BEZEL_SCROLLING_TWO_FINGERS) { |
| + float scroll_delta = GetDistance(event_location, scroll_bezel_); |
| + left_right_delegate_->ScrollUpdate(scroll_delta); |
| + if (left_right_delegate_->CanScroll()) { |
| + event->SetHandled(); |
| + event->StopPropagation(); |
| + } |
| + } |
| + } |
| +} |
| + |
| +} // namespace athena |