Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: ui/events/gesture_detection/snap_scroll_controller.cc

Issue 1287103004: Sync ui/events to chromium @ https://codereview.chromium.org/1210203002 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: rebased Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/events/gesture_detection/snap_scroll_controller.h" 5 #include "ui/events/gesture_detection/snap_scroll_controller.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "ui/events/gesture_detection/motion_event.h" 9 #include "ui/events/gesture_detection/motion_event.h"
10 #include "ui/gfx/display.h"
11 10
12 namespace ui { 11 namespace ui {
13 namespace { 12 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 13
19 float CalculateChannelDistance(const gfx::Display& display) { 14 // Minimum ratio between initial X and Y motion to allow snapping.
20 if (display.bounds().IsEmpty()) 15 const float kMinSnapRatio = 1.25f;
21 return kMinSnapChannelDistance; 16
17 // Size of the snap rail relative to the initial snap bound threshold.
18 const float kSnapBoundToChannelMultiplier = 1.5f;
19
20 float CalculateChannelDistance(float snap_bound,
21 const gfx::SizeF& display_size) {
22 const float kMinChannelDistance = snap_bound * kSnapBoundToChannelMultiplier;
23 const float kMaxChannelDistance = kMinChannelDistance * 3.f;
24 const float kSnapChannelDipsPerScreenDip = kMinChannelDistance / 480.f;
25 if (display_size.IsEmpty())
26 return kMinChannelDistance;
22 27
23 float screen_size = 28 float screen_size =
24 std::abs(hypot(static_cast<float>(display.bounds().width()), 29 std::abs(hypot(static_cast<float>(display_size.width()),
25 static_cast<float>(display.bounds().height()))); 30 static_cast<float>(display_size.height())));
26 31
27 float snap_channel_distance = screen_size * kSnapChannelDipsPerScreenDip; 32 float snap_channel_distance = screen_size * kSnapChannelDipsPerScreenDip;
28 return std::max(kMinSnapChannelDistance, 33 return std::max(kMinChannelDistance,
29 std::min(kMaxSnapChannelDistance, snap_channel_distance)); 34 std::min(kMaxChannelDistance, snap_channel_distance));
30 } 35 }
31 36
32 } // namespace 37 } // namespace
33 38
34 39 SnapScrollController::SnapScrollController(float snap_bound,
35 SnapScrollController::SnapScrollController(const gfx::Display& display) 40 const gfx::SizeF& display_size)
36 : channel_distance_(CalculateChannelDistance(display)), 41 : snap_bound_(snap_bound),
37 snap_scroll_mode_(SNAP_NONE), 42 channel_distance_(CalculateChannelDistance(snap_bound, display_size)),
38 first_touch_x_(-1), 43 mode_(SNAP_NONE) {
39 first_touch_y_(-1),
40 distance_x_(0),
41 distance_y_(0) {}
42
43 SnapScrollController::~SnapScrollController() {}
44
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 } 44 }
67 45
68 void SnapScrollController::SetSnapScrollingMode( 46 SnapScrollController::~SnapScrollController() {
47 }
48
49 void SnapScrollController::SetSnapScrollMode(
69 const MotionEvent& event, 50 const MotionEvent& event,
70 bool is_scale_gesture_detection_in_progress) { 51 bool is_scale_gesture_detection_in_progress) {
71 switch (event.GetAction()) { 52 switch (event.GetAction()) {
72 case MotionEvent::ACTION_DOWN: 53 case MotionEvent::ACTION_DOWN:
73 snap_scroll_mode_ = SNAP_NONE; 54 mode_ = SNAP_PENDING;
74 first_touch_x_ = event.GetX(); 55 down_position_.set_x(event.GetX());
75 first_touch_y_ = event.GetY(); 56 down_position_.set_y(event.GetY());
76 break; 57 break;
77 // Set scrolling mode to SNAP_X if scroll towards x-axis exceeds kSnapBound 58 case MotionEvent::ACTION_MOVE: {
78 // and movement towards y-axis is trivial. 59 if (is_scale_gesture_detection_in_progress)
79 // Set scrolling mode to SNAP_Y if scroll towards y-axis exceeds kSnapBound 60 break;
80 // and movement towards x-axis is trivial. 61
81 // Scrolling mode will remain in SNAP_NONE for other conditions. 62 if (mode_ != SNAP_PENDING)
82 case MotionEvent::ACTION_MOVE: 63 break;
83 if (!is_scale_gesture_detection_in_progress && 64
84 snap_scroll_mode_ == SNAP_NONE) { 65 // Set scrolling mode to SNAP_X if scroll exceeds |snap_bound_| and the
85 int x_diff = static_cast<int>(std::abs(event.GetX() - first_touch_x_)); 66 // ratio of x movement to y movement is sufficiently large. Similarly for
86 int y_diff = static_cast<int>(std::abs(event.GetY() - first_touch_y_)); 67 // SNAP_Y and y movement.
87 if (x_diff > kSnapBound && y_diff < kSnapBound) { 68 float dx = std::abs(event.GetX() - down_position_.x());
88 snap_scroll_mode_ = SNAP_HORIZ; 69 float dy = std::abs(event.GetY() - down_position_.y());
89 } else if (x_diff < kSnapBound && y_diff > kSnapBound) { 70 float kMinSnapBound = snap_bound_;
90 snap_scroll_mode_ = SNAP_VERT; 71 float kMaxSnapBound = snap_bound_ * 2.f;
91 } 72 if (dx * dx + dy * dy > kMinSnapBound * kMinSnapBound) {
73 if (!dy || (dx / dy > kMinSnapRatio && dy < kMaxSnapBound))
74 mode_ = SNAP_HORIZ;
75 else if (!dx || (dy / dx > kMinSnapRatio && dx < kMaxSnapBound))
76 mode_ = SNAP_VERT;
92 } 77 }
93 break; 78
79 if (mode_ == SNAP_PENDING && dx > kMaxSnapBound && dy > kMaxSnapBound)
80 mode_ = SNAP_NONE;
81 } break;
94 case MotionEvent::ACTION_UP: 82 case MotionEvent::ACTION_UP:
95 case MotionEvent::ACTION_CANCEL: 83 case MotionEvent::ACTION_CANCEL:
96 first_touch_x_ = -1; 84 down_position_ = gfx::PointF();
97 first_touch_y_ = -1; 85 accumulated_distance_ = gfx::Vector2dF();
98 distance_x_ = 0;
99 distance_y_ = 0;
100 break; 86 break;
101 default: 87 default:
102 break; 88 break;
103 } 89 }
104 } 90 }
105 91
92 void SnapScrollController::UpdateSnapScrollMode(float distance_x,
93 float distance_y) {
94 if (!IsSnappingScrolls())
95 return;
96
97 accumulated_distance_ +=
98 gfx::Vector2dF(std::abs(distance_x), std::abs(distance_y));
99 if (mode_ == SNAP_HORIZ) {
100 if (accumulated_distance_.y() > channel_distance_)
101 mode_ = SNAP_NONE;
102 else if (accumulated_distance_.x() > channel_distance_)
103 accumulated_distance_ = gfx::Vector2dF();
104 } else if (mode_ == SNAP_VERT) {
105 if (accumulated_distance_.x() > channel_distance_)
106 mode_ = SNAP_NONE;
107 else if (accumulated_distance_.y() > channel_distance_)
108 accumulated_distance_ = gfx::Vector2dF();
109 }
110 }
111
112 bool SnapScrollController::IsSnapVertical() const {
113 return mode_ == SNAP_VERT;
114 }
115
116 bool SnapScrollController::IsSnapHorizontal() const {
117 return mode_ == SNAP_HORIZ;
118 }
119
120 bool SnapScrollController::IsSnappingScrolls() const {
121 return IsSnapHorizontal() || IsSnapVertical();
122 }
123
106 } // namespace ui 124 } // namespace ui
OLDNEW
« no previous file with comments | « ui/events/gesture_detection/snap_scroll_controller.h ('k') | ui/events/gesture_detection/snap_scroll_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698