Skip to content

Commit

Permalink
Plumb smooth scrolling in Chromium compositor
Browse files Browse the repository at this point in the history
Android WebView uses android.widget.OverScroller#startScroll
implement pageUp/pageDown. Since blink  internally knows how
to do a smooth scroll via page scale animation, WebView just
need to send an IPC to blink with the target position and
duration.

The blink change to support smooth scroll:
https://codereview.chromium.org/1251473003

BUG=378984
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel

Review URL: https://codereview.chromium.org/1251323002

Cr-Commit-Position: refs/heads/master@{#347770}
  • Loading branch information
hush authored and Commit bot committed Sep 8, 2015
1 parent fba7202 commit 18c2844
Show file tree
Hide file tree
Showing 16 changed files with 92 additions and 127 deletions.
1 change: 1 addition & 0 deletions android_webview/browser/browser_view_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient {
// Sets the scale for logical<->physical pixel conversions.
void SetDipScale(float dip_scale);
float dip_scale() const { return dip_scale_; }
float page_scale_factor() const { return page_scale_factor_; }

// Set the root layer scroll offset to |new_value|.
void ScrollTo(gfx::Vector2d new_value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ void AwRenderViewHostExt::SetJsOnlineProperty(bool network_up) {
Send(new AwViewMsg_SetJsOnlineProperty(network_up));
}

void AwRenderViewHostExt::SmoothScroll(int target_x,
int target_y,
long duration_ms) {
Send(new AwViewMsg_SmoothScroll(web_contents()->GetRoutingID(), target_x,
target_y, duration_ms));
}

void AwRenderViewHostExt::RenderViewCreated(
content::RenderViewHost* render_view_host) {
Send(new AwViewMsg_SetBackgroundColor(web_contents()->GetRoutingID(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ class AwRenderViewHostExt : public content::WebContentsObserver,
void SetBackgroundColor(SkColor c);
void SetJsOnlineProperty(bool network_up);

void SmoothScroll(int target_x, int target_y, long duration_ms);

private:
// content::WebContentsObserver implementation.
void RenderViewCreated(content::RenderViewHost* view_host) override;
Expand Down
6 changes: 6 additions & 0 deletions android_webview/common/render_view_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ IPC_MESSAGE_ROUTED1(AwViewMsg_SetBackgroundColor,
IPC_MESSAGE_CONTROL1(AwViewMsg_SetJsOnlineProperty,
bool /* network_up */)

// Tells blink to smooth scroll to the specified location within |duration_ms|.
IPC_MESSAGE_ROUTED3(AwViewMsg_SmoothScroll,
int /* target_x */,
int /* target_y */,
long /* duration_ms */);

//-----------------------------------------------------------------------------
// RenderView messages
// These are messages sent from the renderer to the browser process.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,4 @@ public void exitFullscreen() {
mAwContentsClient.onHideCustomView();
}
}

@Override
public boolean isExternalScrollActive() {
return mAwContents.isSmoothScrollingActive();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import android.view.inputmethod.InputConnection;
import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
import android.widget.OverScroller;

import org.chromium.android_webview.permission.AwGeolocationCallback;
import org.chromium.android_webview.permission.AwPermissionRequest;
Expand Down Expand Up @@ -193,8 +192,8 @@ public AwLayoutSizer createLayoutSizer() {
}

public AwScrollOffsetManager createScrollOffsetManager(
AwScrollOffsetManager.Delegate delegate, OverScroller overScroller) {
return new AwScrollOffsetManager(delegate, overScroller);
AwScrollOffsetManager.Delegate delegate) {
return new AwScrollOffsetManager(delegate);
}
}

Expand Down Expand Up @@ -571,6 +570,11 @@ public void scrollNativeTo(int x, int y) {
if (!isDestroyed()) nativeScrollTo(mNativeAwContents, x, y);
}

@Override
public void smoothScroll(int targetX, int targetY, long durationMs) {
if (!isDestroyed()) nativeSmoothScroll(mNativeAwContents, targetX, targetY, durationMs);
}

@Override
public int getContainerViewScrollX() {
return mContainerView.getScrollX();
Expand Down Expand Up @@ -610,11 +614,6 @@ public void onPinchEnded() {
mLayoutSizer.unfreezeLayoutRequests();
}

@Override
public void onFlingCancelGesture() {
mScrollOffsetManager.finishScroll();
}

@Override
public void onScrollUpdateGestureConsumed() {
mScrollAccessibilityHelper.postViewScrolledAccessibilityEventCallback();
Expand Down Expand Up @@ -719,8 +718,8 @@ public void onGestureZoomSupportChanged(
mSettings.setDefaultVideoPosterURL(
mDefaultVideoPosterRequestHandler.getDefaultVideoPosterURL());
mSettings.setDIPScale(mDIPScale);
mScrollOffsetManager = dependencyFactory.createScrollOffsetManager(
new AwScrollOffsetManagerDelegate(), new OverScroller(mContext));
mScrollOffsetManager =
dependencyFactory.createScrollOffsetManager(new AwScrollOffsetManagerDelegate());
mScrollAccessibilityHelper = new ScrollAccessibilityHelper(mContainerView);
mEnablePageVisibility = CommandLine.getInstance().hasSwitch(ENABLE_PAGE_VISIBILITY);

Expand Down Expand Up @@ -1975,13 +1974,6 @@ public float getScale() {
*/
public void flingScroll(int velocityX, int velocityY) {
if (TRACE) Log.d(TAG, "flingScroll");
// Cancel the current smooth scroll, if there is one.
mScrollOffsetManager.finishScroll();
// TODO(hush): crbug.com/493765. A hit test at 0, 0 may not
// target the scroll at root scrolling layer. Instead, we
// should add a method flingRootLayer to ContentViewCore
// and call it here to specifically target the scroll at
// the root layer.
mContentViewCore.flingViewport(SystemClock.uptimeMillis(), -velocityX, -velocityY);
}

Expand Down Expand Up @@ -2619,10 +2611,6 @@ private void scrollContainerViewTo(int x, int y) {
mScrollOffsetManager.scrollContainerViewTo(x, y);
}

public boolean isSmoothScrollingActive() {
return mScrollOffsetManager.isSmoothScrollingActive();
}

@CalledByNative
private void updateScrollState(int maxContainerViewScrollOffsetX,
int maxContainerViewScrollOffsetY, int contentWidthDip, int contentHeightDip,
Expand Down Expand Up @@ -3068,13 +3056,8 @@ public int computeVerticalScrollExtent() {

@Override
public void computeScroll() {
if (mScrollOffsetManager.isSmoothScrollingActive()) {
mScrollOffsetManager.computeScrollAndAbsorbGlow(mOverScrollGlow);
} else {
if (isDestroyed()) return;
nativeOnComputeScroll(
mNativeAwContents, AnimationUtils.currentAnimationTimeMillis());
}
if (isDestroyed()) return;
nativeOnComputeScroll(mNativeAwContents, AnimationUtils.currentAnimationTimeMillis());
}
}

Expand Down Expand Up @@ -3132,6 +3115,8 @@ private native void nativeRequestNewHitTestDataAt(long nativeAwContents, float x

private native void nativeOnSizeChanged(long nativeAwContents, int w, int h, int ow, int oh);
private native void nativeScrollTo(long nativeAwContents, int x, int y);
private native void nativeSmoothScroll(
long nativeAwContents, int targetX, int targetY, long durationMs);
private native void nativeSetViewVisibility(long nativeAwContents, boolean visible);
private native void nativeSetWindowVisibility(long nativeAwContents, boolean visible);
private native void nativeSetIsPaused(long nativeAwContents, boolean paused);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package org.chromium.android_webview;

import android.graphics.Rect;
import android.widget.OverScroller;

import org.chromium.base.VisibleForTesting;

Expand Down Expand Up @@ -42,6 +41,14 @@ void overScrollContainerViewBy(int deltaX, int deltaY, int scrollX, int scrollY,
// this call.
void scrollNativeTo(int x, int y);

/**
* Smooth scrolls the view to targetX, targetY, within durationMs.
* @param targetX x-coordinate of target scroll position.
* @param targetY y-coordinate of target scroll position.
* @param durationMs the animation duration in milliseconds.
*/
void smoothScroll(int targetX, int targetY, long durationMs);

int getContainerViewScrollX();
int getContainerViewScrollY();

Expand Down Expand Up @@ -73,11 +80,8 @@ void overScrollContainerViewBy(int deltaX, int deltaY, int scrollX, int scrollY,
private int mDeferredNativeScrollX;
private int mDeferredNativeScrollY;

private OverScroller mScroller;

public AwScrollOffsetManager(Delegate delegate, OverScroller overScroller) {
public AwScrollOffsetManager(Delegate delegate) {
mDelegate = delegate;
mScroller = overScroller;
}

//----- Scroll range and extent calculation methods -------------------------------------------
Expand Down Expand Up @@ -162,12 +166,6 @@ public void scrollContainerViewTo(int x, int y) {
scrollRangeX, scrollRangeY, mProcessingTouchEvent);
}

// This is used temporarily until animateScrollTo path of Android WebView (pageUp, pageDown)
// is unified with Chrome smooth scrolling.
public boolean isSmoothScrollingActive() {
return !mScroller.isFinished();
}

// Called by the native side to over-scroll the container view.
public void overScrollBy(int deltaX, int deltaY) {
// TODO(mkosiba): Once http://crbug.com/260663 and http://crbug.com/261239 are fixed it
Expand Down Expand Up @@ -250,37 +248,6 @@ private void scrollNativeTo(int x, int y) {
mDelegate.scrollNativeTo(x, y);
}

// Called whenever some other touch interaction requires the fling gesture to be canceled.
public void finishScroll() {
// TODO(mkosiba): Support speeding up a fling by flinging again.
// http://crbug.com/265841
mScroller.forceFinished(true);
}

// Called immediately before the draw to update the scroll offset.
public void computeScrollAndAbsorbGlow(OverScrollGlow overScrollGlow) {
assert isSmoothScrollingActive();
mScroller.computeScrollOffset();
final int oldX = mDelegate.getContainerViewScrollX();
final int oldY = mDelegate.getContainerViewScrollY();
int x = mScroller.getCurrX();
int y = mScroller.getCurrY();

final int scrollRangeX = computeMaximumHorizontalScrollOffset();
final int scrollRangeY = computeMaximumVerticalScrollOffset();

if (overScrollGlow != null) {
overScrollGlow.absorbGlow(x, y, oldX, oldY, scrollRangeX, scrollRangeY,
mScroller.getCurrVelocity());
}

// The mScroller is configured not to go outside of the scrollable range, so this call
// should never result in attempting to scroll outside of the scrollable region.
scrollBy(x - oldX, y - oldY);

mDelegate.invalidate();
}

private static int computeDurationInMilliSec(int dx, int dy) {
int distance = Math.max(Math.abs(dx), Math.abs(dy));
int duration = distance * 1000 / STD_SCROLL_ANIMATION_SPEED_PIX_PER_SEC;
Expand All @@ -299,10 +266,7 @@ private boolean animateScrollTo(int x, int y) {

if (dx == 0 && dy == 0) return false;

// The scroll will be handled by AwScrollOffsetManager instead of the compositor.
// So stop the current fling (either by flingScroll() or by user finger).
mDelegate.cancelFling();
mScroller.startScroll(scrollX, scrollY, dx, dy, computeDurationInMilliSec(dx, dy));
mDelegate.smoothScroll(scrollX + dx, scrollY + dy, computeDurationInMilliSec(dx, dy));
mDelegate.invalidate();

return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import android.os.Build;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.View;
import android.widget.OverScroller;

import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwScrollOffsetManager;
Expand Down Expand Up @@ -129,8 +128,8 @@ protected TestDependencyFactory createTestDependencyFactory() {
return new TestDependencyFactory() {
@Override
public AwScrollOffsetManager createScrollOffsetManager(
AwScrollOffsetManager.Delegate delegate, OverScroller overScroller) {
return new AwScrollOffsetManager(delegate, overScroller);
AwScrollOffsetManager.Delegate delegate) {
return new AwScrollOffsetManager(delegate);
}
@Override
public AwTestContainerView createAwTestContainerView(AwTestRunnerActivity activity,
Expand Down Expand Up @@ -732,10 +731,6 @@ public void onFlingStartGesture(
int velocityX, int velocityY, int scrollOffsetY, int scrollExtentY) {
}

@Override
public void onFlingCancelGesture() {
}

@Override
public void onScrollUpdateGestureConsumed() {
mOnScrollUpdateGestureConsumedHelper.notifyCalled();
Expand Down
Loading

0 comments on commit 18c2844

Please sign in to comment.