Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e34fe69e authored by Adam Powell's avatar Adam Powell Committed by Android (Google) Code Review
Browse files

Merge "DO NOT MERGE Integrate edge effects into WebView." into gingerbread

parents 6c33904a 230269d4
Loading
Loading
Loading
Loading
+201 −27
Original line number Diff line number Diff line
@@ -16,13 +16,16 @@

package android.webkit;

import com.android.internal.R;

import android.annotation.Widget;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -30,7 +33,6 @@ import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Interpolator;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.Point;
@@ -39,8 +41,8 @@ import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.net.http.SslCertificate;
import android.net.Uri;
import android.net.http.SslCertificate;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -74,8 +76,10 @@ import android.webkit.WebViewCore.TouchEventData;
import android.widget.AbsoluteLayout;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.EdgeGlow;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListView;
@@ -83,17 +87,15 @@ import android.widget.OverScroller;
import android.widget.Toast;
import android.widget.ZoomButtonsController;
import android.widget.ZoomControls;
import android.widget.AdapterView.OnItemClickListener;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@@ -757,6 +759,27 @@ public class WebView extends AbsoluteLayout
    private int mHorizontalScrollBarMode = SCROLLBAR_AUTO;
    private int mVerticalScrollBarMode = SCROLLBAR_AUTO;

    /**
     * Max distance to overscroll by in pixels.
     * This how far content can be pulled beyond its normal bounds by the user.
     */
    private int mOverscrollDistance;

    /**
     * Max distance to overfling by in pixels.
     * This is how far flinged content can move beyond the end of its normal bounds.
     */
    private int mOverflingDistance;

    /*
     * These manage the edge glow effect when flung or pulled beyond the edges.
     * If one is not null, all are not null. Checking one for null is as good as checking each.
     */
    private EdgeGlow mEdgeGlowTop;
    private EdgeGlow mEdgeGlowBottom;
    private EdgeGlow mEdgeGlowLeft;
    private EdgeGlow mEdgeGlowRight;

    // Used to match key downs and key ups
    private boolean mGotKeyDown;

@@ -986,7 +1009,6 @@ public class WebView extends AbsoluteLayout
        setFocusableInTouchMode(true);
        setClickable(true);
        setLongClickable(true);
        setOverscrollMode(OVERSCROLL_NEVER);

        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
        int slop = configuration.getScaledTouchSlop();
@@ -1009,6 +1031,29 @@ public class WebView extends AbsoluteLayout
        mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
        mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
        mMaximumFling = configuration.getScaledMaximumFlingVelocity();
        mOverscrollDistance = configuration.getScaledOverscrollDistance();
        mOverflingDistance = configuration.getScaledOverflingDistance();
    }

    @Override
    public void setOverscrollMode(int mode) {
        super.setOverscrollMode(mode);
        if (mode != OVERSCROLL_NEVER) {
            if (mEdgeGlowTop == null) {
                final Resources res = getContext().getResources();
                final Drawable edge = res.getDrawable(R.drawable.edge_light);
                final Drawable glow = res.getDrawable(R.drawable.overscroll_glow);
                mEdgeGlowTop = new EdgeGlow(edge, glow);
                mEdgeGlowBottom = new EdgeGlow(edge, glow);
                mEdgeGlowLeft = new EdgeGlow(edge, glow);
                mEdgeGlowRight = new EdgeGlow(edge, glow);
            }
        } else {
            mEdgeGlowTop = null;
            mEdgeGlowBottom = null;
            mEdgeGlowLeft = null;
            mEdgeGlowRight = null;
        }
    }

    /* package */void updateDefaultZoomDensity(int zoomDensity) {
@@ -2500,6 +2545,9 @@ public class WebView extends AbsoluteLayout
    protected void onDrawVerticalScrollBar(Canvas canvas,
                                           Drawable scrollBar,
                                           int l, int t, int r, int b) {
        if (mScrollY < 0) {
            t -= mScrollY;
        }
        scrollBar.setBounds(l, t + getVisibleTitleHeight(), r, b);
        scrollBar.draw(canvas);
    }
@@ -2518,6 +2566,12 @@ public class WebView extends AbsoluteLayout
        if (scrollY < 0 || scrollY > computeMaxScrollY()) {
            mInOverScrollMode = true;
        }

        if ((clampedX && maxX > 0) || clampedY) {
            // Hitting a scroll barrier breaks velocity; don't fling further.
            mVelocityTracker.clear();
            mLastVelocity = 0;
        }
        super.scrollTo(scrollX, scrollY);
    }

@@ -2876,12 +2930,35 @@ public class WebView extends AbsoluteLayout
            int oldY = mScrollY;
            int x = mScroller.getCurrX();
            int y = mScroller.getCurrY();
            postInvalidate();  // So we draw again
            invalidate();  // So we draw again

            if (oldX != x || oldY != y) {
                final int rangeX = computeMaxScrollX();
                final int rangeY = computeMaxScrollY();
                overscrollBy(x - oldX, y - oldY, oldX, oldY,
                        computeMaxScrollX(), computeMaxScrollY(),
                        getViewWidth() / 3, getViewHeight() / 3, false);
                        rangeX, rangeY,
                        mOverflingDistance, mOverflingDistance, false);

                if (mEdgeGlowTop != null) {
                    if (rangeY > 0 || getOverscrollMode() == OVERSCROLL_ALWAYS) {
                        if (y < 0 && oldY >= 0) {
                            mEdgeGlowTop.onAbsorb((int) mScroller.getCurrVelocity());
                        } else if (y > rangeY && oldY <= rangeY) {
                            mEdgeGlowBottom.onAbsorb((int) mScroller.getCurrVelocity());
                        }
                    }

                    if (rangeX > 0) {
                        if (x < 0 && oldX >= 0) {
                            mEdgeGlowLeft.onAbsorb((int) mScroller.getCurrVelocity());
                        } else if (x > rangeX && oldX <= rangeX) {
                            mEdgeGlowRight.onAbsorb((int) mScroller.getCurrVelocity());
                        }
                    }
                }
            }
            if (mScroller.isFinished()) {
                mPrivateHandler.sendEmptyMessage(RESUME_WEBCORE_PRIORITY);
            }
        } else {
            super.computeScroll();
@@ -3292,13 +3369,8 @@ public class WebView extends AbsoluteLayout
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        if (child == mTitleBar) {
            // When drawing the title bar, move it horizontally to always show
            // at the top of the WebView. While overscroll, stick the title bar
            // on the top otherwise we may have two during loading, one is drawn
            // here, another is drawn by the Browser.
            // at the top of the WebView.
            mTitleBar.offsetLeftAndRight(mScrollX - mTitleBar.getLeft());
            if (mScrollY <= 0) {
                mTitleBar.offsetTopAndBottom(mScrollY - mTitleBar.getTop());
            }
        }
        return super.drawChild(canvas, child, drawingTime);
    }
@@ -3349,7 +3421,7 @@ public class WebView extends AbsoluteLayout
                mOverScrollBorder.setColor(0xffbbbbbb);
            }

            int top = getTitleHeight();
            int top = 0;
            int right = computeRealHorizontalScrollRange();
            int bottom = top + computeRealVerticalScrollRange();
            // first draw the background and anchor to the top of the view
@@ -3389,12 +3461,72 @@ public class WebView extends AbsoluteLayout
                    mScrollY + height);
            mTitleShadow.draw(canvas);
        }

        if (AUTO_REDRAW_HACK && mAutoRedraw) {
            invalidate();
        }
        mWebViewCore.signalRepaintDone();
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (mEdgeGlowTop != null && drawEdgeGlows(canvas)) {
            invalidate();
        }
    }

    /**
     * Draw the glow effect along the sides of the widget. mEdgeGlow* must be non-null.
     *
     * @param canvas Canvas to draw into, transformed into view coordinates.
     * @return true if glow effects are still animating and the view should invalidate again.
     */
    private boolean drawEdgeGlows(Canvas canvas) {
        final int scrollX = mScrollX;
        final int scrollY = mScrollY;
        final int width = getWidth();
        int height = getHeight();

        boolean invalidateForGlow = false;
        if (!mEdgeGlowTop.isFinished()) {
            final int restoreCount = canvas.save();

            canvas.translate(-width / 2 + scrollX, scrollY);
            mEdgeGlowTop.setSize(width * 2, height);
            invalidateForGlow |= mEdgeGlowTop.draw(canvas);
            canvas.restoreToCount(restoreCount);
        }
        if (!mEdgeGlowBottom.isFinished()) {
            final int restoreCount = canvas.save();

            canvas.translate(-width / 2 - scrollX, scrollY + height);
            canvas.rotate(180, width, 0);
            mEdgeGlowBottom.setSize(width * 2, height);
            invalidateForGlow |= mEdgeGlowBottom.draw(canvas);
            canvas.restoreToCount(restoreCount);
        }
        if (!mEdgeGlowLeft.isFinished()) {
            final int restoreCount = canvas.save();

            canvas.rotate(270);
            canvas.translate(-height * 1.5f - scrollY, scrollX);
            mEdgeGlowLeft.setSize(height * 2, width);
            invalidateForGlow |= mEdgeGlowLeft.draw(canvas);
            canvas.restoreToCount(restoreCount);
        }
        if (!mEdgeGlowRight.isFinished()) {
            final int restoreCount = canvas.save();

            canvas.rotate(90);
            canvas.translate(-height / 2 + scrollY, -scrollX - width);
            mEdgeGlowRight.setSize(height * 2, width);
            invalidateForGlow |= mEdgeGlowRight.draw(canvas);
            canvas.restoreToCount(restoreCount);
        }
        return invalidateForGlow;
    }

    @Override
    public void setLayoutParams(ViewGroup.LayoutParams params) {
        if (params.height == LayoutParams.WRAP_CONTENT) {
@@ -5386,9 +5518,34 @@ public class WebView extends AbsoluteLayout

    private void doDrag(int deltaX, int deltaY) {
        if ((deltaX | deltaY) != 0) {
            overscrollBy(deltaX, deltaY, mScrollX, mScrollY,
                    computeMaxScrollX(), computeMaxScrollY(),
                    getViewWidth() / 3, getViewHeight() / 3, true);
            final int oldX = mScrollX;
            final int oldY = mScrollY;
            final int rangeX = computeMaxScrollX();
            final int rangeY = computeMaxScrollY();
            overscrollBy(deltaX, deltaY, oldX, oldY,
                    rangeX, rangeY,
                    mOverscrollDistance, mOverscrollDistance, true);

            if (mEdgeGlowTop != null) {
                // Don't show left/right glows if we fit the whole content.
                if (rangeX > 0) {
                    final int pulledToX = oldX + deltaX;
                    if (pulledToX < 0) {
                        mEdgeGlowLeft.onPull((float) deltaX / getWidth());
                    } else if (pulledToX > rangeX) {
                        mEdgeGlowRight.onPull((float) deltaX / getWidth());
                    }
                }

                if (rangeY > 0 || getOverscrollMode() == OVERSCROLL_ALWAYS) {
                    final int pulledToY = oldY + deltaY;
                    if (pulledToY < 0) {
                        mEdgeGlowTop.onPull((float) deltaY / getHeight());
                    } else if (pulledToY > rangeY) {
                        mEdgeGlowBottom.onPull((float) deltaY / getHeight());
                    }
                }
            }
        }
        if (!getSettings().getBuiltInZoomControls()) {
            boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
@@ -5415,6 +5572,14 @@ public class WebView extends AbsoluteLayout
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }

        // Release any pulled glows
        if (mEdgeGlowTop != null) {
            mEdgeGlowTop.onRelease();
            mEdgeGlowBottom.onRelease();
            mEdgeGlowLeft.onRelease();
            mEdgeGlowRight.onRelease();
        }
    }

    private void cancelTouch() {
@@ -5428,6 +5593,15 @@ public class WebView extends AbsoluteLayout
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }

        // Release any pulled glows
        if (mEdgeGlowTop != null) {
            mEdgeGlowTop.onRelease();
            mEdgeGlowBottom.onRelease();
            mEdgeGlowLeft.onRelease();
            mEdgeGlowRight.onRelease();
        }

        if (mTouchMode == TOUCH_DRAG_MODE) {
            WebViewCore.resumePriority();
            WebViewCore.resumeUpdatePicture(mWebViewCore);
@@ -5746,7 +5920,7 @@ public class WebView extends AbsoluteLayout

    public void flingScroll(int vx, int vy) {
        mScroller.fling(mScrollX, mScrollY, vx, vy, 0, computeMaxScrollX(), 0,
                computeMaxScrollY(), getViewWidth() / 3, getViewHeight() / 3);
                computeMaxScrollY(), mOverflingDistance, mOverflingDistance);
        invalidate();
    }

@@ -5809,13 +5983,13 @@ public class WebView extends AbsoluteLayout

        // no horizontal overscroll if the content just fits
        mScroller.fling(mScrollX, mScrollY, -vx, -vy, 0, maxX, 0, maxY,
                maxX == 0 ? 0 : getViewWidth() / 3, getViewHeight() / 3);
        // TODO: duration is calculated based on velocity, if the range is
        // small, the animation will stop before duration is up. We may
        // want to calculate how long the animation is going to run to precisely
        // resume the webcore update.
                maxX == 0 ? 0 : mOverflingDistance, mOverflingDistance);
        // Duration is calculated based on velocity. With range boundaries and overscroll
        // we may not know how long the final animation will take. (Hence the deprecation
        // warning on the call below.) It's not a big deal for scroll bars but if webcore
        // resumes during this effect we will take a performance hit. See computeScroll;
        // we resume webcore there when the animation is finished.
        final int time = mScroller.getDuration();
        mPrivateHandler.sendEmptyMessageDelayed(RESUME_WEBCORE_PRIORITY, time);
        awakenScrollBars(time);
        invalidate();
    }
+1 −1
Original line number Diff line number Diff line
@@ -213,7 +213,7 @@ public class EdgeGlow {
        final int glowHeight = mGlow.getIntrinsicHeight();

        mGlow.setAlpha((int) (Math.max(0, Math.min(mGlowAlpha, 1)) * 255));
        mGlow.setBounds(0, 0, mWidth, (int) (glowHeight * mGlowScaleY));
        mGlow.setBounds(0, 0, mWidth, (int) (glowHeight * mGlowScaleY * 0.5f));
        mGlow.draw(canvas);

        mEdge.setAlpha((int) (Math.max(0, Math.min(mEdgeAlpha, 1)) * 255));
+1 −1
Original line number Diff line number Diff line
@@ -523,7 +523,7 @@ public class OverScroller {
        // If the velocity is smaller than this value, no bounce is triggered
        // when the edge limits are reached (would result in a zero pixels
        // displacement anyway).
        private static final float MINIMUM_VELOCITY_FOR_BOUNCE = 140.0f;
        private static final float MINIMUM_VELOCITY_FOR_BOUNCE = Float.MAX_VALUE;//140.0f;

        // Proportion of the velocity that is preserved when the edge is reached.
        private static final float DEFAULT_BOUNCE_COEFFICIENT = 0.16f;