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

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: 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/bind.h"
9 #include "base/command_line.h"
9 #include "cc/layers/layer.h" 10 #include "cc/layers/layer.h"
10 #include "cc/output/compositor_frame_metadata.h" 11 #include "cc/output/compositor_frame_metadata.h"
11 #include "content/browser/android/edge_effect.h" 12 #include "content/browser/android/edge_effect.h"
12 #include "content/browser/android/edge_effect_l.h" 13 #include "content/browser/android/edge_effect_l.h"
13 #include "content/common/input/did_overscroll_params.h" 14 #include "content/common/input/did_overscroll_params.h"
14 #include "content/public/browser/web_contents.h" 15 #include "content/public/browser/web_contents.h"
16 #include "content/public/common/content_switches.h"
15 #include "third_party/WebKit/public/web/WebInputEvent.h" 17 #include "third_party/WebKit/public/web/WebInputEvent.h"
16 #include "ui/base/android/window_android_compositor.h" 18 #include "ui/base/android/window_android_compositor.h"
17 19
18 namespace content { 20 namespace content {
19 namespace { 21 namespace {
20 22
21 // Used for conditional creation of EdgeEffect types for the overscroll glow. 23 // Used for conditional creation of EdgeEffect types for the overscroll glow.
22 const int kAndroidLSDKVersion = 21; 24 const int kAndroidLSDKVersion = 21;
23 25
24 scoped_ptr<EdgeEffectBase> CreateGlowEdgeEffect( 26 scoped_ptr<EdgeEffectBase> CreateGlowEdgeEffect(
25 ui::SystemUIResourceManager* resource_manager, 27 ui::SystemUIResourceManager* resource_manager,
26 float dpi_scale) { 28 float dpi_scale) {
27 DCHECK(resource_manager); 29 DCHECK(resource_manager);
28 static bool use_l_flavoured_effect = 30 static bool use_l_flavoured_effect =
29 base::android::BuildInfo::GetInstance()->sdk_int() >= kAndroidLSDKVersion; 31 base::android::BuildInfo::GetInstance()->sdk_int() >= kAndroidLSDKVersion;
30 if (use_l_flavoured_effect) 32 if (use_l_flavoured_effect)
31 return scoped_ptr<EdgeEffectBase>(new EdgeEffectL(resource_manager)); 33 return scoped_ptr<EdgeEffectBase>(new EdgeEffectL(resource_manager));
32 34
33 return scoped_ptr<EdgeEffectBase>( 35 return scoped_ptr<EdgeEffectBase>(
34 new EdgeEffect(resource_manager, dpi_scale)); 36 new EdgeEffect(resource_manager, dpi_scale));
35 } 37 }
36 38
39 scoped_ptr<OverscrollGlow> CreateGlowEffect(
40 ui::WindowAndroidCompositor* compositor,
41 float dpi_scale) {
42 static bool sEnableGlowEffect =
aelias_OOO_until_Jul13 2014/11/19 06:21:51 Please remove these statics, static global state o
jdduke (slow) 2014/11/19 16:56:22 Done.
43 !base::CommandLine::ForCurrentProcess()->HasSwitch(
44 switches::kDisableOverscrollEdgeEffect);
45 if (!sEnableGlowEffect)
46 return scoped_ptr<OverscrollGlow>();
47
48 return make_scoped_ptr(new OverscrollGlow(
49 base::Bind(&CreateGlowEdgeEffect,
50 &compositor->GetSystemUIResourceManager(), dpi_scale)));
51 }
52
53 scoped_ptr<OverscrollRefresh> CreateRefreshEffect(
54 ui::WindowAndroidCompositor* compositor,
55 OverscrollRefreshClient* client) {
56 static bool sEnableRefreshEffect =
57 !base::CommandLine::ForCurrentProcess()->HasSwitch(
58 switches::kDisablePullToRefreshEffect);
59 if (!sEnableRefreshEffect)
60 return scoped_ptr<OverscrollRefresh>();
61
62 return make_scoped_ptr(
63 new OverscrollRefresh(&compositor->GetSystemUIResourceManager(), client));
64 }
65
37 } // namespace 66 } // namespace
38 67
39 OverscrollControllerAndroid::OverscrollControllerAndroid( 68 OverscrollControllerAndroid::OverscrollControllerAndroid(
40 WebContents* web_contents, 69 WebContents* web_contents,
41 ui::WindowAndroidCompositor* compositor, 70 ui::WindowAndroidCompositor* compositor,
42 float dpi_scale) 71 float dpi_scale)
43 : WebContentsObserver(web_contents), 72 : WebContentsObserver(web_contents),
44 compositor_(compositor), 73 compositor_(compositor),
45 dpi_scale_(dpi_scale), 74 dpi_scale_(dpi_scale),
46 enabled_(true), 75 enabled_(false),
47 glow_effect_(base::Bind(&CreateGlowEdgeEffect, 76 glow_effect_(CreateGlowEffect(compositor, dpi_scale)),
48 &compositor->GetSystemUIResourceManager(), 77 refresh_effect_(CreateRefreshEffect(compositor, this)),
49 dpi_scale_)),
50 refresh_effect_(&compositor->GetSystemUIResourceManager(), this),
51 triggered_refresh_active_(false) { 78 triggered_refresh_active_(false) {
52 DCHECK(web_contents); 79 DCHECK(web_contents);
80 DCHECK(compositor);
81 enabled_ = glow_effect_ || refresh_effect_;
aelias_OOO_until_Jul13 2014/11/19 06:21:50 This complicates the meaning of "enabled_" by baki
jdduke (slow) 2014/11/19 16:56:22 Done.
53 } 82 }
54 83
55 OverscrollControllerAndroid::~OverscrollControllerAndroid() { 84 OverscrollControllerAndroid::~OverscrollControllerAndroid() {
56 } 85 }
57 86
58 bool OverscrollControllerAndroid::WillHandleGestureEvent( 87 bool OverscrollControllerAndroid::WillHandleGestureEvent(
59 const blink::WebGestureEvent& event) { 88 const blink::WebGestureEvent& event) {
60 if (!enabled_) 89 if (!enabled_)
61 return false; 90 return false;
62 91
92 if (!refresh_effect_)
93 return false;
94
63 bool handled = false; 95 bool handled = false;
64 bool maybe_needs_animate = false; 96 bool maybe_needs_animate = false;
65 switch (event.type) { 97 switch (event.type) {
66 case blink::WebInputEvent::GestureScrollBegin: 98 case blink::WebInputEvent::GestureScrollBegin:
67 refresh_effect_.OnScrollBegin(); 99 refresh_effect_->OnScrollBegin();
68 break; 100 break;
69 101
70 case blink::WebInputEvent::GestureScrollUpdate: { 102 case blink::WebInputEvent::GestureScrollUpdate: {
71 gfx::Vector2dF scroll_delta(event.data.scrollUpdate.deltaX, 103 gfx::Vector2dF scroll_delta(event.data.scrollUpdate.deltaX,
72 event.data.scrollUpdate.deltaY); 104 event.data.scrollUpdate.deltaY);
73 scroll_delta.Scale(dpi_scale_); 105 scroll_delta.Scale(dpi_scale_);
74 maybe_needs_animate = true; 106 maybe_needs_animate = true;
75 handled = refresh_effect_.WillHandleScrollUpdate(scroll_delta); 107 handled = refresh_effect_->WillHandleScrollUpdate(scroll_delta);
76 } break; 108 } break;
77 109
78 case blink::WebInputEvent::GestureScrollEnd: 110 case blink::WebInputEvent::GestureScrollEnd:
79 refresh_effect_.OnScrollEnd(gfx::Vector2dF()); 111 refresh_effect_->OnScrollEnd(gfx::Vector2dF());
80 maybe_needs_animate = true; 112 maybe_needs_animate = true;
81 break; 113 break;
82 114
83 case blink::WebInputEvent::GestureFlingStart: { 115 case blink::WebInputEvent::GestureFlingStart: {
84 gfx::Vector2dF scroll_velocity(event.data.flingStart.velocityX, 116 gfx::Vector2dF scroll_velocity(event.data.flingStart.velocityX,
85 event.data.flingStart.velocityY); 117 event.data.flingStart.velocityY);
86 scroll_velocity.Scale(dpi_scale_); 118 scroll_velocity.Scale(dpi_scale_);
87 refresh_effect_.OnScrollEnd(scroll_velocity); 119 refresh_effect_->OnScrollEnd(scroll_velocity);
88 if (refresh_effect_.IsActive()) { 120 if (refresh_effect_->IsActive()) {
89 // TODO(jdduke): Figure out a cleaner way of suppressing a fling. 121 // TODO(jdduke): Figure out a cleaner way of suppressing a fling.
90 // 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
91 // 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.
92 // 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
93 // a GestureScrollEnd might work in practice, but could lead to 125 // a GestureScrollEnd might work in practice, but could lead to
94 // unexpected results. For now, simply truncate the fling velocity, but 126 // unexpected results. For now, simply truncate the fling velocity, but
95 // 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.
96 blink::WebGestureEvent& modified_event = 128 blink::WebGestureEvent& modified_event =
97 const_cast<blink::WebGestureEvent&>(event); 129 const_cast<blink::WebGestureEvent&>(event);
98 modified_event.data.flingStart.velocityX = .01f; 130 modified_event.data.flingStart.velocityX = .01f;
99 modified_event.data.flingStart.velocityY = .01f; 131 modified_event.data.flingStart.velocityY = .01f;
100 } 132 }
101 maybe_needs_animate = true; 133 maybe_needs_animate = true;
102 } break; 134 } break;
103 135
104 default: 136 default:
105 break; 137 break;
106 } 138 }
107 139
108 if (maybe_needs_animate && refresh_effect_.IsActive()) 140 if (maybe_needs_animate && refresh_effect_->IsActive())
109 SetNeedsAnimate(); 141 SetNeedsAnimate();
110 142
111 return handled; 143 return handled;
112 } 144 }
113 145
114 void OverscrollControllerAndroid::OnGestureEventAck( 146 void OverscrollControllerAndroid::OnGestureEventAck(
115 const blink::WebGestureEvent& event, 147 const blink::WebGestureEvent& event,
116 InputEventAckState ack_result) { 148 InputEventAckState ack_result) {
117 if (!enabled_) 149 if (!enabled_)
118 return; 150 return;
119 151
120 // 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
121 // sent from the renderer compositor. 153 // sent from the renderer compositor.
122 if (event.type == blink::WebInputEvent::GestureScrollEnd || 154 if (event.type == blink::WebInputEvent::GestureScrollEnd ||
123 event.type == blink::WebInputEvent::GestureFlingStart) { 155 event.type == blink::WebInputEvent::GestureFlingStart) {
124 OnOverscrolled(DidOverscrollParams()); 156 OnOverscrolled(DidOverscrollParams());
125 } 157 }
126 158
127 if (event.type == blink::WebInputEvent::GestureScrollUpdate) { 159 if (event.type == blink::WebInputEvent::GestureScrollUpdate &&
160 refresh_effect_) {
128 // 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
129 // unconsumed and the generated scroll events go unconsumed. 162 // unconsumed and the generated scroll events go unconsumed.
130 // TODO(jdduke): Prevent activation if the first touchmove was consumed, 163 // TODO(jdduke): Prevent activation if the first touchmove was consumed,
131 // i.e., the first GSU was prevented. 164 // i.e., the first GSU was prevented.
132 bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED; 165 bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
133 refresh_effect_.OnScrollUpdateAck(consumed); 166 refresh_effect_->OnScrollUpdateAck(consumed);
134 } 167 }
135 } 168 }
136 169
137 void OverscrollControllerAndroid::OnOverscrolled( 170 void OverscrollControllerAndroid::OnOverscrolled(
138 const DidOverscrollParams& params) { 171 const DidOverscrollParams& params) {
139 if (!enabled_) 172 if (!enabled_)
140 return; 173 return;
141 174
142 if (refresh_effect_.IsActive() || 175 if (refresh_effect_ &&
143 refresh_effect_.IsAwaitingScrollUpdateAck()) { 176 (refresh_effect_->IsActive() ||
177 refresh_effect_->IsAwaitingScrollUpdateAck())) {
144 // An active (or potentially active) refresh effect should always pre-empt 178 // An active (or potentially active) refresh effect should always pre-empt
145 // the passive glow effect. 179 // the passive glow effect.
146 return; 180 return;
147 } 181 }
148 182
149 if (glow_effect_.OnOverscrolled( 183 if (glow_effect_ &&
184 glow_effect_->OnOverscrolled(
150 base::TimeTicks::Now(), 185 base::TimeTicks::Now(),
151 gfx::ScaleVector2d(params.accumulated_overscroll, dpi_scale_), 186 gfx::ScaleVector2d(params.accumulated_overscroll, dpi_scale_),
152 gfx::ScaleVector2d(params.latest_overscroll_delta, dpi_scale_), 187 gfx::ScaleVector2d(params.latest_overscroll_delta, dpi_scale_),
153 gfx::ScaleVector2d(params.current_fling_velocity, dpi_scale_), 188 gfx::ScaleVector2d(params.current_fling_velocity, dpi_scale_),
154 gfx::ScaleVector2d(params.causal_event_viewport_point.OffsetFromOrigin(), 189 gfx::ScaleVector2d(params.causal_event_viewport_point.OffsetFromOrigin(),
155 dpi_scale_))) { 190 dpi_scale_))) {
156 SetNeedsAnimate(); 191 SetNeedsAnimate();
157 } 192 }
158 } 193 }
159 194
160 bool OverscrollControllerAndroid::Animate(base::TimeTicks current_time, 195 bool OverscrollControllerAndroid::Animate(base::TimeTicks current_time,
161 cc::Layer* parent_layer) { 196 cc::Layer* parent_layer) {
162 DCHECK(parent_layer); 197 DCHECK(parent_layer);
163 if (!enabled_) 198 if (!enabled_)
164 return false; 199 return false;
165 200
166 bool needs_animate = refresh_effect_.Animate(current_time, parent_layer); 201 bool needs_animate = false;
167 needs_animate |= glow_effect_.Animate(current_time, parent_layer); 202 if (refresh_effect_)
203 needs_animate |= refresh_effect_->Animate(current_time, parent_layer);
204 if (glow_effect_)
205 needs_animate |= glow_effect_->Animate(current_time, parent_layer);
168 return needs_animate; 206 return needs_animate;
169 } 207 }
170 208
171 void OverscrollControllerAndroid::OnFrameMetadataUpdated( 209 void OverscrollControllerAndroid::OnFrameMetadataUpdated(
172 const cc::CompositorFrameMetadata& frame_metadata) { 210 const cc::CompositorFrameMetadata& frame_metadata) {
211 if (!refresh_effect_ && !glow_effect_)
212 return;
213
173 const float scale_factor = 214 const float scale_factor =
174 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor; 215 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor;
175 gfx::SizeF viewport_size = 216 gfx::SizeF viewport_size =
176 gfx::ScaleSize(frame_metadata.scrollable_viewport_size, scale_factor); 217 gfx::ScaleSize(frame_metadata.scrollable_viewport_size, scale_factor);
177 gfx::SizeF content_size = 218 gfx::SizeF content_size =
178 gfx::ScaleSize(frame_metadata.root_layer_size, scale_factor); 219 gfx::ScaleSize(frame_metadata.root_layer_size, scale_factor);
179 gfx::Vector2dF content_scroll_offset = 220 gfx::Vector2dF content_scroll_offset =
180 gfx::ScaleVector2d(frame_metadata.root_scroll_offset, scale_factor); 221 gfx::ScaleVector2d(frame_metadata.root_scroll_offset, scale_factor);
181 222
182 refresh_effect_.UpdateDisplay(viewport_size, content_scroll_offset); 223 if (refresh_effect_)
183 glow_effect_.UpdateDisplay(viewport_size, content_size, 224 refresh_effect_->UpdateDisplay(viewport_size, content_scroll_offset);
184 content_scroll_offset); 225
226 if (glow_effect_) {
227 glow_effect_->UpdateDisplay(viewport_size, content_size,
228 content_scroll_offset);
229 }
185 } 230 }
186 231
187 void OverscrollControllerAndroid::Enable() { 232 void OverscrollControllerAndroid::Enable() {
188 enabled_ = true; 233 enabled_ = glow_effect_ || refresh_effect_;
aelias_OOO_until_Jul13 2014/11/19 06:21:51 As mentioned above, I'd prefer this to just be "en
jdduke (slow) 2014/11/19 16:56:22 Done.
189 } 234 }
190 235
191 void OverscrollControllerAndroid::Disable() { 236 void OverscrollControllerAndroid::Disable() {
192 if (!enabled_) 237 if (!enabled_)
193 return; 238 return;
194 enabled_ = false; 239 enabled_ = false;
195 if (!enabled_) { 240 if (!enabled_) {
196 refresh_effect_.Reset(); 241 if (refresh_effect_)
197 glow_effect_.Reset(); 242 refresh_effect_->Reset();
243 if (glow_effect_)
244 glow_effect_->Reset();
198 } 245 }
199 } 246 }
200 247
201 void OverscrollControllerAndroid::DidNavigateMainFrame( 248 void OverscrollControllerAndroid::DidNavigateMainFrame(
202 const LoadCommittedDetails& details, 249 const LoadCommittedDetails& details,
203 const FrameNavigateParams& params) { 250 const FrameNavigateParams& params) {
204 // Once the main frame has navigated, there's little need to further animate 251 // Once the main frame has navigated, there's little need to further animate
205 // the reload effect. Note that the effect will naturally time out should the 252 // the reload effect. Note that the effect will naturally time out should the
206 // reload be interruped for any reason. 253 // reload be interruped for any reason.
207 triggered_refresh_active_ = false; 254 triggered_refresh_active_ = false;
(...skipping 10 matching lines...) Expand all
218 265
219 bool OverscrollControllerAndroid::IsStillRefreshing() const { 266 bool OverscrollControllerAndroid::IsStillRefreshing() const {
220 return triggered_refresh_active_; 267 return triggered_refresh_active_;
221 } 268 }
222 269
223 void OverscrollControllerAndroid::SetNeedsAnimate() { 270 void OverscrollControllerAndroid::SetNeedsAnimate() {
224 compositor_->SetNeedsAnimate(); 271 compositor_->SetNeedsAnimate();
225 } 272 }
226 273
227 } // namespace content 274 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698