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 |