OLD | NEW |
---|---|
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 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
43 switches::kDisableOverscrollEdgeEffect)) { | |
44 return scoped_ptr<OverscrollGlow>(); | |
boliu
2014/11/20 23:12:48
return nullptr should work, the new c++11 hotness
jdduke (slow)
2014/11/20 23:14:54
yay!
| |
45 } | |
46 | |
47 return make_scoped_ptr(new OverscrollGlow( | |
48 base::Bind(&CreateGlowEdgeEffect, | |
49 &compositor->GetSystemUIResourceManager(), dpi_scale))); | |
50 } | |
51 | |
52 scoped_ptr<OverscrollRefresh> CreateRefreshEffect( | |
53 ui::WindowAndroidCompositor* compositor, | |
54 OverscrollRefreshClient* client) { | |
55 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
56 switches::kDisablePullToRefreshEffect)) { | |
57 return scoped_ptr<OverscrollRefresh>(); | |
boliu
2014/11/20 23:12:48
ditto
jdduke (slow)
2014/11/20 23:14:54
Done.
| |
58 } | |
59 | |
60 return make_scoped_ptr( | |
61 new OverscrollRefresh(&compositor->GetSystemUIResourceManager(), client)); | |
62 } | |
63 | |
37 } // namespace | 64 } // namespace |
38 | 65 |
39 OverscrollControllerAndroid::OverscrollControllerAndroid( | 66 OverscrollControllerAndroid::OverscrollControllerAndroid( |
40 WebContents* web_contents, | 67 WebContents* web_contents, |
41 ui::WindowAndroidCompositor* compositor, | 68 ui::WindowAndroidCompositor* compositor, |
42 float dpi_scale) | 69 float dpi_scale) |
43 : WebContentsObserver(web_contents), | 70 : compositor_(compositor), |
44 compositor_(compositor), | |
45 dpi_scale_(dpi_scale), | 71 dpi_scale_(dpi_scale), |
46 enabled_(true), | 72 enabled_(true), |
47 glow_effect_(base::Bind(&CreateGlowEdgeEffect, | 73 glow_effect_(CreateGlowEffect(compositor, dpi_scale)), |
48 &compositor->GetSystemUIResourceManager(), | 74 refresh_effect_(CreateRefreshEffect(compositor, this)), |
49 dpi_scale_)), | |
50 refresh_effect_(&compositor->GetSystemUIResourceManager(), this), | |
51 triggered_refresh_active_(false) { | 75 triggered_refresh_active_(false) { |
52 DCHECK(web_contents); | 76 DCHECK(web_contents); |
77 DCHECK(compositor); | |
78 if (refresh_effect_) | |
79 Observe(web_contents); | |
53 } | 80 } |
54 | 81 |
55 OverscrollControllerAndroid::~OverscrollControllerAndroid() { | 82 OverscrollControllerAndroid::~OverscrollControllerAndroid() { |
56 } | 83 } |
57 | 84 |
58 bool OverscrollControllerAndroid::WillHandleGestureEvent( | 85 bool OverscrollControllerAndroid::WillHandleGestureEvent( |
59 const blink::WebGestureEvent& event) { | 86 const blink::WebGestureEvent& event) { |
60 if (!enabled_) | 87 if (!enabled_) |
61 return false; | 88 return false; |
62 | 89 |
90 if (!refresh_effect_) | |
91 return false; | |
92 | |
63 bool handled = false; | 93 bool handled = false; |
64 bool maybe_needs_animate = false; | 94 bool maybe_needs_animate = false; |
65 switch (event.type) { | 95 switch (event.type) { |
66 case blink::WebInputEvent::GestureScrollBegin: | 96 case blink::WebInputEvent::GestureScrollBegin: |
67 refresh_effect_.OnScrollBegin(); | 97 refresh_effect_->OnScrollBegin(); |
68 break; | 98 break; |
69 | 99 |
70 case blink::WebInputEvent::GestureScrollUpdate: { | 100 case blink::WebInputEvent::GestureScrollUpdate: { |
71 gfx::Vector2dF scroll_delta(event.data.scrollUpdate.deltaX, | 101 gfx::Vector2dF scroll_delta(event.data.scrollUpdate.deltaX, |
72 event.data.scrollUpdate.deltaY); | 102 event.data.scrollUpdate.deltaY); |
73 scroll_delta.Scale(dpi_scale_); | 103 scroll_delta.Scale(dpi_scale_); |
74 maybe_needs_animate = true; | 104 maybe_needs_animate = true; |
75 handled = refresh_effect_.WillHandleScrollUpdate(scroll_delta); | 105 handled = refresh_effect_->WillHandleScrollUpdate(scroll_delta); |
76 } break; | 106 } break; |
77 | 107 |
78 case blink::WebInputEvent::GestureScrollEnd: | 108 case blink::WebInputEvent::GestureScrollEnd: |
79 refresh_effect_.OnScrollEnd(gfx::Vector2dF()); | 109 refresh_effect_->OnScrollEnd(gfx::Vector2dF()); |
80 maybe_needs_animate = true; | 110 maybe_needs_animate = true; |
81 break; | 111 break; |
82 | 112 |
83 case blink::WebInputEvent::GestureFlingStart: { | 113 case blink::WebInputEvent::GestureFlingStart: { |
84 gfx::Vector2dF scroll_velocity(event.data.flingStart.velocityX, | 114 gfx::Vector2dF scroll_velocity(event.data.flingStart.velocityX, |
85 event.data.flingStart.velocityY); | 115 event.data.flingStart.velocityY); |
86 scroll_velocity.Scale(dpi_scale_); | 116 scroll_velocity.Scale(dpi_scale_); |
87 refresh_effect_.OnScrollEnd(scroll_velocity); | 117 refresh_effect_->OnScrollEnd(scroll_velocity); |
88 if (refresh_effect_.IsActive()) { | 118 if (refresh_effect_->IsActive()) { |
89 // TODO(jdduke): Figure out a cleaner way of suppressing a fling. | 119 // TODO(jdduke): Figure out a cleaner way of suppressing a fling. |
90 // It's important that the any downstream code sees a scroll-ending | 120 // 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. | 121 // 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 | 122 // Thus, we cannot simply consume the fling. Changing the event type to |
93 // a GestureScrollEnd might work in practice, but could lead to | 123 // a GestureScrollEnd might work in practice, but could lead to |
94 // unexpected results. For now, simply truncate the fling velocity, but | 124 // unexpected results. For now, simply truncate the fling velocity, but |
95 // not to zero as downstream code may not expect a zero-velocity fling. | 125 // not to zero as downstream code may not expect a zero-velocity fling. |
96 blink::WebGestureEvent& modified_event = | 126 blink::WebGestureEvent& modified_event = |
97 const_cast<blink::WebGestureEvent&>(event); | 127 const_cast<blink::WebGestureEvent&>(event); |
98 modified_event.data.flingStart.velocityX = .01f; | 128 modified_event.data.flingStart.velocityX = .01f; |
99 modified_event.data.flingStart.velocityY = .01f; | 129 modified_event.data.flingStart.velocityY = .01f; |
100 } | 130 } |
101 maybe_needs_animate = true; | 131 maybe_needs_animate = true; |
102 } break; | 132 } break; |
103 | 133 |
104 default: | 134 default: |
105 break; | 135 break; |
106 } | 136 } |
107 | 137 |
108 if (maybe_needs_animate && refresh_effect_.IsActive()) | 138 if (maybe_needs_animate && refresh_effect_->IsActive()) |
109 SetNeedsAnimate(); | 139 SetNeedsAnimate(); |
110 | 140 |
111 return handled; | 141 return handled; |
112 } | 142 } |
113 | 143 |
114 void OverscrollControllerAndroid::OnGestureEventAck( | 144 void OverscrollControllerAndroid::OnGestureEventAck( |
115 const blink::WebGestureEvent& event, | 145 const blink::WebGestureEvent& event, |
116 InputEventAckState ack_result) { | 146 InputEventAckState ack_result) { |
117 if (!enabled_) | 147 if (!enabled_) |
118 return; | 148 return; |
119 | 149 |
120 // The overscroll effect requires an explicit release signal that may not be | 150 // The overscroll effect requires an explicit release signal that may not be |
121 // sent from the renderer compositor. | 151 // sent from the renderer compositor. |
122 if (event.type == blink::WebInputEvent::GestureScrollEnd || | 152 if (event.type == blink::WebInputEvent::GestureScrollEnd || |
123 event.type == blink::WebInputEvent::GestureFlingStart) { | 153 event.type == blink::WebInputEvent::GestureFlingStart) { |
124 OnOverscrolled(DidOverscrollParams()); | 154 OnOverscrolled(DidOverscrollParams()); |
125 } | 155 } |
126 | 156 |
127 if (event.type == blink::WebInputEvent::GestureScrollUpdate) { | 157 if (event.type == blink::WebInputEvent::GestureScrollUpdate && |
158 refresh_effect_) { | |
128 // The effect should only be allowed if both the causal touch events go | 159 // The effect should only be allowed if both the causal touch events go |
129 // unconsumed and the generated scroll events go unconsumed. | 160 // unconsumed and the generated scroll events go unconsumed. |
130 bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED || | 161 bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED || |
131 event.data.scrollUpdate.previousUpdateInSequencePrevented; | 162 event.data.scrollUpdate.previousUpdateInSequencePrevented; |
132 refresh_effect_.OnScrollUpdateAck(consumed); | 163 refresh_effect_->OnScrollUpdateAck(consumed); |
133 } | 164 } |
134 } | 165 } |
135 | 166 |
136 void OverscrollControllerAndroid::OnOverscrolled( | 167 void OverscrollControllerAndroid::OnOverscrolled( |
137 const DidOverscrollParams& params) { | 168 const DidOverscrollParams& params) { |
138 if (!enabled_) | 169 if (!enabled_) |
139 return; | 170 return; |
140 | 171 |
141 if (refresh_effect_.IsActive() || | 172 if (refresh_effect_ && |
142 refresh_effect_.IsAwaitingScrollUpdateAck()) { | 173 (refresh_effect_->IsActive() || |
174 refresh_effect_->IsAwaitingScrollUpdateAck())) { | |
143 // An active (or potentially active) refresh effect should always pre-empt | 175 // An active (or potentially active) refresh effect should always pre-empt |
144 // the passive glow effect. | 176 // the passive glow effect. |
145 return; | 177 return; |
146 } | 178 } |
147 | 179 |
148 if (glow_effect_.OnOverscrolled( | 180 if (glow_effect_ && |
181 glow_effect_->OnOverscrolled( | |
149 base::TimeTicks::Now(), | 182 base::TimeTicks::Now(), |
150 gfx::ScaleVector2d(params.accumulated_overscroll, dpi_scale_), | 183 gfx::ScaleVector2d(params.accumulated_overscroll, dpi_scale_), |
151 gfx::ScaleVector2d(params.latest_overscroll_delta, dpi_scale_), | 184 gfx::ScaleVector2d(params.latest_overscroll_delta, dpi_scale_), |
152 gfx::ScaleVector2d(params.current_fling_velocity, dpi_scale_), | 185 gfx::ScaleVector2d(params.current_fling_velocity, dpi_scale_), |
153 gfx::ScaleVector2d(params.causal_event_viewport_point.OffsetFromOrigin(), | 186 gfx::ScaleVector2d(params.causal_event_viewport_point.OffsetFromOrigin(), |
154 dpi_scale_))) { | 187 dpi_scale_))) { |
155 SetNeedsAnimate(); | 188 SetNeedsAnimate(); |
156 } | 189 } |
157 } | 190 } |
158 | 191 |
159 bool OverscrollControllerAndroid::Animate(base::TimeTicks current_time, | 192 bool OverscrollControllerAndroid::Animate(base::TimeTicks current_time, |
160 cc::Layer* parent_layer) { | 193 cc::Layer* parent_layer) { |
161 DCHECK(parent_layer); | 194 DCHECK(parent_layer); |
162 if (!enabled_) | 195 if (!enabled_) |
163 return false; | 196 return false; |
164 | 197 |
165 bool needs_animate = refresh_effect_.Animate(current_time, parent_layer); | 198 bool needs_animate = false; |
166 needs_animate |= glow_effect_.Animate(current_time, parent_layer); | 199 if (refresh_effect_) |
200 needs_animate |= refresh_effect_->Animate(current_time, parent_layer); | |
201 if (glow_effect_) | |
202 needs_animate |= glow_effect_->Animate(current_time, parent_layer); | |
167 return needs_animate; | 203 return needs_animate; |
168 } | 204 } |
169 | 205 |
170 void OverscrollControllerAndroid::OnFrameMetadataUpdated( | 206 void OverscrollControllerAndroid::OnFrameMetadataUpdated( |
171 const cc::CompositorFrameMetadata& frame_metadata) { | 207 const cc::CompositorFrameMetadata& frame_metadata) { |
208 if (!refresh_effect_ && !glow_effect_) | |
209 return; | |
210 | |
172 const float scale_factor = | 211 const float scale_factor = |
173 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor; | 212 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor; |
174 gfx::SizeF viewport_size = | 213 gfx::SizeF viewport_size = |
175 gfx::ScaleSize(frame_metadata.scrollable_viewport_size, scale_factor); | 214 gfx::ScaleSize(frame_metadata.scrollable_viewport_size, scale_factor); |
176 gfx::SizeF content_size = | 215 gfx::SizeF content_size = |
177 gfx::ScaleSize(frame_metadata.root_layer_size, scale_factor); | 216 gfx::ScaleSize(frame_metadata.root_layer_size, scale_factor); |
178 gfx::Vector2dF content_scroll_offset = | 217 gfx::Vector2dF content_scroll_offset = |
179 gfx::ScaleVector2d(frame_metadata.root_scroll_offset, scale_factor); | 218 gfx::ScaleVector2d(frame_metadata.root_scroll_offset, scale_factor); |
180 | 219 |
181 refresh_effect_.UpdateDisplay(viewport_size, content_scroll_offset); | 220 if (refresh_effect_) |
182 glow_effect_.UpdateDisplay(viewport_size, content_size, | 221 refresh_effect_->UpdateDisplay(viewport_size, content_scroll_offset); |
183 content_scroll_offset); | 222 |
223 if (glow_effect_) { | |
224 glow_effect_->UpdateDisplay(viewport_size, content_size, | |
225 content_scroll_offset); | |
226 } | |
184 } | 227 } |
185 | 228 |
186 void OverscrollControllerAndroid::Enable() { | 229 void OverscrollControllerAndroid::Enable() { |
187 enabled_ = true; | 230 enabled_ = true; |
188 } | 231 } |
189 | 232 |
190 void OverscrollControllerAndroid::Disable() { | 233 void OverscrollControllerAndroid::Disable() { |
191 if (!enabled_) | 234 if (!enabled_) |
192 return; | 235 return; |
193 enabled_ = false; | 236 enabled_ = false; |
194 if (!enabled_) { | 237 if (!enabled_) { |
195 refresh_effect_.Reset(); | 238 if (refresh_effect_) |
196 glow_effect_.Reset(); | 239 refresh_effect_->Reset(); |
240 if (glow_effect_) | |
241 glow_effect_->Reset(); | |
197 } | 242 } |
198 } | 243 } |
199 | 244 |
200 void OverscrollControllerAndroid::DidNavigateMainFrame( | 245 void OverscrollControllerAndroid::DidNavigateMainFrame( |
201 const LoadCommittedDetails& details, | 246 const LoadCommittedDetails& details, |
202 const FrameNavigateParams& params) { | 247 const FrameNavigateParams& params) { |
203 // Once the main frame has navigated, there's little need to further animate | 248 // Once the main frame has navigated, there's little need to further animate |
204 // the reload effect. Note that the effect will naturally time out should the | 249 // the reload effect. Note that the effect will naturally time out should the |
205 // reload be interruped for any reason. | 250 // reload be interruped for any reason. |
206 triggered_refresh_active_ = false; | 251 triggered_refresh_active_ = false; |
(...skipping 10 matching lines...) Expand all Loading... | |
217 | 262 |
218 bool OverscrollControllerAndroid::IsStillRefreshing() const { | 263 bool OverscrollControllerAndroid::IsStillRefreshing() const { |
219 return triggered_refresh_active_; | 264 return triggered_refresh_active_; |
220 } | 265 } |
221 | 266 |
222 void OverscrollControllerAndroid::SetNeedsAnimate() { | 267 void OverscrollControllerAndroid::SetNeedsAnimate() { |
223 compositor_->SetNeedsAnimate(); | 268 compositor_->SetNeedsAnimate(); |
224 } | 269 } |
225 | 270 |
226 } // namespace content | 271 } // namespace content |
OLD | NEW |