OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "athena/wm/bezel_controller.h" |
| 6 |
| 7 #include "ui/aura/window.h" |
| 8 #include "ui/events/event_handler.h" |
| 9 |
| 10 namespace athena { |
| 11 namespace { |
| 12 |
| 13 // Using bezel swipes, the first touch that is registered is usually within |
| 14 // 5-10 pixels from the edge, but sometimes as far as 29 pixels away. |
| 15 // So setting this width fairly high for now. |
| 16 const float kBezelWidth = 20.0f; |
| 17 |
| 18 const float kScrollPositionNone = -100; |
| 19 |
| 20 bool ShouldProcessGesture(ui::EventType event_type) { |
| 21 return event_type == ui::ET_GESTURE_SCROLL_UPDATE || |
| 22 event_type == ui::ET_GESTURE_SCROLL_BEGIN || |
| 23 event_type == ui::ET_GESTURE_BEGIN || |
| 24 event_type == ui::ET_GESTURE_END; |
| 25 } |
| 26 |
| 27 } // namespace |
| 28 |
| 29 BezelController::BezelController(aura::Window* container) |
| 30 : container_(container), |
| 31 state_(NONE), |
| 32 scroll_bezel_(BEZEL_NONE), |
| 33 scroll_target_(NULL), |
| 34 left_right_delegate_(NULL) { |
| 35 } |
| 36 |
| 37 float BezelController::GetDistance(const gfx::PointF& position, |
| 38 BezelController::Bezel bezel) { |
| 39 DCHECK(bezel == BEZEL_LEFT || bezel == BEZEL_RIGHT); |
| 40 return bezel == BEZEL_LEFT |
| 41 ? position.x() |
| 42 : position.x() - container_->GetBoundsInScreen().width(); |
| 43 } |
| 44 |
| 45 void BezelController::SetState(BezelController::State state, |
| 46 const gfx::PointF& scroll_position) { |
| 47 if (!left_right_delegate_ || state == state_) |
| 48 return; |
| 49 |
| 50 if (state == BEZEL_SCROLLING_TWO_FINGERS) { |
| 51 float delta = GetDistance(scroll_position, scroll_bezel_); |
| 52 left_right_delegate_->ScrollBegin(scroll_bezel_, delta); |
| 53 } else if (state_ == BEZEL_SCROLLING_TWO_FINGERS) { |
| 54 left_right_delegate_->ScrollEnd(); |
| 55 } |
| 56 state_ = state; |
| 57 if (state == NONE) { |
| 58 scroll_bezel_ = BEZEL_NONE; |
| 59 scroll_target_ = NULL; |
| 60 } |
| 61 } |
| 62 |
| 63 // Only implemented for LEFT and RIGHT bezels ATM. |
| 64 BezelController::Bezel BezelController::GetBezel(const gfx::PointF& location) { |
| 65 if (location.x() < kBezelWidth) { |
| 66 return BEZEL_LEFT; |
| 67 } else if (location.x() > |
| 68 container_->GetBoundsInScreen().width() - kBezelWidth) { |
| 69 return BEZEL_RIGHT; |
| 70 } else { |
| 71 return BEZEL_NONE; |
| 72 } |
| 73 } |
| 74 |
| 75 void BezelController::OnGestureEvent(ui::GestureEvent* event) { |
| 76 // TODO (mfomitchev): Currently we aren't retargetting or consuming any of the |
| 77 // touch events. This means that content can prevent the generation of gesture |
| 78 // events and two-finger scroll won't work. Possible solution to this problem |
| 79 // is hosting our own gesture recognizer or retargetting touch events at the |
| 80 // bezel. |
| 81 |
| 82 if (!left_right_delegate_) |
| 83 return; |
| 84 |
| 85 ui::EventType type = event->type(); |
| 86 if (!ShouldProcessGesture(type)) |
| 87 return; |
| 88 |
| 89 if (scroll_target_ && event->target() != scroll_target_) |
| 90 return; |
| 91 |
| 92 const gfx::PointF& event_location = event->location_f(); |
| 93 const ui::GestureEventDetails& event_details = event->details(); |
| 94 int num_touch_points = event_details.touch_points(); |
| 95 |
| 96 if (type == ui::ET_GESTURE_BEGIN) { |
| 97 if (num_touch_points > 2) { |
| 98 SetState(IGNORE_CURRENT_SCROLL, |
| 99 gfx::Point(kScrollPositionNone, kScrollPositionNone)); |
| 100 return; |
| 101 } |
| 102 BezelController::Bezel event_bezel = GetBezel(event->location_f()); |
| 103 switch (state_) { |
| 104 case NONE: |
| 105 scroll_bezel_ = event_bezel; |
| 106 scroll_target_ = event->target(); |
| 107 if (event_bezel != BEZEL_LEFT && event_bezel != BEZEL_RIGHT) { |
| 108 SetState(IGNORE_CURRENT_SCROLL, |
| 109 gfx::Point(kScrollPositionNone, kScrollPositionNone)); |
| 110 } else { |
| 111 SetState(BEZEL_GESTURE_STARTED, event_location); |
| 112 } |
| 113 break; |
| 114 case IGNORE_CURRENT_SCROLL: |
| 115 break; |
| 116 case BEZEL_GESTURE_STARTED: |
| 117 case BEZEL_SCROLLING_ONE_FINGER: |
| 118 DCHECK_EQ(num_touch_points, 2); |
| 119 DCHECK(scroll_target_); |
| 120 DCHECK_NE(scroll_bezel_, BEZEL_NONE); |
| 121 |
| 122 if (event_bezel != scroll_bezel_) { |
| 123 SetState(IGNORE_CURRENT_SCROLL, |
| 124 gfx::Point(kScrollPositionNone, kScrollPositionNone)); |
| 125 return; |
| 126 } |
| 127 if (state_ == BEZEL_SCROLLING_ONE_FINGER) |
| 128 SetState(BEZEL_SCROLLING_TWO_FINGERS, event_location); |
| 129 break; |
| 130 case BEZEL_SCROLLING_TWO_FINGERS: |
| 131 // Should've exited above |
| 132 NOTREACHED(); |
| 133 break; |
| 134 } |
| 135 } else if (type == ui::ET_GESTURE_END) { |
| 136 if (state_ == NONE) |
| 137 return; |
| 138 |
| 139 CHECK(scroll_target_); |
| 140 if (num_touch_points == 1) { |
| 141 SetState(NONE, gfx::Point(kScrollPositionNone, kScrollPositionNone)); |
| 142 } else { |
| 143 SetState(IGNORE_CURRENT_SCROLL, |
| 144 gfx::Point(kScrollPositionNone, kScrollPositionNone)); |
| 145 } |
| 146 } else if (type == ui::ET_GESTURE_SCROLL_BEGIN) { |
| 147 DCHECK(state_ == IGNORE_CURRENT_SCROLL || state_ == BEZEL_GESTURE_STARTED); |
| 148 if (state_ != BEZEL_GESTURE_STARTED) |
| 149 return; |
| 150 |
| 151 if (num_touch_points == 1) { |
| 152 SetState(BEZEL_SCROLLING_ONE_FINGER, event_location); |
| 153 return; |
| 154 } |
| 155 |
| 156 DCHECK_EQ(num_touch_points, 2); |
| 157 SetState(BEZEL_SCROLLING_TWO_FINGERS, event_location); |
| 158 if (left_right_delegate_->CanScroll()) |
| 159 event->SetHandled(); |
| 160 } else if (type == ui::ET_GESTURE_SCROLL_UPDATE) { |
| 161 if (state_ != BEZEL_SCROLLING_TWO_FINGERS) |
| 162 return; |
| 163 |
| 164 float scroll_delta = GetDistance(event_location, scroll_bezel_); |
| 165 left_right_delegate_->ScrollUpdate(scroll_delta); |
| 166 if (left_right_delegate_->CanScroll()) |
| 167 event->SetHandled(); |
| 168 } |
| 169 } |
| 170 |
| 171 } // namespace athena |
OLD | NEW |