Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java +9 −9 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.wm.shell.windowdecor; import static android.view.InputDevice.SOURCE_TOUCHSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY; Loading @@ -29,6 +28,8 @@ import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT; import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT; import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.isEdgeResizePermitted; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.isEventFromTouchscreen; import android.annotation.NonNull; import android.content.Context; Loading Loading @@ -392,10 +393,9 @@ class DragResizeInputListener implements AutoCloseable { boolean result = false; // Check if this is a touch event vs mouse event. // Touch events are tracked in four corners. Other events are tracked in resize edges. boolean isTouch = isTouchEvent(e); switch (e.getActionMasked()) { case MotionEvent.ACTION_DOWN: { mShouldHandleEvents = mDragResizeWindowGeometry.shouldHandleEvent(e, isTouch, mShouldHandleEvents = mDragResizeWindowGeometry.shouldHandleEvent(e, new Point() /* offset */); if (mShouldHandleEvents) { // Save the id of the pointer for this drag interaction; we will use the Loading @@ -405,7 +405,8 @@ class DragResizeInputListener implements AutoCloseable { float y = e.getY(0); float rawX = e.getRawX(0); float rawY = e.getRawY(0); int ctrlType = mDragResizeWindowGeometry.calculateCtrlType(isTouch, x, y); final int ctrlType = mDragResizeWindowGeometry.calculateCtrlType( isEventFromTouchscreen(e), isEdgeResizePermitted(e), x, y); ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: Handling action down, update ctrlType to %d", TAG, ctrlType); mDragStartTaskBounds = mCallback.onDragPositioningStart(ctrlType, Loading Loading @@ -493,8 +494,11 @@ class DragResizeInputListener implements AutoCloseable { private void updateCursorType(int displayId, int deviceId, int pointerId, float x, float y) { // Since we are handling cursor, we know that this is not a touchscreen event, and // that edge resizing should always be allowed. @DragPositioningCallback.CtrlType int ctrlType = mDragResizeWindowGeometry.calculateCtrlType(/* isTouch= */ false, x, y); mDragResizeWindowGeometry.calculateCtrlType(/* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, x, y); int cursorType = PointerIcon.TYPE_DEFAULT; switch (ctrlType) { Loading Loading @@ -536,9 +540,5 @@ class DragResizeInputListener implements AutoCloseable { private boolean shouldHandleEvent(MotionEvent e, Point offset) { return mDragResizeWindowGeometry.shouldHandleEvent(e, offset); } private boolean isTouchEvent(MotionEvent e) { return (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN; } } } libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java +24 −17 Original line number Diff line number Diff line Loading @@ -142,40 +142,42 @@ final class DragResizeWindowGeometry { * Returns if this MotionEvent should be handled, based on its source and position. */ boolean shouldHandleEvent(@NonNull MotionEvent e, @NonNull Point offset) { return shouldHandleEvent(e, isTouchEvent(e), offset); } /** * Returns if this MotionEvent should be handled, based on its source and position. */ boolean shouldHandleEvent(@NonNull MotionEvent e, boolean isTouch, @NonNull Point offset) { final float x = e.getX(0) + offset.x; final float y = e.getY(0) + offset.y; if (enableWindowingEdgeDragResize()) { // First check if touch falls within a corner. // Large corner bounds are used for course input like touch, otherwise fine bounds. boolean result = isTouch boolean result = isEventFromTouchscreen(e) ? isInCornerBounds(mLargeTaskCorners, x, y) : isInCornerBounds(mFineTaskCorners, x, y); // Check if touch falls within the edge resize handle, since edge resizing can apply // for any input source. if (!result) { // Check if touch falls within the edge resize handle. Limit edge resizing to stylus and // mouse input. if (!result && isEdgeResizePermitted(e)) { result = isInEdgeResizeBounds(x, y); } return result; } else { // Legacy uses only fine corners for touch, and edges only for non-touch input. return isTouch return isEventFromTouchscreen(e) ? isInCornerBounds(mFineTaskCorners, x, y) : isInEdgeResizeBounds(x, y); } } private boolean isTouchEvent(@NonNull MotionEvent e) { static boolean isEventFromTouchscreen(@NonNull MotionEvent e) { return (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN; } static boolean isEdgeResizePermitted(@NonNull MotionEvent e) { if (enableWindowingEdgeDragResize()) { return e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS || e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE; } else { return e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE; } } private boolean isInCornerBounds(TaskCorners corners, float xf, float yf) { return corners.calculateCornersCtrlType(xf, yf) != 0; } Loading @@ -187,24 +189,29 @@ final class DragResizeWindowGeometry { /** * Returns the control type for the drag-resize, based on the touch regions and this * MotionEvent's coordinates. * @param isTouchscreen Controls the size of the corner resize regions; touchscreen events * (finger & stylus) are eligible for a larger area than cursor events * @param isEdgeResizePermitted Indicates if the event is eligible for falling into an edge * resize region. */ @DragPositioningCallback.CtrlType int calculateCtrlType(boolean isTouch, float x, float y) { int calculateCtrlType(boolean isTouchscreen, boolean isEdgeResizePermitted, float x, float y) { if (enableWindowingEdgeDragResize()) { // First check if touch falls within a corner. // Large corner bounds are used for course input like touch, otherwise fine bounds. int ctrlType = isTouch int ctrlType = isTouchscreen ? mLargeTaskCorners.calculateCornersCtrlType(x, y) : mFineTaskCorners.calculateCornersCtrlType(x, y); // Check if touch falls within the edge resize handle, since edge resizing can apply // for any input source. if (ctrlType == CTRL_TYPE_UNDEFINED) { if (ctrlType == CTRL_TYPE_UNDEFINED && isEdgeResizePermitted) { ctrlType = calculateEdgeResizeCtrlType(x, y); } return ctrlType; } else { // Legacy uses only fine corners for touch, and edges only for non-touch input. return isTouch return isTouchscreen ? mFineTaskCorners.calculateCornersCtrlType(x, y) : calculateEdgeResizeCtrlType(x, y); } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java +108 −66 Original line number Diff line number Diff line Loading @@ -27,10 +27,9 @@ import static com.google.common.truth.Truth.assertThat; import android.annotation.NonNull; import android.graphics.Point; import android.graphics.Region; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.testing.AndroidTestingRunner; import android.util.Size; Loading Loading @@ -74,7 +73,7 @@ public class DragResizeWindowGeometryTests { TASK_SIZE.getHeight() + EDGE_RESIZE_THICKNESS / 2); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); /** * Check that both groups of objects satisfy equals/hashcode within each group, and that each Loading Loading @@ -144,10 +143,11 @@ public class DragResizeWindowGeometryTests { /** * Validate that with the flag enabled, the corner resize regions are the largest size, to * capture all eligible input regardless of source (touch or cursor). * capture all eligible input regardless of source (touchscreen or cursor). * <p>Note that capturing input does not necessarily mean that the event will be handled. */ @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testRegionUnion_edgeDragResizeEnabled_containsLargeCorners() { Region region = new Region(); GEOMETRY.union(region); Loading @@ -164,7 +164,7 @@ public class DragResizeWindowGeometryTests { * size. */ @Test @RequiresFlagsDisabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @DisableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testRegionUnion_edgeDragResizeDisabled_containsFineCorners() { Region region = new Region(); GEOMETRY.union(region); Loading @@ -176,74 +176,114 @@ public class DragResizeWindowGeometryTests { } @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testCalculateControlType_edgeDragResizeEnabled_edges() { // The input source (touch or cursor) shouldn't impact the edge resize size. validateCtrlTypeForEdges(/* isTouch= */ false); validateCtrlTypeForEdges(/* isTouch= */ true); // The input source (touchscreen or cursor) shouldn't impact the edge resize size. validateCtrlTypeForEdges(/* isTouchscreen= */ false, /* isEdgeResizePermitted= */ false); validateCtrlTypeForEdges(/* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false); validateCtrlTypeForEdges(/* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true); validateCtrlTypeForEdges(/* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true); } @Test @RequiresFlagsDisabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @DisableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testCalculateControlType_edgeDragResizeDisabled_edges() { // Edge resizing is not supported when the flag is disabled. validateCtrlTypeForEdges(/* isTouch= */ false); validateCtrlTypeForEdges(/* isTouch= */ false); // Edge resizing is not supported for touchscreen input when the flag is disabled. validateCtrlTypeForEdges(/* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true); validateCtrlTypeForEdges(/* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false); } private void validateCtrlTypeForEdges(boolean isTouch) { assertThat(GEOMETRY.calculateCtrlType(isTouch, LEFT_EDGE_POINT.x, LEFT_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_LEFT); assertThat(GEOMETRY.calculateCtrlType(isTouch, TOP_EDGE_POINT.x, TOP_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_TOP); assertThat(GEOMETRY.calculateCtrlType(isTouch, RIGHT_EDGE_POINT.x, RIGHT_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_RIGHT); assertThat(GEOMETRY.calculateCtrlType(isTouch, BOTTOM_EDGE_POINT.x, BOTTOM_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_BOTTOM); private void validateCtrlTypeForEdges(boolean isTouchscreen, boolean isEdgeResizePermitted) { assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, LEFT_EDGE_POINT.x, LEFT_EDGE_POINT.y)).isEqualTo( isEdgeResizePermitted ? CTRL_TYPE_LEFT : CTRL_TYPE_UNDEFINED); assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, TOP_EDGE_POINT.x, TOP_EDGE_POINT.y)).isEqualTo( isEdgeResizePermitted ? CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, RIGHT_EDGE_POINT.x, RIGHT_EDGE_POINT.y)).isEqualTo( isEdgeResizePermitted ? CTRL_TYPE_RIGHT : CTRL_TYPE_UNDEFINED); assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, BOTTOM_EDGE_POINT.x, BOTTOM_EDGE_POINT.y)).isEqualTo( isEdgeResizePermitted ? CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); } @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testCalculateControlType_edgeDragResizeEnabled_corners() { final TestPoints fineTestPoints = new TestPoints(TASK_SIZE, FINE_CORNER_SIZE / 2); final TestPoints largeCornerTestPoints = new TestPoints(TASK_SIZE, LARGE_CORNER_SIZE / 2); // When the flag is enabled, points within fine corners should pass regardless of touch or // not. Points outside fine corners should not pass when using a course input (non-touch). fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true, true); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false, false); // Edge resizing permitted (events from stylus/cursor) should have no impact on corners. fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, true); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false, true); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ false, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ false, false); // When the flag is enabled, points near the large corners should only pass when the point // is within the corner for large touch inputs. largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, true); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, true); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); } @Test @RequiresFlagsDisabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @DisableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testCalculateControlType_edgeDragResizeDisabled_corners() { final TestPoints fineTestPoints = new TestPoints(TASK_SIZE, FINE_CORNER_SIZE / 2); final TestPoints largeCornerTestPoints = new TestPoints(TASK_SIZE, LARGE_CORNER_SIZE / 2); // When the flag is disabled, points within fine corners should pass only when touch. fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true, false); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, false); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false, false); // When the flag is disabled, points within fine corners should pass only from touchscreen. // Edge resize permitted (indicating the event is from a cursor/stylus) should have no // impact. fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, false); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false, false); // Points within fine corners should never pass when not from touchscreen; expect edge // resizing only. fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ false, false); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ false, false); // When the flag is disabled, points near the large corners should never pass. largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); } /** Loading Loading @@ -306,19 +346,20 @@ public class DragResizeWindowGeometryTests { * {@code @DragPositioningCallback.CtrlType}. */ public void validateCtrlTypeForInnerPoints(@NonNull DragResizeWindowGeometry geometry, boolean isTouch, boolean expectedWithinGeometry) { assertThat(geometry.calculateCtrlType(isTouch, mTopLeftPoint.x, mTopLeftPoint.y)).isEqualTo( boolean isTouchscreen, boolean isEdgeResizePermitted, boolean expectedWithinGeometry) { assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mTopLeftPoint.x, mTopLeftPoint.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mTopRightPoint.x, mTopRightPoint.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mTopRightPoint.x, mTopRightPoint.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mBottomLeftPoint.x, mBottomLeftPoint.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mBottomLeftPoint.x, mBottomLeftPoint.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mBottomRightPoint.x, mBottomRightPoint.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mBottomRightPoint.x, mBottomRightPoint.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); } Loading @@ -328,19 +369,20 @@ public class DragResizeWindowGeometryTests { * {@code @DragPositioningCallback.CtrlType}. */ public void validateCtrlTypeForOutsidePoints(@NonNull DragResizeWindowGeometry geometry, boolean isTouch, boolean expectedWithinGeometry) { assertThat(geometry.calculateCtrlType(isTouch, mTopLeftPointOutside.x, mTopLeftPointOutside.y)).isEqualTo( boolean isTouchscreen, boolean isEdgeResizePermitted, boolean expectedWithinGeometry) { assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mTopLeftPointOutside.x, mTopLeftPointOutside.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mTopRightPointOutside.x, mTopRightPointOutside.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mTopRightPointOutside.x, mTopRightPointOutside.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mBottomLeftPointOutside.x, mBottomLeftPointOutside.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mBottomLeftPointOutside.x, mBottomLeftPointOutside.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mBottomRightPointOutside.x, mBottomRightPointOutside.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mBottomRightPointOutside.x, mBottomRightPointOutside.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); } Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java +9 −9 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.wm.shell.windowdecor; import static android.view.InputDevice.SOURCE_TOUCHSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY; Loading @@ -29,6 +28,8 @@ import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT; import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT; import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.isEdgeResizePermitted; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.isEventFromTouchscreen; import android.annotation.NonNull; import android.content.Context; Loading Loading @@ -392,10 +393,9 @@ class DragResizeInputListener implements AutoCloseable { boolean result = false; // Check if this is a touch event vs mouse event. // Touch events are tracked in four corners. Other events are tracked in resize edges. boolean isTouch = isTouchEvent(e); switch (e.getActionMasked()) { case MotionEvent.ACTION_DOWN: { mShouldHandleEvents = mDragResizeWindowGeometry.shouldHandleEvent(e, isTouch, mShouldHandleEvents = mDragResizeWindowGeometry.shouldHandleEvent(e, new Point() /* offset */); if (mShouldHandleEvents) { // Save the id of the pointer for this drag interaction; we will use the Loading @@ -405,7 +405,8 @@ class DragResizeInputListener implements AutoCloseable { float y = e.getY(0); float rawX = e.getRawX(0); float rawY = e.getRawY(0); int ctrlType = mDragResizeWindowGeometry.calculateCtrlType(isTouch, x, y); final int ctrlType = mDragResizeWindowGeometry.calculateCtrlType( isEventFromTouchscreen(e), isEdgeResizePermitted(e), x, y); ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: Handling action down, update ctrlType to %d", TAG, ctrlType); mDragStartTaskBounds = mCallback.onDragPositioningStart(ctrlType, Loading Loading @@ -493,8 +494,11 @@ class DragResizeInputListener implements AutoCloseable { private void updateCursorType(int displayId, int deviceId, int pointerId, float x, float y) { // Since we are handling cursor, we know that this is not a touchscreen event, and // that edge resizing should always be allowed. @DragPositioningCallback.CtrlType int ctrlType = mDragResizeWindowGeometry.calculateCtrlType(/* isTouch= */ false, x, y); mDragResizeWindowGeometry.calculateCtrlType(/* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, x, y); int cursorType = PointerIcon.TYPE_DEFAULT; switch (ctrlType) { Loading Loading @@ -536,9 +540,5 @@ class DragResizeInputListener implements AutoCloseable { private boolean shouldHandleEvent(MotionEvent e, Point offset) { return mDragResizeWindowGeometry.shouldHandleEvent(e, offset); } private boolean isTouchEvent(MotionEvent e) { return (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN; } } }
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java +24 −17 Original line number Diff line number Diff line Loading @@ -142,40 +142,42 @@ final class DragResizeWindowGeometry { * Returns if this MotionEvent should be handled, based on its source and position. */ boolean shouldHandleEvent(@NonNull MotionEvent e, @NonNull Point offset) { return shouldHandleEvent(e, isTouchEvent(e), offset); } /** * Returns if this MotionEvent should be handled, based on its source and position. */ boolean shouldHandleEvent(@NonNull MotionEvent e, boolean isTouch, @NonNull Point offset) { final float x = e.getX(0) + offset.x; final float y = e.getY(0) + offset.y; if (enableWindowingEdgeDragResize()) { // First check if touch falls within a corner. // Large corner bounds are used for course input like touch, otherwise fine bounds. boolean result = isTouch boolean result = isEventFromTouchscreen(e) ? isInCornerBounds(mLargeTaskCorners, x, y) : isInCornerBounds(mFineTaskCorners, x, y); // Check if touch falls within the edge resize handle, since edge resizing can apply // for any input source. if (!result) { // Check if touch falls within the edge resize handle. Limit edge resizing to stylus and // mouse input. if (!result && isEdgeResizePermitted(e)) { result = isInEdgeResizeBounds(x, y); } return result; } else { // Legacy uses only fine corners for touch, and edges only for non-touch input. return isTouch return isEventFromTouchscreen(e) ? isInCornerBounds(mFineTaskCorners, x, y) : isInEdgeResizeBounds(x, y); } } private boolean isTouchEvent(@NonNull MotionEvent e) { static boolean isEventFromTouchscreen(@NonNull MotionEvent e) { return (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN; } static boolean isEdgeResizePermitted(@NonNull MotionEvent e) { if (enableWindowingEdgeDragResize()) { return e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS || e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE; } else { return e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE; } } private boolean isInCornerBounds(TaskCorners corners, float xf, float yf) { return corners.calculateCornersCtrlType(xf, yf) != 0; } Loading @@ -187,24 +189,29 @@ final class DragResizeWindowGeometry { /** * Returns the control type for the drag-resize, based on the touch regions and this * MotionEvent's coordinates. * @param isTouchscreen Controls the size of the corner resize regions; touchscreen events * (finger & stylus) are eligible for a larger area than cursor events * @param isEdgeResizePermitted Indicates if the event is eligible for falling into an edge * resize region. */ @DragPositioningCallback.CtrlType int calculateCtrlType(boolean isTouch, float x, float y) { int calculateCtrlType(boolean isTouchscreen, boolean isEdgeResizePermitted, float x, float y) { if (enableWindowingEdgeDragResize()) { // First check if touch falls within a corner. // Large corner bounds are used for course input like touch, otherwise fine bounds. int ctrlType = isTouch int ctrlType = isTouchscreen ? mLargeTaskCorners.calculateCornersCtrlType(x, y) : mFineTaskCorners.calculateCornersCtrlType(x, y); // Check if touch falls within the edge resize handle, since edge resizing can apply // for any input source. if (ctrlType == CTRL_TYPE_UNDEFINED) { if (ctrlType == CTRL_TYPE_UNDEFINED && isEdgeResizePermitted) { ctrlType = calculateEdgeResizeCtrlType(x, y); } return ctrlType; } else { // Legacy uses only fine corners for touch, and edges only for non-touch input. return isTouch return isTouchscreen ? mFineTaskCorners.calculateCornersCtrlType(x, y) : calculateEdgeResizeCtrlType(x, y); } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java +108 −66 Original line number Diff line number Diff line Loading @@ -27,10 +27,9 @@ import static com.google.common.truth.Truth.assertThat; import android.annotation.NonNull; import android.graphics.Point; import android.graphics.Region; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.testing.AndroidTestingRunner; import android.util.Size; Loading Loading @@ -74,7 +73,7 @@ public class DragResizeWindowGeometryTests { TASK_SIZE.getHeight() + EDGE_RESIZE_THICKNESS / 2); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); /** * Check that both groups of objects satisfy equals/hashcode within each group, and that each Loading Loading @@ -144,10 +143,11 @@ public class DragResizeWindowGeometryTests { /** * Validate that with the flag enabled, the corner resize regions are the largest size, to * capture all eligible input regardless of source (touch or cursor). * capture all eligible input regardless of source (touchscreen or cursor). * <p>Note that capturing input does not necessarily mean that the event will be handled. */ @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testRegionUnion_edgeDragResizeEnabled_containsLargeCorners() { Region region = new Region(); GEOMETRY.union(region); Loading @@ -164,7 +164,7 @@ public class DragResizeWindowGeometryTests { * size. */ @Test @RequiresFlagsDisabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @DisableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testRegionUnion_edgeDragResizeDisabled_containsFineCorners() { Region region = new Region(); GEOMETRY.union(region); Loading @@ -176,74 +176,114 @@ public class DragResizeWindowGeometryTests { } @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testCalculateControlType_edgeDragResizeEnabled_edges() { // The input source (touch or cursor) shouldn't impact the edge resize size. validateCtrlTypeForEdges(/* isTouch= */ false); validateCtrlTypeForEdges(/* isTouch= */ true); // The input source (touchscreen or cursor) shouldn't impact the edge resize size. validateCtrlTypeForEdges(/* isTouchscreen= */ false, /* isEdgeResizePermitted= */ false); validateCtrlTypeForEdges(/* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false); validateCtrlTypeForEdges(/* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true); validateCtrlTypeForEdges(/* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true); } @Test @RequiresFlagsDisabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @DisableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testCalculateControlType_edgeDragResizeDisabled_edges() { // Edge resizing is not supported when the flag is disabled. validateCtrlTypeForEdges(/* isTouch= */ false); validateCtrlTypeForEdges(/* isTouch= */ false); // Edge resizing is not supported for touchscreen input when the flag is disabled. validateCtrlTypeForEdges(/* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true); validateCtrlTypeForEdges(/* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false); } private void validateCtrlTypeForEdges(boolean isTouch) { assertThat(GEOMETRY.calculateCtrlType(isTouch, LEFT_EDGE_POINT.x, LEFT_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_LEFT); assertThat(GEOMETRY.calculateCtrlType(isTouch, TOP_EDGE_POINT.x, TOP_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_TOP); assertThat(GEOMETRY.calculateCtrlType(isTouch, RIGHT_EDGE_POINT.x, RIGHT_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_RIGHT); assertThat(GEOMETRY.calculateCtrlType(isTouch, BOTTOM_EDGE_POINT.x, BOTTOM_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_BOTTOM); private void validateCtrlTypeForEdges(boolean isTouchscreen, boolean isEdgeResizePermitted) { assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, LEFT_EDGE_POINT.x, LEFT_EDGE_POINT.y)).isEqualTo( isEdgeResizePermitted ? CTRL_TYPE_LEFT : CTRL_TYPE_UNDEFINED); assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, TOP_EDGE_POINT.x, TOP_EDGE_POINT.y)).isEqualTo( isEdgeResizePermitted ? CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, RIGHT_EDGE_POINT.x, RIGHT_EDGE_POINT.y)).isEqualTo( isEdgeResizePermitted ? CTRL_TYPE_RIGHT : CTRL_TYPE_UNDEFINED); assertThat(GEOMETRY.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, BOTTOM_EDGE_POINT.x, BOTTOM_EDGE_POINT.y)).isEqualTo( isEdgeResizePermitted ? CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); } @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testCalculateControlType_edgeDragResizeEnabled_corners() { final TestPoints fineTestPoints = new TestPoints(TASK_SIZE, FINE_CORNER_SIZE / 2); final TestPoints largeCornerTestPoints = new TestPoints(TASK_SIZE, LARGE_CORNER_SIZE / 2); // When the flag is enabled, points within fine corners should pass regardless of touch or // not. Points outside fine corners should not pass when using a course input (non-touch). fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true, true); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false, false); // Edge resizing permitted (events from stylus/cursor) should have no impact on corners. fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, true); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false, true); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ false, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ false, false); // When the flag is enabled, points near the large corners should only pass when the point // is within the corner for large touch inputs. largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, true); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, true); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); } @Test @RequiresFlagsDisabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) @DisableFlags(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE) public void testCalculateControlType_edgeDragResizeDisabled_corners() { final TestPoints fineTestPoints = new TestPoints(TASK_SIZE, FINE_CORNER_SIZE / 2); final TestPoints largeCornerTestPoints = new TestPoints(TASK_SIZE, LARGE_CORNER_SIZE / 2); // When the flag is disabled, points within fine corners should pass only when touch. fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true, false); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, false); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false, false); // When the flag is disabled, points within fine corners should pass only from touchscreen. // Edge resize permitted (indicating the event is from a cursor/stylus) should have no // impact. fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, false); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false, true); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ false, false); // Points within fine corners should never pass when not from touchscreen; expect edge // resizing only. fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ false, false); fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ false, false); // When the flag is disabled, points near the large corners should never pass. largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ true, /* isEdgeResizePermitted= */ true, false); largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouchscreen= */ false, /* isEdgeResizePermitted= */ true, false); } /** Loading Loading @@ -306,19 +346,20 @@ public class DragResizeWindowGeometryTests { * {@code @DragPositioningCallback.CtrlType}. */ public void validateCtrlTypeForInnerPoints(@NonNull DragResizeWindowGeometry geometry, boolean isTouch, boolean expectedWithinGeometry) { assertThat(geometry.calculateCtrlType(isTouch, mTopLeftPoint.x, mTopLeftPoint.y)).isEqualTo( boolean isTouchscreen, boolean isEdgeResizePermitted, boolean expectedWithinGeometry) { assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mTopLeftPoint.x, mTopLeftPoint.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mTopRightPoint.x, mTopRightPoint.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mTopRightPoint.x, mTopRightPoint.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mBottomLeftPoint.x, mBottomLeftPoint.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mBottomLeftPoint.x, mBottomLeftPoint.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mBottomRightPoint.x, mBottomRightPoint.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mBottomRightPoint.x, mBottomRightPoint.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); } Loading @@ -328,19 +369,20 @@ public class DragResizeWindowGeometryTests { * {@code @DragPositioningCallback.CtrlType}. */ public void validateCtrlTypeForOutsidePoints(@NonNull DragResizeWindowGeometry geometry, boolean isTouch, boolean expectedWithinGeometry) { assertThat(geometry.calculateCtrlType(isTouch, mTopLeftPointOutside.x, mTopLeftPointOutside.y)).isEqualTo( boolean isTouchscreen, boolean isEdgeResizePermitted, boolean expectedWithinGeometry) { assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mTopLeftPointOutside.x, mTopLeftPointOutside.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mTopRightPointOutside.x, mTopRightPointOutside.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mTopRightPointOutside.x, mTopRightPointOutside.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mBottomLeftPointOutside.x, mBottomLeftPointOutside.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mBottomLeftPointOutside.x, mBottomLeftPointOutside.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); assertThat(geometry.calculateCtrlType(isTouch, mBottomRightPointOutside.x, mBottomRightPointOutside.y)).isEqualTo( assertThat(geometry.calculateCtrlType(isTouchscreen, isEdgeResizePermitted, mBottomRightPointOutside.x, mBottomRightPointOutside.y)).isEqualTo( expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); } Loading