Index: content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
index 395742f779e25da42f31947052190abb4324f6e8..bcead3e67feae3ca26786aceead4f9416a3a5b28 100644 |
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
@@ -8,6 +8,7 @@ import android.content.Context; |
import android.content.res.Configuration; |
import android.graphics.Bitmap; |
import android.graphics.Canvas; |
+import android.graphics.PointF; |
import android.os.Build; |
import android.os.Bundle; |
import android.os.ResultReceiver; |
@@ -156,6 +157,18 @@ public class ContentViewCore implements MotionEventDelegate { |
private ContentViewGestureHandler mContentViewGestureHandler; |
private ZoomManager mZoomManager; |
+ // Currently ContentView's scrolling is handled by the native side. We keep a cached copy of the |
+ // scroll offset and content size so that we can display the scrollbar correctly. In the future, |
+ // we may switch to tile rendering and handle the scrolling in the Java level. |
+ |
+ // Cached scroll offset from the native |
+ private int mNativeScrollX; |
+ private int mNativeScrollY; |
+ |
+ // Cached content size from the native |
+ private int mContentWidth; |
+ private int mContentHeight; |
+ |
// Cached page scale factor from native |
private float mNativePageScaleFactor = 1.0f; |
private float mNativeMinimumScale = 1.0f; |
@@ -376,6 +389,7 @@ public class ContentViewCore implements MotionEventDelegate { |
mZoomManager.updateMultiTouchSupport(); |
mContentViewGestureHandler = new ContentViewGestureHandler(mContext, this, mZoomManager); |
+ mNativeScrollX = mNativeScrollY = 0; |
initPopupZoomer(mContext); |
mImeAdapter = createImeAdapter(mContext); |
mKeyboardConnected = mContainerView.getResources().getConfiguration().keyboard |
@@ -549,6 +563,20 @@ public class ContentViewCore implements MotionEventDelegate { |
} |
/** |
+ * @see android.webkit.WebView#getContentHeight() |
+ */ |
+ public int getContentHeight() { |
+ return (int) (mContentHeight / mNativePageScaleFactor); |
+ } |
+ |
+ /** |
+ * @see android.webkit.WebView#getContentWidth() |
+ */ |
+ public int getContentWidth() { |
+ return (int) (mContentWidth / mNativePageScaleFactor); |
+ } |
+ |
+ /** |
* @return Whether the current WebContents has a previous navigation entry. |
*/ |
public boolean canGoBack() { |
@@ -837,6 +865,84 @@ public class ContentViewCore implements MotionEventDelegate { |
TraceEvent.end(); |
} |
+ /** |
+ * @see View#onSizeChanged(int, int, int, int) |
+ */ |
+ @SuppressWarnings("javadoc") |
+ public void onSizeChanged(int w, int h, int ow, int oh) { |
+ mPopupZoomer.hide(false); |
+ // Update the content size to make sure it is at least the View size |
+ if (mContentWidth < w) mContentWidth = w; |
+ if (mContentHeight < h) mContentHeight = h; |
+ } |
+ |
+ /** |
+ * @see View#dispatchKeyEvent(KeyEvent) |
+ */ |
+ public boolean dispatchKeyEvent(KeyEvent event) { |
+ if (mImeAdapter != null && |
+ !mImeAdapter.isNativeImeAdapterAttached() && mNativeContentViewCore != 0) { |
+ mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore)); |
+ } |
+ // The key handling logic is kind of confusing here. |
+ // The purpose of shouldOverrideKeyEvent() is to filter out some keys that is critical |
+ // to browser function but useless in renderer process (for example, the back button), |
+ // so the browser can still respond to these keys in a timely manner when the renderer |
+ // process is busy/blocked/busted. mImeAdapter.dispatchKeyEvent() forwards the key event |
+ // to the renderer process. If mImeAdapter is bypassed or is not interested to the event, |
+ // fall back to the default dispatcher to propagate the event to sub-views. |
+ return (!getContentViewClient().shouldOverrideKeyEvent(event) |
+ && mImeAdapter.dispatchKeyEvent(event)) |
+ || mContainerViewInternals.super_dispatchKeyEvent(event); |
+ } |
+ |
+ /** |
+ * @see View#scrollTo(int, int) |
+ */ |
+ public void scrollTo(int x, int y) { |
+ if (mNativeContentViewCore == 0) return; |
+ int dx = x - mNativeScrollX, dy = y - mNativeScrollY; |
+ if (dx != 0 || dy != 0) { |
+ long time = System.currentTimeMillis(); |
+ nativeScrollBegin(mNativeContentViewCore, time, mNativeScrollX, mNativeScrollY); |
+ nativeScrollBy(mNativeContentViewCore, time, mNativeScrollX, mNativeScrollY, |
+ dx, dy); |
+ nativeScrollEnd(mNativeContentViewCore, time); |
+ } |
+ } |
+ |
+ /** |
+ * @see View#computeHorizontalScrollOffset() |
+ */ |
+ @SuppressWarnings("javadoc") |
+ public int computeHorizontalScrollOffset() { |
+ return mNativeScrollX; |
+ } |
+ |
+ /** |
+ * @see View#computeHorizontalScrollRange() |
+ */ |
+ @SuppressWarnings("javadoc") |
+ public int computeHorizontalScrollRange() { |
+ return mContentWidth; |
+ } |
+ |
+ /** |
+ * @see View#computeVerticalScrollOffset() |
+ */ |
+ @SuppressWarnings("javadoc") |
+ public int computeVerticalScrollOffset() { |
+ return mNativeScrollY; |
+ } |
+ |
+ /** |
+ * @see View#computeVerticalScrollRange() |
+ */ |
+ @SuppressWarnings("javadoc") |
+ public int computeVerticalScrollRange() { |
+ return mContentHeight; |
+ } |
+ |
// End FrameLayout overrides. |
/** |
@@ -1037,6 +1143,36 @@ public class ContentViewCore implements MotionEventDelegate { |
return nativeCrashed(mNativeContentViewCore); |
} |
+ @SuppressWarnings("unused") |
+ @CalledByNative |
+ private void updateContentSize(int width, int height) { |
+ if (mContentWidth != width || mContentHeight != height) { |
+ mPopupZoomer.hide(true); |
+ } |
+ // Make sure the content size is at least the View size |
+ mContentWidth = Math.max(width, getWidth()); |
+ mContentHeight = Math.max(height, getHeight()); |
+ } |
+ |
+ @SuppressWarnings("unused") |
+ @CalledByNative |
+ private void updateScrollOffsetAndPageScaleFactor(int x, int y, float scale) { |
+ if (mNativeScrollX == x && mNativeScrollY == y && mNativePageScaleFactor == scale) return; |
+ |
+ mContainerViewInternals.onScrollChanged(x, y, mNativeScrollX, mNativeScrollY); |
+ |
+ // This function should be called back from native as soon |
+ // as the scroll is applied to the backbuffer. We should only |
+ // update mNativeScrollX/Y here for consistency. |
+ mNativeScrollX = x; |
+ mNativeScrollY = y; |
+ mNativePageScaleFactor = scale; |
+ |
+ mPopupZoomer.hide(true); |
+ |
+ mZoomManager.updateZoomControls(); |
+ } |
+ |
// The following methods are called by native through jni |
@SuppressWarnings("unused") |
@@ -1311,6 +1447,42 @@ public class ContentViewCore implements MotionEventDelegate { |
} |
/** |
+ * @See android.webkit.WebView#pageDown(boolean) |
+ */ |
+ public boolean pageDown(boolean bottom) { |
+ if (computeVerticalScrollOffset() >= mContentHeight - getHeight()) { |
+ // We seem to already be at the bottom of the page, so no scrolling will occur. |
+ return false; |
+ } |
+ |
+ if (bottom) { |
+ scrollTo(computeHorizontalScrollOffset(), mContentHeight - getHeight()); |
+ } else { |
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_PAGE_DOWN)); |
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_PAGE_DOWN)); |
+ } |
+ return true; |
+ } |
+ |
+ /** |
+ * @See android.webkit.WebView#pageUp(boolean) |
+ */ |
+ public boolean pageUp(boolean top) { |
+ if (computeVerticalScrollOffset() == 0) { |
+ // We seem to already be at the top of the page, so no scrolling will occur. |
+ return false; |
+ } |
+ |
+ if (top) { |
+ scrollTo(computeHorizontalScrollOffset(), 0); |
+ } else { |
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_PAGE_UP)); |
+ dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_PAGE_UP)); |
+ } |
+ return true; |
+ } |
+ |
+ /** |
* Callback factory method for nativeGetNavigationHistory(). |
*/ |
@CalledByNative |