diff options
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 20 | ||||
| -rw-r--r-- | core/java/android/widget/Magnifier.java | 61 | 
2 files changed, 59 insertions, 22 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index fe3b6964047b..eebf7e3b508a 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -895,6 +895,26 @@ public final class ViewRootImpl implements ViewParent,          return mWindowAttributes.getTitle();      } +    /** +     * @return the width of the root view. Note that this will return {@code -1} until the first +     *         layout traversal, when the width is set. +     * +     * @hide +     */ +    public int getWidth() { +        return mWidth; +    } + +    /** +     * @return the height of the root view. Note that this will return {@code -1} until the first +     *         layout traversal, when the height is set. +     * +     * @hide +     */ +    public int getHeight() { +        return mHeight; +    } +      void destroyHardwareResources() {          if (mAttachInfo.mThreadedRenderer != null) {              mAttachInfo.mThreadedRenderer.destroyHardwareResources(mView); diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java index 310b1708cb13..b44f0c66bc99 100644 --- a/core/java/android/widget/Magnifier.java +++ b/core/java/android/widget/Magnifier.java @@ -18,7 +18,6 @@ package android.widget;  import android.annotation.FloatRange;  import android.annotation.NonNull; -import android.annotation.Nullable;  import android.annotation.UiThread;  import android.content.Context;  import android.graphics.Bitmap; @@ -30,9 +29,11 @@ import android.view.Gravity;  import android.view.LayoutInflater;  import android.view.PixelCopy;  import android.view.Surface; +import android.view.SurfaceHolder;  import android.view.SurfaceView;  import android.view.View;  import android.view.ViewParent; +import android.view.ViewRootImpl;  import com.android.internal.util.Preconditions; @@ -124,7 +125,8 @@ public final class Magnifier {          configureCoordinates(xPosInView, yPosInView); -        // Clamp startX value to avoid distorting the rendering of the magnifier content. +        // Clamp the startX value to avoid magnifying content which does not belong to the magnified +        // view. This will not take into account overlapping views.          // For this, we compute:          // - zeroScrollXInSurface: this is the start x of mView, where this is not masked by a          //                         potential scrolling container. For example, if mView is a @@ -214,33 +216,48 @@ public final class Magnifier {      }      private void performPixelCopy(final int startXInSurface, final int startYInSurface) { -        final Surface surface = getValidViewSurface(); -        if (surface != null) { -            mPixelCopyRequestRect.set(startXInSurface, startYInSurface, -                    startXInSurface + mBitmap.getWidth(), startYInSurface + mBitmap.getHeight()); - -            PixelCopy.request(surface, mPixelCopyRequestRect, mBitmap, -                    result -> { -                        getImageView().invalidate(); -                        mPrevStartCoordsInSurface.x = startXInSurface; -                        mPrevStartCoordsInSurface.y = startYInSurface; -                    }, -                    mPixelCopyHandler); -        } -    } - -    @Nullable -    private Surface getValidViewSurface() { +        // Get the view surface where the content will be copied from.          final Surface surface; +        final int surfaceWidth; +        final int surfaceHeight;          if (mView instanceof SurfaceView) { -            surface = ((SurfaceView) mView).getHolder().getSurface(); +            final SurfaceHolder surfaceHolder = ((SurfaceView) mView).getHolder(); +            surface = surfaceHolder.getSurface(); +            surfaceWidth = surfaceHolder.getSurfaceFrame().right; +            surfaceHeight = surfaceHolder.getSurfaceFrame().bottom;          } else if (mView.getViewRootImpl() != null) { -            surface = mView.getViewRootImpl().mSurface; +            final ViewRootImpl viewRootImpl = mView.getViewRootImpl(); +            surface = viewRootImpl.mSurface; +            surfaceWidth = viewRootImpl.getWidth(); +            surfaceHeight = viewRootImpl.getHeight();          } else {              surface = null; +            surfaceWidth = NONEXISTENT_PREVIOUS_CONFIG_VALUE; +            surfaceHeight = NONEXISTENT_PREVIOUS_CONFIG_VALUE;          } -        return (surface != null && surface.isValid()) ? surface : null; +        if (surface == null || !surface.isValid()) { +            return; +        } + +        // Clamp copy coordinates inside the surface to avoid displaying distorted content. +        final int clampedStartXInSurface = Math.max(0, +                Math.min(startXInSurface, surfaceWidth - mWindowWidth)); +        final int clampedStartYInSurface = Math.max(0, +                Math.min(startYInSurface, surfaceHeight - mWindowHeight)); + +        // Perform the pixel copy. +        mPixelCopyRequestRect.set(clampedStartXInSurface, +                clampedStartYInSurface, +                clampedStartXInSurface + mBitmap.getWidth(), +                clampedStartYInSurface + mBitmap.getHeight()); +        PixelCopy.request(surface, mPixelCopyRequestRect, mBitmap, +                result -> { +                    getImageView().invalidate(); +                    mPrevStartCoordsInSurface.x = startXInSurface; +                    mPrevStartCoordsInSurface.y = startYInSurface; +                }, +                mPixelCopyHandler);      }      private ImageView getImageView() {  |