summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/ViewRootImpl.java20
-rw-r--r--core/java/android/widget/Magnifier.java61
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() {