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 29246fd34748..0af12544294c 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -896,6 +896,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 30dddd0d9c24..e42217f710c4 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 @@ -221,33 +223,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() { |