| 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 |