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

Side by Side Diff: content/browser/android/overscroll_controller_android.cc

Issue 733293002: [Android] Add a flag to disable the pull-to-refresh effect (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 6 years, 1 month 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 "content/browser/android/overscroll_controller_android.h" 5 #include "content/browser/android/overscroll_controller_android.h"
6 6
7 #include "base/android/build_info.h" 7 #include "base/android/build_info.h"
8 #include "base/bind.h" 8 #include "base/command_line.h"
9 #include "cc/layers/layer.h" 9 #include "cc/layers/layer.h"
10 #include "cc/output/compositor_frame_metadata.h" 10 #include "cc/output/compositor_frame_metadata.h"
11 #include "content/browser/android/edge_effect.h" 11 #include "content/browser/android/edge_effect.h"
12 #include "content/browser/android/edge_effect_l.h" 12 #include "content/browser/android/edge_effect_l.h"
13 #include "content/common/input/did_overscroll_params.h" 13 #include "content/common/input/did_overscroll_params.h"
14 #include "content/public/browser/web_contents.h" 14 #include "content/public/browser/web_contents.h"
15 #include "content/public/common/content_switches.h"
15 #include "third_party/WebKit/public/web/WebInputEvent.h" 16 #include "third_party/WebKit/public/web/WebInputEvent.h"
16 #include "ui/base/android/window_android_compositor.h" 17 #include "ui/base/android/window_android_compositor.h"
17 18
18 namespace content { 19 namespace content {
19 namespace { 20 namespace {
20 21
21 // Used for conditional creation of EdgeEffect types for the overscroll glow. 22 // Used for conditional creation of EdgeEffect types for the overscroll glow.
22 const int kAndroidLSDKVersion = 21; 23 const int kAndroidLSDKVersion = 21;
23 24
24 // Default offset in dips from the top of the view beyond which the refresh 25 // Default offset in dips from the top of the view beyond which the refresh
25 // action will be activated. 26 // action will be activated.
26 const int kDefaultRefreshDragTargetDips = 64; 27 const int kDefaultRefreshDragTargetDips = 64;
27 28
28 scoped_ptr<EdgeEffectBase> CreateGlowEdgeEffect( 29 scoped_ptr<EdgeEffectBase> CreateGlowEdgeEffect(
29 ui::SystemUIResourceManager* resource_manager, 30 ui::SystemUIResourceManager* resource_manager,
30 float dpi_scale) { 31 float dpi_scale) {
31 DCHECK(resource_manager); 32 DCHECK(resource_manager);
32 static bool use_l_flavoured_effect = 33 static bool use_l_flavoured_effect =
33 base::android::BuildInfo::GetInstance()->sdk_int() >= kAndroidLSDKVersion; 34 base::android::BuildInfo::GetInstance()->sdk_int() >= kAndroidLSDKVersion;
34 if (use_l_flavoured_effect) 35 if (use_l_flavoured_effect)
35 return scoped_ptr<EdgeEffectBase>(new EdgeEffectL(resource_manager)); 36 return scoped_ptr<EdgeEffectBase>(new EdgeEffectL(resource_manager));
36 37
37 return scoped_ptr<EdgeEffectBase>( 38 return scoped_ptr<EdgeEffectBase>(
38 new EdgeEffect(resource_manager, dpi_scale)); 39 new EdgeEffect(resource_manager, dpi_scale));
39 } 40 }
40 41
42 scoped_ptr<OverscrollGlow> CreateGlowEffect(OverscrollGlowClient* client,
43 float dpi_scale) {
44 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
45 switches::kDisableOverscrollEdgeEffect)) {
46 return nullptr;
47 }
48
49 return make_scoped_ptr(new OverscrollGlow(client));
50 }
51
52 scoped_ptr<OverscrollRefresh> CreateRefreshEffect(
53 ui::WindowAndroidCompositor* compositor,
54 OverscrollRefreshClient* client,
55 float dpi_scale) {
56 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
57 switches::kDisablePullToRefreshEffect)) {
58 return nullptr;
59 }
60
61 return make_scoped_ptr(
62 new OverscrollRefresh(&compositor->GetSystemUIResourceManager(), client,
63 kDefaultRefreshDragTargetDips * dpi_scale));
64 }
65
41 } // namespace 66 } // namespace
42 67
43 OverscrollControllerAndroid::OverscrollControllerAndroid( 68 OverscrollControllerAndroid::OverscrollControllerAndroid(
44 WebContents* web_contents, 69 WebContents* web_contents,
45 ui::WindowAndroidCompositor* compositor, 70 ui::WindowAndroidCompositor* compositor,
46 float dpi_scale) 71 float dpi_scale)
47 : WebContentsObserver(web_contents), 72 : compositor_(compositor),
48 compositor_(compositor),
49 dpi_scale_(dpi_scale), 73 dpi_scale_(dpi_scale),
50 enabled_(true), 74 enabled_(true),
51 glow_effect_(base::Bind(&CreateGlowEdgeEffect, 75 glow_effect_(CreateGlowEffect(this, dpi_scale)),
52 &compositor->GetSystemUIResourceManager(), 76 refresh_effect_(CreateRefreshEffect(compositor, this, dpi_scale)),
53 dpi_scale_)),
54 refresh_effect_(&compositor->GetSystemUIResourceManager(),
55 this,
56 kDefaultRefreshDragTargetDips * dpi_scale),
57 triggered_refresh_active_(false) { 77 triggered_refresh_active_(false) {
58 DCHECK(web_contents); 78 DCHECK(web_contents);
79 DCHECK(compositor);
80 if (refresh_effect_)
81 Observe(web_contents);
59 } 82 }
60 83
61 OverscrollControllerAndroid::~OverscrollControllerAndroid() { 84 OverscrollControllerAndroid::~OverscrollControllerAndroid() {
62 } 85 }
63 86
64 bool OverscrollControllerAndroid::WillHandleGestureEvent( 87 bool OverscrollControllerAndroid::WillHandleGestureEvent(
65 const blink::WebGestureEvent& event) { 88 const blink::WebGestureEvent& event) {
66 if (!enabled_) 89 if (!enabled_)
67 return false; 90 return false;
68 91
92 if (!refresh_effect_)
93 return false;
94
69 bool handled = false; 95 bool handled = false;
70 bool maybe_needs_animate = false; 96 bool maybe_needs_animate = false;
71 switch (event.type) { 97 switch (event.type) {
72 case blink::WebInputEvent::GestureScrollBegin: 98 case blink::WebInputEvent::GestureScrollBegin:
73 refresh_effect_.OnScrollBegin(); 99 refresh_effect_->OnScrollBegin();
74 break; 100 break;
75 101
76 case blink::WebInputEvent::GestureScrollUpdate: { 102 case blink::WebInputEvent::GestureScrollUpdate: {
77 gfx::Vector2dF scroll_delta(event.data.scrollUpdate.deltaX, 103 gfx::Vector2dF scroll_delta(event.data.scrollUpdate.deltaX,
78 event.data.scrollUpdate.deltaY); 104 event.data.scrollUpdate.deltaY);
79 scroll_delta.Scale(dpi_scale_); 105 scroll_delta.Scale(dpi_scale_);
80 maybe_needs_animate = true; 106 maybe_needs_animate = true;
81 handled = refresh_effect_.WillHandleScrollUpdate(scroll_delta); 107 handled = refresh_effect_->WillHandleScrollUpdate(scroll_delta);
82 } break; 108 } break;
83 109
84 case blink::WebInputEvent::GestureScrollEnd: 110 case blink::WebInputEvent::GestureScrollEnd:
85 refresh_effect_.OnScrollEnd(gfx::Vector2dF()); 111 refresh_effect_->OnScrollEnd(gfx::Vector2dF());
86 maybe_needs_animate = true; 112 maybe_needs_animate = true;
87 break; 113 break;
88 114
89 case blink::WebInputEvent::GestureFlingStart: { 115 case blink::WebInputEvent::GestureFlingStart: {
90 gfx::Vector2dF scroll_velocity(event.data.flingStart.velocityX, 116 gfx::Vector2dF scroll_velocity(event.data.flingStart.velocityX,
91 event.data.flingStart.velocityY); 117 event.data.flingStart.velocityY);
92 scroll_velocity.Scale(dpi_scale_); 118 scroll_velocity.Scale(dpi_scale_);
93 refresh_effect_.OnScrollEnd(scroll_velocity); 119 refresh_effect_->OnScrollEnd(scroll_velocity);
94 if (refresh_effect_.IsActive()) { 120 if (refresh_effect_->IsActive()) {
95 // TODO(jdduke): Figure out a cleaner way of suppressing a fling. 121 // TODO(jdduke): Figure out a cleaner way of suppressing a fling.
96 // It's important that the any downstream code sees a scroll-ending 122 // It's important that the any downstream code sees a scroll-ending
97 // event (in this case GestureFlingStart) if it has seen a scroll begin. 123 // event (in this case GestureFlingStart) if it has seen a scroll begin.
98 // Thus, we cannot simply consume the fling. Changing the event type to 124 // Thus, we cannot simply consume the fling. Changing the event type to
99 // a GestureScrollEnd might work in practice, but could lead to 125 // a GestureScrollEnd might work in practice, but could lead to
100 // unexpected results. For now, simply truncate the fling velocity, but 126 // unexpected results. For now, simply truncate the fling velocity, but
101 // not to zero as downstream code may not expect a zero-velocity fling. 127 // not to zero as downstream code may not expect a zero-velocity fling.
102 blink::WebGestureEvent& modified_event = 128 blink::WebGestureEvent& modified_event =
103 const_cast<blink::WebGestureEvent&>(event); 129 const_cast<blink::WebGestureEvent&>(event);
104 modified_event.data.flingStart.velocityX = .01f; 130 modified_event.data.flingStart.velocityX = .01f;
105 modified_event.data.flingStart.velocityY = .01f; 131 modified_event.data.flingStart.velocityY = .01f;
106 } 132 }
107 maybe_needs_animate = true; 133 maybe_needs_animate = true;
108 } break; 134 } break;
109 135
110 default: 136 default:
111 break; 137 break;
112 } 138 }
113 139
114 if (maybe_needs_animate && refresh_effect_.IsActive()) 140 if (maybe_needs_animate && refresh_effect_->IsActive())
115 SetNeedsAnimate(); 141 SetNeedsAnimate();
116 142
117 return handled; 143 return handled;
118 } 144 }
119 145
120 void OverscrollControllerAndroid::OnGestureEventAck( 146 void OverscrollControllerAndroid::OnGestureEventAck(
121 const blink::WebGestureEvent& event, 147 const blink::WebGestureEvent& event,
122 InputEventAckState ack_result) { 148 InputEventAckState ack_result) {
123 if (!enabled_) 149 if (!enabled_)
124 return; 150 return;
125 151
126 // The overscroll effect requires an explicit release signal that may not be 152 // The overscroll effect requires an explicit release signal that may not be
127 // sent from the renderer compositor. 153 // sent from the renderer compositor.
128 if (event.type == blink::WebInputEvent::GestureScrollEnd || 154 if (event.type == blink::WebInputEvent::GestureScrollEnd ||
129 event.type == blink::WebInputEvent::GestureFlingStart) { 155 event.type == blink::WebInputEvent::GestureFlingStart) {
130 OnOverscrolled(DidOverscrollParams()); 156 OnOverscrolled(DidOverscrollParams());
131 } 157 }
132 158
133 if (event.type == blink::WebInputEvent::GestureScrollUpdate) { 159 if (event.type == blink::WebInputEvent::GestureScrollUpdate &&
160 refresh_effect_) {
134 // The effect should only be allowed if both the causal touch events go 161 // The effect should only be allowed if both the causal touch events go
135 // unconsumed and the generated scroll events go unconsumed. 162 // unconsumed and the generated scroll events go unconsumed.
136 bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED || 163 bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED ||
137 event.data.scrollUpdate.previousUpdateInSequencePrevented; 164 event.data.scrollUpdate.previousUpdateInSequencePrevented;
138 refresh_effect_.OnScrollUpdateAck(consumed); 165 refresh_effect_->OnScrollUpdateAck(consumed);
139 } 166 }
140 } 167 }
141 168
142 void OverscrollControllerAndroid::OnOverscrolled( 169 void OverscrollControllerAndroid::OnOverscrolled(
143 const DidOverscrollParams& params) { 170 const DidOverscrollParams& params) {
144 if (!enabled_) 171 if (!enabled_)
145 return; 172 return;
146 173
147 if (refresh_effect_.IsActive() || 174 if (refresh_effect_ && (refresh_effect_->IsActive() ||
148 refresh_effect_.IsAwaitingScrollUpdateAck()) { 175 refresh_effect_->IsAwaitingScrollUpdateAck())) {
149 // An active (or potentially active) refresh effect should always pre-empt 176 // An active (or potentially active) refresh effect should always pre-empt
150 // the passive glow effect. 177 // the passive glow effect.
151 return; 178 return;
152 } 179 }
153 180
154 if (glow_effect_.OnOverscrolled( 181 if (glow_effect_ &&
155 base::TimeTicks::Now(), 182 glow_effect_->OnOverscrolled(
156 gfx::ScaleVector2d(params.accumulated_overscroll, dpi_scale_), 183 base::TimeTicks::Now(),
157 gfx::ScaleVector2d(params.latest_overscroll_delta, dpi_scale_), 184 gfx::ScaleVector2d(params.accumulated_overscroll, dpi_scale_),
158 gfx::ScaleVector2d(params.current_fling_velocity, dpi_scale_), 185 gfx::ScaleVector2d(params.latest_overscroll_delta, dpi_scale_),
159 gfx::ScaleVector2d(params.causal_event_viewport_point.OffsetFromOrigin(), 186 gfx::ScaleVector2d(params.current_fling_velocity, dpi_scale_),
160 dpi_scale_))) { 187 gfx::ScaleVector2d(
188 params.causal_event_viewport_point.OffsetFromOrigin(),
189 dpi_scale_))) {
161 SetNeedsAnimate(); 190 SetNeedsAnimate();
162 } 191 }
163 } 192 }
164 193
165 bool OverscrollControllerAndroid::Animate(base::TimeTicks current_time, 194 bool OverscrollControllerAndroid::Animate(base::TimeTicks current_time,
166 cc::Layer* parent_layer) { 195 cc::Layer* parent_layer) {
167 DCHECK(parent_layer); 196 DCHECK(parent_layer);
168 if (!enabled_) 197 if (!enabled_)
169 return false; 198 return false;
170 199
171 bool needs_animate = refresh_effect_.Animate(current_time, parent_layer); 200 bool needs_animate = false;
172 needs_animate |= glow_effect_.Animate(current_time, parent_layer); 201 if (refresh_effect_)
202 needs_animate |= refresh_effect_->Animate(current_time, parent_layer);
203 if (glow_effect_)
204 needs_animate |= glow_effect_->Animate(current_time, parent_layer);
173 return needs_animate; 205 return needs_animate;
174 } 206 }
175 207
176 void OverscrollControllerAndroid::OnFrameMetadataUpdated( 208 void OverscrollControllerAndroid::OnFrameMetadataUpdated(
177 const cc::CompositorFrameMetadata& frame_metadata) { 209 const cc::CompositorFrameMetadata& frame_metadata) {
210 if (!refresh_effect_ && !glow_effect_)
211 return;
212
178 const float scale_factor = 213 const float scale_factor =
179 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor; 214 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor;
180 gfx::SizeF viewport_size = 215 gfx::SizeF viewport_size =
181 gfx::ScaleSize(frame_metadata.scrollable_viewport_size, scale_factor); 216 gfx::ScaleSize(frame_metadata.scrollable_viewport_size, scale_factor);
182 gfx::SizeF content_size = 217 gfx::SizeF content_size =
183 gfx::ScaleSize(frame_metadata.root_layer_size, scale_factor); 218 gfx::ScaleSize(frame_metadata.root_layer_size, scale_factor);
184 gfx::Vector2dF content_scroll_offset = 219 gfx::Vector2dF content_scroll_offset =
185 gfx::ScaleVector2d(frame_metadata.root_scroll_offset, scale_factor); 220 gfx::ScaleVector2d(frame_metadata.root_scroll_offset, scale_factor);
186 221
187 refresh_effect_.UpdateDisplay(viewport_size, content_scroll_offset); 222 if (refresh_effect_)
188 glow_effect_.UpdateDisplay(viewport_size, content_size, 223 refresh_effect_->UpdateDisplay(viewport_size, content_scroll_offset);
189 content_scroll_offset); 224
225 if (glow_effect_) {
226 glow_effect_->UpdateDisplay(viewport_size, content_size,
227 content_scroll_offset);
228 }
190 } 229 }
191 230
192 void OverscrollControllerAndroid::Enable() { 231 void OverscrollControllerAndroid::Enable() {
193 enabled_ = true; 232 enabled_ = true;
194 } 233 }
195 234
196 void OverscrollControllerAndroid::Disable() { 235 void OverscrollControllerAndroid::Disable() {
197 if (!enabled_) 236 if (!enabled_)
198 return; 237 return;
199 enabled_ = false; 238 enabled_ = false;
200 if (!enabled_) { 239 if (!enabled_) {
201 refresh_effect_.Reset(); 240 if (refresh_effect_)
202 glow_effect_.Reset(); 241 refresh_effect_->Reset();
242 if (glow_effect_)
243 glow_effect_->Reset();
203 } 244 }
204 } 245 }
205 246
206 void OverscrollControllerAndroid::DidNavigateMainFrame( 247 void OverscrollControllerAndroid::DidNavigateMainFrame(
207 const LoadCommittedDetails& details, 248 const LoadCommittedDetails& details,
208 const FrameNavigateParams& params) { 249 const FrameNavigateParams& params) {
209 // Once the main frame has navigated, there's little need to further animate 250 // Once the main frame has navigated, there's little need to further animate
210 // the reload effect. Note that the effect will naturally time out should the 251 // the reload effect. Note that the effect will naturally time out should the
211 // reload be interruped for any reason. 252 // reload be interruped for any reason.
212 triggered_refresh_active_ = false; 253 triggered_refresh_active_ = false;
213 } 254 }
214 255
215 void OverscrollControllerAndroid::TriggerRefresh() { 256 void OverscrollControllerAndroid::TriggerRefresh() {
216 triggered_refresh_active_ = false; 257 triggered_refresh_active_ = false;
217 if (!web_contents()) 258 if (!web_contents())
218 return; 259 return;
219 260
220 triggered_refresh_active_ = true; 261 triggered_refresh_active_ = true;
221 web_contents()->ReloadFocusedFrame(false); 262 web_contents()->ReloadFocusedFrame(false);
222 } 263 }
223 264
224 bool OverscrollControllerAndroid::IsStillRefreshing() const { 265 bool OverscrollControllerAndroid::IsStillRefreshing() const {
225 return triggered_refresh_active_; 266 return triggered_refresh_active_;
226 } 267 }
227 268
269 scoped_ptr<EdgeEffectBase> OverscrollControllerAndroid::CreateEdgeEffect() {
270 return CreateGlowEdgeEffect(&compositor_->GetSystemUIResourceManager(),
271 dpi_scale_);
272 }
273
228 void OverscrollControllerAndroid::SetNeedsAnimate() { 274 void OverscrollControllerAndroid::SetNeedsAnimate() {
229 compositor_->SetNeedsAnimate(); 275 compositor_->SetNeedsAnimate();
230 } 276 }
231 277
232 } // namespace content 278 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/android/overscroll_controller_android.h ('k') | content/browser/android/overscroll_glow.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698