| // 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 "ash/app_list/pagination_controller.h" |
| |
| #include "ash/app_list/pagination_model.h" |
| #include "ash/public/cpp/app_list/app_list_constants.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "ui/events/event.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/vector2d.h" |
| |
| namespace app_list { |
| |
| namespace { |
| |
| // Constants for dealing with scroll events. |
| const int kMinScrollToSwitchPage = 20; |
| const int kMinHorizVelocityToSwitchPage = 800; |
| |
| const double kFinishTransitionThreshold = 0.33; |
| |
| } // namespace |
| |
| PaginationController::PaginationController(PaginationModel* model, |
| ScrollAxis scroll_axis) |
| : pagination_model_(model), scroll_axis_(scroll_axis) {} |
| |
| bool PaginationController::OnScroll(const gfx::Vector2d& offset, |
| ui::EventType type) { |
| int offset_magnitude; |
| if (scroll_axis_ == SCROLL_AXIS_HORIZONTAL) { |
| // If the view scrolls horizontally, both horizontal and vertical scroll |
| // events are valid (since most mouse wheels only have vertical scrolling). |
| offset_magnitude = |
| abs(offset.x()) > abs(offset.y()) ? offset.x() : offset.y(); |
| } else { |
| // If the view scrolls vertically, only vertical scroll events are valid. |
| offset_magnitude = offset.y(); |
| } |
| |
| // Do not scroll on very small events. |
| // TODO(calamity): This should only apply on touchpad scroll but touchpad |
| // events are coming in as mousewheel events. See https://crbug.com/594264. |
| if (abs(offset_magnitude) > kMinScrollToSwitchPage && |
| !pagination_model_->has_transition()) { |
| const int delta = offset_magnitude > 0 ? -1 : 1; |
| if (pagination_model_->IsValidPageRelative(delta)) { |
| UMA_HISTOGRAM_ENUMERATION(kAppListPageSwitcherSourceHistogram, |
| type == ui::EventType::ET_MOUSEWHEEL |
| ? kMouseWheelScroll |
| : kMousePadScroll, |
| kMaxAppListPageSwitcherSource); |
| } |
| pagination_model_->SelectPageRelative(delta, true); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| bool PaginationController::OnGestureEvent(const ui::GestureEvent& event, |
| const gfx::Rect& bounds) { |
| const ui::GestureEventDetails& details = event.details(); |
| switch (event.type()) { |
| case ui::ET_GESTURE_SCROLL_BEGIN: { |
| float scroll = scroll_axis_ == SCROLL_AXIS_HORIZONTAL |
| ? details.scroll_x_hint() |
| : details.scroll_y_hint(); |
| if (scroll == 0) |
| return false; |
| pagination_model_->StartScroll(); |
| return true; |
| } |
| case ui::ET_GESTURE_SCROLL_UPDATE: { |
| float scroll = scroll_axis_ == SCROLL_AXIS_HORIZONTAL |
| ? details.scroll_x() |
| : details.scroll_y(); |
| if (!pagination_model_->IsValidPageRelative(scroll < 0 ? 1 : -1) && |
| !pagination_model_->has_transition()) { |
| // scroll > 0 means moving contents right or down. That is, |
| // transitioning to the previous page. If scrolling to an invalid page, |
| // ignore the event until movement continues in a valid direction. |
| return true; |
| } |
| int width = scroll_axis_ == SCROLL_AXIS_HORIZONTAL ? bounds.width() |
| : bounds.height(); |
| pagination_model_->UpdateScroll(scroll / width); |
| return true; |
| } |
| case ui::ET_GESTURE_SCROLL_END: { |
| const bool cancel_transition = |
| pagination_model_->transition().progress < kFinishTransitionThreshold; |
| pagination_model_->EndScroll(cancel_transition); |
| if (!cancel_transition) { |
| UMA_HISTOGRAM_ENUMERATION(kAppListPageSwitcherSourceHistogram, |
| kSwipeAppGrid, kMaxAppListPageSwitcherSource); |
| } |
| return true; |
| } |
| case ui::ET_SCROLL_FLING_START: { |
| float velocity = scroll_axis_ == SCROLL_AXIS_HORIZONTAL |
| ? details.velocity_x() |
| : details.velocity_y(); |
| pagination_model_->EndScroll(true); |
| |
| if (fabs(velocity) > kMinHorizVelocityToSwitchPage) { |
| const int delta = velocity < 0 ? 1 : -1; |
| if (pagination_model_->IsValidPageRelative(delta)) { |
| UMA_HISTOGRAM_ENUMERATION(kAppListPageSwitcherSourceHistogram, |
| kFlingAppGrid, |
| kMaxAppListPageSwitcherSource); |
| } |
| pagination_model_->SelectPageRelative(delta, true); |
| } |
| return true; |
| } |
| default: |
| return false; |
| } |
| } |
| |
| } // namespace app_list |