• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ui/events/gesture_detection/snap_scroll_controller.h"
6 
7 #include <cmath>
8 
9 #include "ui/events/gesture_detection/motion_event.h"
10 #include "ui/gfx/display.h"
11 
12 namespace ui {
13 namespace {
14 const int kSnapBound = 16;
15 const float kMinSnapChannelDistance = kSnapBound;
16 const float kMaxSnapChannelDistance = kMinSnapChannelDistance * 3.f;
17 const float kSnapChannelDipsPerScreenDip = kMinSnapChannelDistance / 480.f;
18 
CalculateChannelDistance(const gfx::Display & display)19 float CalculateChannelDistance(const gfx::Display& display) {
20   if (display.bounds().IsEmpty())
21     return kMinSnapChannelDistance;
22 
23   float screen_size =
24       std::abs(hypot(static_cast<float>(display.bounds().width()),
25                      static_cast<float>(display.bounds().height())));
26 
27   float snap_channel_distance = screen_size * kSnapChannelDipsPerScreenDip;
28   return std::max(kMinSnapChannelDistance,
29                   std::min(kMaxSnapChannelDistance, snap_channel_distance));
30 }
31 
32 }  // namespace
33 
34 
SnapScrollController(const gfx::Display & display)35 SnapScrollController::SnapScrollController(const gfx::Display& display)
36     : channel_distance_(CalculateChannelDistance(display)),
37       snap_scroll_mode_(SNAP_NONE),
38       first_touch_x_(-1),
39       first_touch_y_(-1),
40       distance_x_(0),
41       distance_y_(0) {}
42 
~SnapScrollController()43 SnapScrollController::~SnapScrollController() {}
44 
UpdateSnapScrollMode(float distance_x,float distance_y)45 void SnapScrollController::UpdateSnapScrollMode(float distance_x,
46                                                 float distance_y) {
47   if (snap_scroll_mode_ == SNAP_HORIZ || snap_scroll_mode_ == SNAP_VERT) {
48     distance_x_ += std::abs(distance_x);
49     distance_y_ += std::abs(distance_y);
50     if (snap_scroll_mode_ == SNAP_HORIZ) {
51       if (distance_y_ > channel_distance_) {
52         snap_scroll_mode_ = SNAP_NONE;
53       } else if (distance_x_ > channel_distance_) {
54         distance_x_ = 0;
55         distance_y_ = 0;
56       }
57     } else {
58       if (distance_x_ > channel_distance_) {
59         snap_scroll_mode_ = SNAP_NONE;
60       } else if (distance_y_ > channel_distance_) {
61         distance_x_ = 0;
62         distance_y_ = 0;
63       }
64     }
65   }
66 }
67 
SetSnapScrollingMode(const MotionEvent & event,bool is_scale_gesture_detection_in_progress)68 void SnapScrollController::SetSnapScrollingMode(
69     const MotionEvent& event,
70     bool is_scale_gesture_detection_in_progress) {
71   switch (event.GetAction()) {
72     case MotionEvent::ACTION_DOWN:
73       snap_scroll_mode_ = SNAP_NONE;
74       first_touch_x_ = event.GetX();
75       first_touch_y_ = event.GetY();
76       break;
77     // Set scrolling mode to SNAP_X if scroll towards x-axis exceeds kSnapBound
78     // and movement towards y-axis is trivial.
79     // Set scrolling mode to SNAP_Y if scroll towards y-axis exceeds kSnapBound
80     // and movement towards x-axis is trivial.
81     // Scrolling mode will remain in SNAP_NONE for other conditions.
82     case MotionEvent::ACTION_MOVE:
83       if (!is_scale_gesture_detection_in_progress &&
84           snap_scroll_mode_ == SNAP_NONE) {
85         int x_diff = static_cast<int>(std::abs(event.GetX() - first_touch_x_));
86         int y_diff = static_cast<int>(std::abs(event.GetY() - first_touch_y_));
87         if (x_diff > kSnapBound && y_diff < kSnapBound) {
88           snap_scroll_mode_ = SNAP_HORIZ;
89         } else if (x_diff < kSnapBound && y_diff > kSnapBound) {
90           snap_scroll_mode_ = SNAP_VERT;
91         }
92       }
93       break;
94     case MotionEvent::ACTION_UP:
95     case MotionEvent::ACTION_CANCEL:
96       first_touch_x_ = -1;
97       first_touch_y_ = -1;
98       distance_x_ = 0;
99       distance_y_ = 0;
100       break;
101     default:
102       break;
103   }
104 }
105 
106 }  // namespace ui
107