OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 package org.chromium.android_webview; | 5 package org.chromium.android_webview; |
6 | 6 |
7 import android.graphics.Rect; | 7 import android.graphics.Rect; |
8 import android.widget.OverScroller; | 8 import android.widget.OverScroller; |
9 | 9 |
10 import com.google.common.annotations.VisibleForTesting; | 10 import com.google.common.annotations.VisibleForTesting; |
11 | 11 |
12 import org.chromium.base.CalledByNative; | |
13 | |
14 /** | 12 /** |
15 * Takes care of syncing the scroll offset between the Android View system and t
he | 13 * Takes care of syncing the scroll offset between the Android View system and t
he |
16 * InProcessViewRenderer. | 14 * InProcessViewRenderer. |
17 * | 15 * |
18 * Unless otherwise values (sizes, scroll offsets) are in physical pixels. | 16 * Unless otherwise values (sizes, scroll offsets) are in physical pixels. |
19 */ | 17 */ |
20 @VisibleForTesting | 18 @VisibleForTesting |
21 public class AwScrollOffsetManager { | 19 public class AwScrollOffsetManager { |
22 // Values taken from WebViewClassic. | 20 // Values taken from WebViewClassic. |
23 | 21 |
(...skipping 21 matching lines...) Expand all Loading... |
45 | 43 |
46 void invalidate(); | 44 void invalidate(); |
47 } | 45 } |
48 | 46 |
49 private final Delegate mDelegate; | 47 private final Delegate mDelegate; |
50 | 48 |
51 // Scroll offset as seen by the native side. | 49 // Scroll offset as seen by the native side. |
52 private int mNativeScrollX; | 50 private int mNativeScrollX; |
53 private int mNativeScrollY; | 51 private int mNativeScrollY; |
54 | 52 |
55 // Content size. | 53 // How many pixels can we scroll in a given direction. |
56 private int mContentWidth; | 54 private int mMaxHorizontalScrollOffset; |
57 private int mContentHeight; | 55 private int mMaxVerticalScrollOffset; |
58 | 56 |
59 // Size of the container view. | 57 // Size of the container view. |
60 private int mContainerViewWidth; | 58 private int mContainerViewWidth; |
61 private int mContainerViewHeight; | 59 private int mContainerViewHeight; |
62 | 60 |
63 // Whether we're in the middle of processing a touch event. | 61 // Whether we're in the middle of processing a touch event. |
64 private boolean mProcessingTouchEvent; | 62 private boolean mProcessingTouchEvent; |
65 | 63 |
66 // Whether (and to what value) to update the native side scroll offset after
we've finished | 64 // Whether (and to what value) to update the native side scroll offset after
we've finished |
67 // provessing a touch event. | 65 // processing a touch event. |
68 private boolean mApplyDeferredNativeScroll; | 66 private boolean mApplyDeferredNativeScroll; |
69 private int mDeferredNativeScrollX; | 67 private int mDeferredNativeScrollX; |
70 private int mDeferredNativeScrollY; | 68 private int mDeferredNativeScrollY; |
71 | 69 |
72 // Whether (and to what value) to update the container view scroll offset af
ter we've received | |
73 // a valid content size. | |
74 private boolean mApplyDeferredContainerScrollOnValidContentSize; | |
75 private int mDeferredContainerScrollX; | |
76 private int mDeferredContainerScrollY; | |
77 | |
78 // The velocity of the last recorded fling, | 70 // The velocity of the last recorded fling, |
79 private int mLastFlingVelocityX; | 71 private int mLastFlingVelocityX; |
80 private int mLastFlingVelocityY; | 72 private int mLastFlingVelocityY; |
81 | 73 |
82 private OverScroller mScroller; | 74 private OverScroller mScroller; |
83 | 75 |
84 public AwScrollOffsetManager(Delegate delegate, OverScroller overScroller) { | 76 public AwScrollOffsetManager(Delegate delegate, OverScroller overScroller) { |
85 mDelegate = delegate; | 77 mDelegate = delegate; |
86 mScroller = overScroller; | 78 mScroller = overScroller; |
87 } | 79 } |
88 | 80 |
89 //----- Scroll range and extent calculation methods ------------------------
------------------- | 81 //----- Scroll range and extent calculation methods ------------------------
------------------- |
90 | 82 |
91 public int computeHorizontalScrollRange() { | 83 public int computeHorizontalScrollRange() { |
92 return Math.max(mContainerViewWidth, mContentWidth); | 84 return mContainerViewWidth + mMaxHorizontalScrollOffset; |
93 } | 85 } |
94 | 86 |
95 public int computeMaximumHorizontalScrollOffset() { | 87 public int computeMaximumHorizontalScrollOffset() { |
96 return computeHorizontalScrollRange() - mContainerViewWidth; | 88 return mMaxHorizontalScrollOffset; |
97 } | 89 } |
98 | 90 |
99 public int computeHorizontalScrollOffset() { | 91 public int computeHorizontalScrollOffset() { |
100 return mDelegate.getContainerViewScrollX(); | 92 return mDelegate.getContainerViewScrollX(); |
101 } | 93 } |
102 | 94 |
103 public int computeVerticalScrollRange() { | 95 public int computeVerticalScrollRange() { |
104 return Math.max(mContainerViewHeight, mContentHeight); | 96 return mContainerViewHeight + mMaxVerticalScrollOffset; |
105 } | 97 } |
106 | 98 |
107 public int computeMaximumVerticalScrollOffset() { | 99 public int computeMaximumVerticalScrollOffset() { |
108 return computeVerticalScrollRange() - mContainerViewHeight; | 100 return mMaxVerticalScrollOffset; |
109 } | 101 } |
110 | 102 |
111 public int computeVerticalScrollOffset() { | 103 public int computeVerticalScrollOffset() { |
112 return mDelegate.getContainerViewScrollY(); | 104 return mDelegate.getContainerViewScrollY(); |
113 } | 105 } |
114 | 106 |
115 public int computeVerticalScrollExtent() { | 107 public int computeVerticalScrollExtent() { |
116 return mContainerViewHeight; | 108 return mContainerViewHeight; |
117 } | 109 } |
118 | 110 |
119 //--------------------------------------------------------------------------
------------------- | 111 //--------------------------------------------------------------------------
------------------- |
120 | 112 // Called when the scroll range changes. This needs to be the size of the on
-screen content. |
121 // Called when the content size changes. This needs to be the size of the on
-screen content and | 113 public void setMaxScrollOffset(int width, int height) { |
122 // therefore we can't use the WebContentsDelegate preferred size. | 114 mMaxHorizontalScrollOffset = width; |
123 public void setContentSize(int width, int height) { | 115 mMaxVerticalScrollOffset = height; |
124 mContentWidth = width; | |
125 mContentHeight = height; | |
126 | |
127 if (mApplyDeferredContainerScrollOnValidContentSize && | |
128 mContentWidth != 0 && mContentHeight != 0) { | |
129 mApplyDeferredContainerScrollOnValidContentSize = false; | |
130 scrollContainerViewTo(mDeferredContainerScrollX, mDeferredContainerS
crollY); | |
131 } | |
132 } | 116 } |
133 | 117 |
134 // Called when the physical size of the view changes. | 118 // Called when the physical size of the view changes. |
135 public void setContainerViewSize(int width, int height) { | 119 public void setContainerViewSize(int width, int height) { |
136 mContainerViewWidth = width; | 120 mContainerViewWidth = width; |
137 mContainerViewHeight = height; | 121 mContainerViewHeight = height; |
138 } | 122 } |
139 | 123 |
140 public void syncScrollOffsetFromOnDraw() { | 124 public void syncScrollOffsetFromOnDraw() { |
141 // Unfortunately apps override onScrollChanged without calling super whi
ch is why we need | 125 // Unfortunately apps override onScrollChanged without calling super whi
ch is why we need |
142 // to sync the scroll offset on every onDraw. | 126 // to sync the scroll offset on every onDraw. |
143 onContainerViewScrollChanged(mDelegate.getContainerViewScrollX(), | 127 onContainerViewScrollChanged(mDelegate.getContainerViewScrollX(), |
144 mDelegate.getContainerViewScrollY()); | 128 mDelegate.getContainerViewScrollY()); |
145 } | 129 } |
146 | 130 |
147 public void setProcessingTouchEvent(boolean processingTouchEvent) { | 131 public void setProcessingTouchEvent(boolean processingTouchEvent) { |
148 assert mProcessingTouchEvent != processingTouchEvent; | 132 assert mProcessingTouchEvent != processingTouchEvent; |
149 mProcessingTouchEvent = processingTouchEvent; | 133 mProcessingTouchEvent = processingTouchEvent; |
150 | 134 |
151 if (!mProcessingTouchEvent && mApplyDeferredNativeScroll) { | 135 if (!mProcessingTouchEvent && mApplyDeferredNativeScroll) { |
152 mApplyDeferredNativeScroll = false; | 136 mApplyDeferredNativeScroll = false; |
153 scrollNativeTo(mDeferredNativeScrollX, mDeferredNativeScrollY); | 137 scrollNativeTo(mDeferredNativeScrollX, mDeferredNativeScrollY); |
154 } | 138 } |
155 } | 139 } |
156 | 140 |
157 // Called by the native side to attempt to scroll the container view. | 141 // Called by the native side to scroll the container view. |
158 public void scrollContainerViewTo(int x, int y) { | 142 public void scrollContainerViewTo(int x, int y) { |
159 if (mContentWidth == 0 && mContentHeight == 0) { | |
160 mApplyDeferredContainerScrollOnValidContentSize = true; | |
161 mDeferredContainerScrollX = x; | |
162 mDeferredContainerScrollY = y; | |
163 return; | |
164 } | |
165 mApplyDeferredContainerScrollOnValidContentSize = false; | |
166 | |
167 mNativeScrollX = x; | 143 mNativeScrollX = x; |
168 mNativeScrollY = y; | 144 mNativeScrollY = y; |
169 | 145 |
170 final int scrollX = mDelegate.getContainerViewScrollX(); | 146 final int scrollX = mDelegate.getContainerViewScrollX(); |
171 final int scrollY = mDelegate.getContainerViewScrollY(); | 147 final int scrollY = mDelegate.getContainerViewScrollY(); |
172 final int deltaX = x - scrollX; | 148 final int deltaX = x - scrollX; |
173 final int deltaY = y - scrollY; | 149 final int deltaY = y - scrollY; |
174 final int scrollRangeX = computeMaximumHorizontalScrollOffset(); | 150 final int scrollRangeX = computeMaximumHorizontalScrollOffset(); |
175 final int scrollRangeY = computeMaximumVerticalScrollOffset(); | 151 final int scrollRangeY = computeMaximumVerticalScrollOffset(); |
176 | 152 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 if (mProcessingTouchEvent) { | 224 if (mProcessingTouchEvent) { |
249 mDeferredNativeScrollX = x; | 225 mDeferredNativeScrollX = x; |
250 mDeferredNativeScrollY = y; | 226 mDeferredNativeScrollY = y; |
251 mApplyDeferredNativeScroll = true; | 227 mApplyDeferredNativeScroll = true; |
252 return; | 228 return; |
253 } | 229 } |
254 | 230 |
255 if (x == mNativeScrollX && y == mNativeScrollY) | 231 if (x == mNativeScrollX && y == mNativeScrollY) |
256 return; | 232 return; |
257 | 233 |
258 // Updating the native scroll will override any pending scroll originall
y sent from native. | |
259 mApplyDeferredContainerScrollOnValidContentSize = false; | |
260 | |
261 // The scrollNativeTo call should be a simple store, so it's OK to assum
e it always | 234 // The scrollNativeTo call should be a simple store, so it's OK to assum
e it always |
262 // succeeds. | 235 // succeeds. |
263 mNativeScrollX = x; | 236 mNativeScrollX = x; |
264 mNativeScrollY = y; | 237 mNativeScrollY = y; |
265 | 238 |
266 mDelegate.scrollNativeTo(x, y); | 239 mDelegate.scrollNativeTo(x, y); |
267 } | 240 } |
268 | 241 |
269 // Called at the beginning of every fling gesture. | 242 // Called at the beginning of every fling gesture. |
270 public void onFlingStartGesture(int velocityX, int velocityY) { | 243 public void onFlingStartGesture(int velocityX, int velocityY) { |
(...skipping 13 matching lines...) Expand all Loading... |
284 // scroll layer. | 257 // scroll layer. |
285 public void onUnhandledFlingStartEvent() { | 258 public void onUnhandledFlingStartEvent() { |
286 flingScroll(-mLastFlingVelocityX, -mLastFlingVelocityY); | 259 flingScroll(-mLastFlingVelocityX, -mLastFlingVelocityY); |
287 } | 260 } |
288 | 261 |
289 // Starts the fling animation. Called both as a response to a fling gesture
and as via the | 262 // Starts the fling animation. Called both as a response to a fling gesture
and as via the |
290 // public WebView#flingScroll(int, int) API. | 263 // public WebView#flingScroll(int, int) API. |
291 public void flingScroll(int velocityX, int velocityY) { | 264 public void flingScroll(int velocityX, int velocityY) { |
292 final int scrollX = mDelegate.getContainerViewScrollX(); | 265 final int scrollX = mDelegate.getContainerViewScrollX(); |
293 final int scrollY = mDelegate.getContainerViewScrollY(); | 266 final int scrollY = mDelegate.getContainerViewScrollY(); |
294 final int rangeX = computeMaximumHorizontalScrollOffset(); | 267 final int scrollRangeX = computeMaximumHorizontalScrollOffset(); |
295 final int rangeY = computeMaximumVerticalScrollOffset(); | 268 final int scrollRangeY = computeMaximumVerticalScrollOffset(); |
296 | 269 |
297 mScroller.fling(scrollX, scrollY, velocityX, velocityY, | 270 mScroller.fling(scrollX, scrollY, velocityX, velocityY, |
298 0, rangeX, 0, rangeY); | 271 0, scrollRangeX, 0, scrollRangeY); |
299 mDelegate.invalidate(); | 272 mDelegate.invalidate(); |
300 } | 273 } |
301 | 274 |
302 // Called immediately before the draw to update the scroll offset. | 275 // Called immediately before the draw to update the scroll offset. |
303 public void computeScrollAndAbsorbGlow(OverScrollGlow overScrollGlow) { | 276 public void computeScrollAndAbsorbGlow(OverScrollGlow overScrollGlow) { |
304 final boolean stillAnimating = mScroller.computeScrollOffset(); | 277 final boolean stillAnimating = mScroller.computeScrollOffset(); |
305 if (!stillAnimating) return; | 278 if (!stillAnimating) return; |
306 | 279 |
307 final int oldX = mDelegate.getContainerViewScrollX(); | 280 final int oldX = mDelegate.getContainerViewScrollX(); |
308 final int oldY = mDelegate.getContainerViewScrollY(); | 281 final int oldY = mDelegate.getContainerViewScrollY(); |
309 int x = mScroller.getCurrX(); | 282 int x = mScroller.getCurrX(); |
310 int y = mScroller.getCurrY(); | 283 int y = mScroller.getCurrY(); |
311 | 284 |
312 int rangeX = computeMaximumHorizontalScrollOffset(); | 285 final int scrollRangeX = computeMaximumHorizontalScrollOffset(); |
313 int rangeY = computeMaximumVerticalScrollOffset(); | 286 final int scrollRangeY = computeMaximumVerticalScrollOffset(); |
314 | 287 |
315 if (overScrollGlow != null) { | 288 if (overScrollGlow != null) { |
316 overScrollGlow.absorbGlow(x, y, oldX, oldY, rangeX, rangeY, | 289 overScrollGlow.absorbGlow(x, y, oldX, oldY, scrollRangeX, scrollRang
eY, |
317 mScroller.getCurrVelocity()); | 290 mScroller.getCurrVelocity()); |
318 } | 291 } |
319 | 292 |
320 // The mScroller is configured not to go outside of the scrollable range
, so this call | 293 // The mScroller is configured not to go outside of the scrollable range
, so this call |
321 // should never result in attempting to scroll outside of the scrollable
region. | 294 // should never result in attempting to scroll outside of the scrollable
region. |
322 scrollBy(x - oldX, y - oldY); | 295 scrollBy(x - oldX, y - oldY); |
323 | 296 |
324 mDelegate.invalidate(); | 297 mDelegate.invalidate(); |
325 } | 298 } |
326 | 299 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 } | 416 } |
444 | 417 |
445 if (immediate) { | 418 if (immediate) { |
446 scrollBy(scrollXDelta, scrollYDelta); | 419 scrollBy(scrollXDelta, scrollYDelta); |
447 return true; | 420 return true; |
448 } else { | 421 } else { |
449 return animateScrollTo(scrollX + scrollXDelta, scrollY + scrollYDelt
a); | 422 return animateScrollTo(scrollX + scrollXDelta, scrollY + scrollYDelt
a); |
450 } | 423 } |
451 } | 424 } |
452 } | 425 } |
OLD | NEW |