From e72f621e389d057b0f2ed001820517f2379abedc Mon Sep 17 00:00:00 2001 From: Hyunki Kim Date: Tue, 27 Sep 2022 01:52:54 +0000 Subject: feat(magnification settings): Add Diagonal resize handles for Window magnification Test: `atest SystemUITests:com.android.systemui.accessibility.WindowMagnificationControllerTest` Bug: b/188136191 Change-Id: I270689671765f4287f91689e5acb82711bef4885 --- ...ccessibility_window_magnification_button_bg.xml | 26 ++++ .../ic_magnification_corner_bottom_left.xml | 33 +++++ .../ic_magnification_corner_bottom_right.xml | 33 +++++ .../drawable/ic_magnification_corner_top_left.xml | 33 +++++ .../drawable/ic_magnification_corner_top_right.xml | 33 +++++ .../SystemUI/res/layout/window_magnifier_view.xml | 61 ++++++++- packages/SystemUI/res/values/colors.xml | 4 + packages/SystemUI/res/values/strings.xml | 2 + .../WindowMagnificationController.java | 143 ++++++++++++++------- .../accessibility/WindowMagnificationSettings.java | 2 +- .../WindowMagnificationControllerTest.java | 91 +++++++++++++ 11 files changed, 413 insertions(+), 48 deletions(-) create mode 100644 packages/SystemUI/res/drawable/accessibility_window_magnification_button_bg.xml create mode 100644 packages/SystemUI/res/drawable/ic_magnification_corner_bottom_left.xml create mode 100644 packages/SystemUI/res/drawable/ic_magnification_corner_bottom_right.xml create mode 100644 packages/SystemUI/res/drawable/ic_magnification_corner_top_left.xml create mode 100644 packages/SystemUI/res/drawable/ic_magnification_corner_top_right.xml diff --git a/packages/SystemUI/res/drawable/accessibility_window_magnification_button_bg.xml b/packages/SystemUI/res/drawable/accessibility_window_magnification_button_bg.xml new file mode 100644 index 000000000000..eefe36459f9c --- /dev/null +++ b/packages/SystemUI/res/drawable/accessibility_window_magnification_button_bg.xml @@ -0,0 +1,26 @@ + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_magnification_corner_bottom_left.xml b/packages/SystemUI/res/drawable/ic_magnification_corner_bottom_left.xml new file mode 100644 index 000000000000..d25cd6558116 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_magnification_corner_bottom_left.xml @@ -0,0 +1,33 @@ + + + + + diff --git a/packages/SystemUI/res/drawable/ic_magnification_corner_bottom_right.xml b/packages/SystemUI/res/drawable/ic_magnification_corner_bottom_right.xml new file mode 100644 index 000000000000..bb6df3ac1b32 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_magnification_corner_bottom_right.xml @@ -0,0 +1,33 @@ + + + + + diff --git a/packages/SystemUI/res/drawable/ic_magnification_corner_top_left.xml b/packages/SystemUI/res/drawable/ic_magnification_corner_top_left.xml new file mode 100644 index 000000000000..8f259309b747 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_magnification_corner_top_left.xml @@ -0,0 +1,33 @@ + + + + + diff --git a/packages/SystemUI/res/drawable/ic_magnification_corner_top_right.xml b/packages/SystemUI/res/drawable/ic_magnification_corner_top_right.xml new file mode 100644 index 000000000000..291db44ba8ba --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_magnification_corner_top_right.xml @@ -0,0 +1,33 @@ + + + + + diff --git a/packages/SystemUI/res/layout/window_magnifier_view.xml b/packages/SystemUI/res/layout/window_magnifier_view.xml index 0bff47ccf722..0be732855dee 100644 --- a/packages/SystemUI/res/layout/window_magnifier_view.xml +++ b/packages/SystemUI/res/layout/window_magnifier_view.xml @@ -40,19 +40,22 @@ android:id="@+id/top_handle" android:layout_width="match_parent" android:layout_height="@dimen/magnification_border_drag_size" - android:layout_alignParentTop="true"/> + android:layout_alignParentTop="true" + android:accessibilityTraversalAfter="@id/left_handle"/> + android:layout_alignParentEnd="true" + android:accessibilityTraversalAfter="@id/top_handle"/> + android:layout_alignParentBottom="true" + android:accessibilityTraversalAfter="@id/right_handle"/> + + + + + + + + #FCFCFC #E0E0E0 #252525 + #0680FD + #FAFAFA + #252525 + #0680FD @android:color/transparent diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 9324e8f3babb..8c1ffb2920ab 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2118,6 +2118,8 @@ Magnify part of screen Switch + + Drag corner to resize Allow diagonal scrolling diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index e3c04a379fe4..25462a2bc9e9 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -158,6 +158,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private View mTopDrag; private View mRightDrag; private View mBottomDrag; + private ImageView mTopLeftCornerView; + private ImageView mTopRightCornerView; + private ImageView mBottomLeftCornerView; + private ImageView mBottomRightCornerView; private final Configuration mConfiguration; @NonNull @@ -357,13 +361,15 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return false; } - private void changeMagnificationSize(@MagnificationSize int index) { + @VisibleForTesting + void changeMagnificationSize(@MagnificationSize int index) { final int initSize = Math.min(mWindowBounds.width(), mWindowBounds.height()) / 3; int size = (int) (initSize * MAGNIFICATION_SCALE_OPTIONS[index]); setWindowSize(size, size); } - private void setEditMagnifierSizeMode(boolean enable) { + @VisibleForTesting + void setEditMagnifierSizeMode(boolean enable) { mEditSizeEnable = enable; applyResourcesValues(); @@ -641,10 +647,37 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold Region regionInsideDragBorder = new Region(mBorderDragSize, mBorderDragSize, mMirrorView.getWidth() - mBorderDragSize, mMirrorView.getHeight() - mBorderDragSize); + + Region tapExcludeRegion = new Region(); + Rect dragArea = new Rect(); mDragView.getHitRect(dragArea); - regionInsideDragBorder.op(dragArea, Region.Op.DIFFERENCE); + Rect topLeftArea = new Rect(); + mTopLeftCornerView.getHitRect(topLeftArea); + + Rect topRightArea = new Rect(); + mTopRightCornerView.getHitRect(topRightArea); + + Rect bottomLeftArea = new Rect(); + mBottomLeftCornerView.getHitRect(bottomLeftArea); + + Rect bottomRightArea = new Rect(); + mBottomRightCornerView.getHitRect(bottomRightArea); + + Rect closeArea = new Rect(); + mCloseView.getHitRect(closeArea); + + // add tapExcludeRegion for Drag or close + tapExcludeRegion.op(dragArea, Region.Op.UNION); + tapExcludeRegion.op(topLeftArea, Region.Op.UNION); + tapExcludeRegion.op(topRightArea, Region.Op.UNION); + tapExcludeRegion.op(bottomLeftArea, Region.Op.UNION); + tapExcludeRegion.op(bottomRightArea, Region.Op.UNION); + tapExcludeRegion.op(closeArea, Region.Op.UNION); + + regionInsideDragBorder.op(tapExcludeRegion, Region.Op.DIFFERENCE); + return regionInsideDragBorder; } @@ -758,6 +791,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mRightDrag = mMirrorView.findViewById(R.id.right_handle); mBottomDrag = mMirrorView.findViewById(R.id.bottom_handle); mCloseView = mMirrorView.findViewById(R.id.close_button); + mTopRightCornerView = mMirrorView.findViewById(R.id.top_right_corner); + mTopLeftCornerView = mMirrorView.findViewById(R.id.top_left_corner); + mBottomRightCornerView = mMirrorView.findViewById(R.id.bottom_right_corner); + mBottomLeftCornerView = mMirrorView.findViewById(R.id.bottom_left_corner); mDragView.setOnTouchListener(this); mLeftDrag.setOnTouchListener(this); @@ -765,6 +802,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mRightDrag.setOnTouchListener(this); mBottomDrag.setOnTouchListener(this); mCloseView.setOnTouchListener(this); + mTopLeftCornerView.setOnTouchListener(this); + mTopRightCornerView.setOnTouchListener(this); + mBottomLeftCornerView.setOnTouchListener(this); + mBottomRightCornerView.setOnTouchListener(this); } /** @@ -833,8 +874,16 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold @Override public boolean onTouch(View v, MotionEvent event) { - if (v == mDragView || v == mLeftDrag || v == mTopDrag || v == mRightDrag - || v == mBottomDrag || v == mCloseView) { + if (v == mDragView + || v == mLeftDrag + || v == mTopDrag + || v == mRightDrag + || v == mBottomDrag + || v == mTopLeftCornerView + || v == mTopRightCornerView + || v == mBottomLeftCornerView + || v == mBottomRightCornerView + || v == mCloseView) { return mGestureDetector.onTouch(v, event); } return false; @@ -1197,7 +1246,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold @Override public boolean onDrag(View view, float offsetX, float offsetY) { if (mEditSizeEnable) { - changeWindowSize(view, offsetX, offsetY); + return changeWindowSize(view, offsetX, offsetY); } else { move((int) offsetX, (int) offsetY); } @@ -1222,13 +1271,47 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold if (mEditSizeEnable) { mDragView.setVisibility(View.GONE); mCloseView.setVisibility(View.VISIBLE); + mTopRightCornerView.setVisibility(View.VISIBLE); + mTopLeftCornerView.setVisibility(View.VISIBLE); + mBottomRightCornerView.setVisibility(View.VISIBLE); + mBottomLeftCornerView.setVisibility(View.VISIBLE); } else { mDragView.setVisibility(View.VISIBLE); mCloseView.setVisibility(View.GONE); + mTopRightCornerView.setVisibility(View.GONE); + mTopLeftCornerView.setVisibility(View.GONE); + mBottomRightCornerView.setVisibility(View.GONE); + mBottomLeftCornerView.setVisibility(View.GONE); } } - public boolean changeWindowSize(View view, float offsetX, float offsetY) { + private boolean changeWindowSize(View view, float offsetX, float offsetY) { + if (view == mLeftDrag) { + changeMagnificationFrameSize(offsetX, 0, 0, 0); + } else if (view == mRightDrag) { + changeMagnificationFrameSize(0, 0, offsetX, 0); + } else if (view == mTopDrag) { + changeMagnificationFrameSize(0, offsetY, 0, 0); + } else if (view == mBottomDrag) { + changeMagnificationFrameSize(0, 0, 0, offsetY); + } else if (view == mTopLeftCornerView) { + changeMagnificationFrameSize(offsetX, offsetY, 0, 0); + } else if (view == mTopRightCornerView) { + changeMagnificationFrameSize(0, offsetY, offsetX, 0); + } else if (view == mBottomLeftCornerView) { + changeMagnificationFrameSize(offsetX, 0, 0, offsetY); + } else if (view == mBottomRightCornerView) { + changeMagnificationFrameSize(0, 0, offsetX, offsetY); + } else { + return false; + } + + return true; + } + + private void changeMagnificationFrameSize( + float leftOffset, float topOffset, float rightOffset, + float bottomOffset) { boolean bRTL = isRTL(mContext); final int initSize = Math.min(mWindowBounds.width(), mWindowBounds.height()) / 3; @@ -1238,54 +1321,26 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold Rect tempRect = new Rect(); tempRect.set(mMagnificationFrame); - if (view == mLeftDrag) { - if (bRTL) { - tempRect.right += offsetX; - if (tempRect.right > mWindowBounds.width()) { - return false; - } - } else { - tempRect.left += offsetX; - if (tempRect.left < 0) { - return false; - } - } - } else if (view == mRightDrag) { - if (bRTL) { - tempRect.left += offsetX; - if (tempRect.left < 0) { - return false; - } - } else { - tempRect.right += offsetX; - if (tempRect.right > mWindowBounds.width()) { - return false; - } - } - } else if (view == mTopDrag) { - tempRect.top += offsetY; - if (tempRect.top < 0) { - return false; - } - } else if (view == mBottomDrag) { - tempRect.bottom += offsetY; - if (tempRect.bottom > mWindowBounds.height()) { - return false; - } + if (bRTL) { + tempRect.left += (int) (rightOffset); + tempRect.right += (int) (leftOffset); + } else { + tempRect.right += (int) (rightOffset); + tempRect.left += (int) (leftOffset); } + tempRect.top += (int) (topOffset); + tempRect.bottom += (int) (bottomOffset); if (tempRect.width() < initSize || tempRect.height() < initSize || tempRect.width() > maxWidthSize || tempRect.height() > maxHeightSize) { - return false; + return; } - mMagnificationFrame.set(tempRect); computeBounceAnimationScale(); calculateMagnificationFrameBoundary(); modifyWindowMagnification(true); - return true; } private static boolean isRTL(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java index 9cffd5d609a7..069c0f656d7b 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java @@ -103,7 +103,7 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest MagnificationSize.LARGE, }) /** Denotes the Magnification size type. */ - @interface MagnificationSize { + public @interface MagnificationSize { int NONE = 0; int SMALL = 1; int MEDIUM = 2; diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 69ccc8b88bd8..57ca9c064224 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -902,6 +902,97 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { assertEquals(bounds.width(), actualWindowWidth.get()); } + @Test + public void changeMagnificationSize_expectedWindowSize() { + final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); + + final float magnificationScaleLarge = 2.5f; + final int initSize = Math.min(bounds.width(), bounds.height()) / 3; + final int magnificationSize = (int) (initSize * magnificationScaleLarge); + + final int expectedWindowHeight = magnificationSize; + final int expectedWindowWidth = magnificationSize; + + mInstrumentation.runOnMainSync( + () -> + mWindowMagnificationController.enableWindowMagnificationInternal( + Float.NaN, Float.NaN, Float.NaN)); + + final AtomicInteger actualWindowHeight = new AtomicInteger(); + final AtomicInteger actualWindowWidth = new AtomicInteger(); + mInstrumentation.runOnMainSync( + () -> { + mWindowMagnificationController.changeMagnificationSize( + WindowMagnificationSettings.MagnificationSize.LARGE); + actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height); + actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width); + }); + + assertEquals(expectedWindowHeight, actualWindowHeight.get()); + assertEquals(expectedWindowWidth, actualWindowWidth.get()); + } + + @Test + public void editModeOnDragCorner_resizesWindow() { + final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); + + final int startingSize = (int) (bounds.width() / 2); + + mInstrumentation.runOnMainSync( + () -> + mWindowMagnificationController.enableWindowMagnificationInternal( + Float.NaN, Float.NaN, Float.NaN)); + + final AtomicInteger actualWindowHeight = new AtomicInteger(); + final AtomicInteger actualWindowWidth = new AtomicInteger(); + + mInstrumentation.runOnMainSync( + () -> { + mWindowMagnificationController.setWindowSize(startingSize, startingSize); + mWindowMagnificationController.setEditMagnifierSizeMode(true); + }); + + waitForIdleSync(); + + mInstrumentation.runOnMainSync( + () -> { + mWindowMagnificationController + .onDrag(getInternalView(R.id.bottom_right_corner), 2f, 1f); + actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height); + actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width); + }); + + assertEquals(startingSize + 1, actualWindowHeight.get()); + assertEquals(startingSize + 2, actualWindowWidth.get()); + } + + @Test + public void editModeOnDragEdge_resizesWindowInOnlyOneDirection() { + final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); + + final int startingSize = (int) (bounds.width() / 2f); + + mInstrumentation.runOnMainSync( + () -> + mWindowMagnificationController.enableWindowMagnificationInternal( + Float.NaN, Float.NaN, Float.NaN)); + + final AtomicInteger actualWindowHeight = new AtomicInteger(); + final AtomicInteger actualWindowWidth = new AtomicInteger(); + + mInstrumentation.runOnMainSync( + () -> { + mWindowMagnificationController.setWindowSize(startingSize, startingSize); + mWindowMagnificationController.setEditMagnifierSizeMode(true); + mWindowMagnificationController + .onDrag(getInternalView(R.id.bottom_handle), 2f, 1f); + actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height); + actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width); + }); + assertEquals(startingSize + 1, actualWindowHeight.get()); + assertEquals(startingSize, actualWindowWidth.get()); + } + @Test public void setWindowCenterOutOfScreen_enabled_magnificationCenterIsInsideTheScreen() { -- cgit v1.2.3-59-g8ed1b