OSDN Git Service

[Magnifier-41] Fix behavior in windows with insets
authorMihai Popa <popam@google.com>
Fri, 27 Apr 2018 12:09:12 +0000 (13:09 +0100)
committerMihai Popa <popam@google.com>
Wed, 2 May 2018 10:29:19 +0000 (10:29 +0000)
The CL fixes the magnifier's behavior when its parent window has
positive insets in its surface:
- we compute the content copy coordinates sent to the pixel copy request
relative to the surface the content is copied from. We were clamping
them inside the visible region of the magnified view as returned by
belonging to the view which is magnified. However, the method returns
coordinates relative to the window. Therefore, the CL offsets the
visible rectangle with the window insets, to account for them.
Otherwise, when the insets were non-zero, on a text line we were
allowing the magnifier to display content from the left outside of the
text line, while a certain region at the end of the text line could have
never been magnified
- when clamping against the visible view region, when the surface we
copy from is a SurfaceView, #getGlobalVisibleRect is still returning
coordinates relative to the main window, whereas the coordinates we are
trying to clamp are relative to the surface of the SurfaceView. In order
to make the visible rectangle relative to the surface of the SurfaceView
instead, this CL negatively offsets the visible rectangle with the
SurfaceView position in the parent surface
- the selection/insertion handles are hidden when they overlap the
magnifier. To check this, we intersect the magnifier rectangle with the
rectangle of each handle.  However, when we were performing this check,
the magnifier rectangle was relative to the surface, whereas the
handles' rectangle was relative to the main window. The CL negatively
offsets the magnifier position with the surface insets, to make both
rectangles relative to the window.

Bug: 78621162
Test: manual testing
Test: atest CtsWidgetTestCases:android.widget.cts.MagnifierTest
Change-Id: I0d749c1abb38520fe8fc477d22d6523f470e9abc

core/java/android/view/ViewRootImpl.java
core/java/android/widget/Magnifier.java

index 4bd6fc8..239185e 100644 (file)
@@ -245,7 +245,7 @@ public final class ViewRootImpl implements ViewParent,
 
     final WindowLeaked mLocation;
 
-    final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();
+    public final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();
 
     final W mWindow;
 
index f1a1457..00632fb 100644 (file)
@@ -161,6 +161,15 @@ public final class Magnifier {
         // to the magnified view. This will not take into account overlapping views.
         final Rect viewVisibleRegion = new Rect();
         mView.getGlobalVisibleRect(viewVisibleRegion);
+        if (mView.getViewRootImpl() != null) {
+            // Clamping coordinates relative to the surface, not to the window.
+            final Rect surfaceInsets = mView.getViewRootImpl().mWindowAttributes.surfaceInsets;
+            viewVisibleRegion.offset(surfaceInsets.left, surfaceInsets.top);
+        }
+        if (mView instanceof SurfaceView) {
+            // If we copy content from a SurfaceView, clamp coordinates relative to it.
+            viewVisibleRegion.offset(-mViewCoordinatesInSurface[0], -mViewCoordinatesInSurface[1]);
+        }
         final int startX = Math.max(viewVisibleRegion.left, Math.min(
                 mCenterZoomCoords.x - mBitmapWidth / 2,
                 viewVisibleRegion.right - mBitmapWidth));
@@ -235,13 +244,17 @@ public final class Magnifier {
 
     /**
      * @hide
+     *
+     * @return The top left coordinates of the magnifier, relative to the parent window.
      */
     @Nullable
     public Point getWindowCoords() {
         if (mWindow == null) {
             return null;
         }
-        return new Point(mWindow.mLastDrawContentPositionX, mWindow.mLastDrawContentPositionY);
+        final Rect surfaceInsets = mView.getViewRootImpl().mWindowAttributes.surfaceInsets;
+        return new Point(mWindow.mLastDrawContentPositionX - surfaceInsets.left,
+                mWindow.mLastDrawContentPositionY - surfaceInsets.top);
     }
 
     @Nullable
@@ -308,8 +321,9 @@ public final class Magnifier {
         } else if (mView.getViewRootImpl() != null) {
             final ViewRootImpl viewRootImpl = mView.getViewRootImpl();
             surface = viewRootImpl.mSurface;
-            surfaceWidth = viewRootImpl.getWidth();
-            surfaceHeight = viewRootImpl.getHeight();
+            final Rect surfaceInsets = viewRootImpl.mWindowAttributes.surfaceInsets;
+            surfaceWidth = viewRootImpl.getWidth() + surfaceInsets.left + surfaceInsets.right;
+            surfaceHeight = viewRootImpl.getHeight() + surfaceInsets.top + surfaceInsets.bottom;
         } else {
             surface = null;
             surfaceWidth = NONEXISTENT_PREVIOUS_CONFIG_VALUE;