Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java +25 −7 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import android.os.SystemProperties; import android.provider.DeviceConfig; import android.util.Size; import android.view.DisplayCutout; import android.view.InputDevice; import android.view.InputEvent; import android.view.MotionEvent; import android.view.ViewConfiguration; Loading Loading @@ -98,7 +99,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha @NonNull private final SizeSpecSource mSizeSpecSource; @NonNull private final PipDisplayLayoutState mPipDisplayLayoutState; private final PipUiEventLogger mPipUiEventLogger; private final PipDismissTargetHandler mPipDismissTargetHandler; private PipDismissTargetHandler mPipDismissTargetHandler; private final ShellExecutor mMainExecutor; @Nullable private final PipPerfHintController mPipPerfHintController; Loading Loading @@ -554,6 +555,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha } if ((ev.getAction() == MotionEvent.ACTION_DOWN || mTouchState.isUserInteracting()) && isDismissTargetEnabled(ev) && mPipDismissTargetHandler.maybeConsumeMotionEvent(ev)) { // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event // to the touch state. Touch state needs a DOWN event in order to later process MOVE Loading Loading @@ -787,22 +789,29 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha return mMotionHelper; } @VisibleForTesting public PipResizeGestureHandler getPipResizeGestureHandler() { @VisibleForTesting PipResizeGestureHandler getPipResizeGestureHandler() { return mPipResizeGestureHandler; } @VisibleForTesting public void setPipResizeGestureHandler(PipResizeGestureHandler pipResizeGestureHandler) { void setPipResizeGestureHandler(PipResizeGestureHandler pipResizeGestureHandler) { mPipResizeGestureHandler = pipResizeGestureHandler; } @VisibleForTesting PipDismissTargetHandler getPipDismissTargetHandler() { return mPipDismissTargetHandler; } @VisibleForTesting public void setPipMotionHelper(PipMotionHelper pipMotionHelper) { void setPipDismissTargetHandler(PipDismissTargetHandler pipDismissTargetHandler) { mPipDismissTargetHandler = pipDismissTargetHandler; } @VisibleForTesting void setPipMotionHelper(PipMotionHelper pipMotionHelper) { mMotionHelper = pipMotionHelper; } @VisibleForTesting public void setPipTouchState(PipTouchState pipTouchState) { @VisibleForTesting void setPipTouchState(PipTouchState pipTouchState) { mTouchState = pipTouchState; } Loading Loading @@ -876,8 +885,10 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha if (touchState.startedDragging()) { mSavedSnapFraction = -1f; if (isDismissTargetEnabled(touchState.getLatestMotionEvent())) { mPipDismissTargetHandler.showDismissTargetMaybe(); } } if (touchState.isDragging()) { mPipBoundsState.setHasUserMovedPip(true); Loading Loading @@ -1087,6 +1098,13 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha } } private boolean isDismissTargetEnabled(MotionEvent ev) { // Only allow dismiss target to be shown and enabled on touch screen and stylus input return !mPipDesktopState.isDraggingPipAcrossDisplaysEnabled() || ev.getSource() == InputDevice.SOURCE_TOUCHSCREEN || ev.getSource() == InputDevice.SOURCE_STYLUS; } /** * Updates the current movement bounds based on whether the menu is currently visible and * resized. Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchState.java +10 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ public class PipTouchState { private final PointF mLastTouch = new PointF(); private final PointF mLastDelta = new PointF(); private final PointF mVelocity = new PointF(); private MotionEvent mLatestMotionEvent; private boolean mAllowTouches = true; // Set to false to block both PipTouchHandler and PipResizeGestureHandler's input processing Loading Loading @@ -119,6 +120,7 @@ public class PipTouchState { initOrResetVelocityTracker(); addMovementToVelocityTracker(ev); mLatestMotionEvent = ev; mActivePointerId = ev.getPointerId(0); if (DEBUG) { ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, Loading Loading @@ -247,6 +249,13 @@ public class PipTouchState { return mLastTouch; } /** * @return the motion event of the latest touch event. */ public MotionEvent getLatestMotionEvent() { return mLatestMotionEvent; } /** * @return the movement delta between the last handled touch event and the previous touch * position. Loading Loading @@ -419,6 +428,7 @@ public class PipTouchState { pw.println(innerPrefix + "mLastTouch=" + mLastTouch); pw.println(innerPrefix + "mLastDelta=" + mLastDelta); pw.println(innerPrefix + "mVelocity=" + mVelocity); pw.println(innerPrefix + "mLatestMotionEvent=" + mLatestMotionEvent); pw.println(innerPrefix + "mIsUserInteracting=" + mIsUserInteracting); pw.println(innerPrefix + "mIsDragging=" + mIsDragging); pw.println(innerPrefix + "mStartedDragging=" + mStartedDragging); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTouchHandlerTest.kt +79 −3 Original line number Diff line number Diff line Loading @@ -20,6 +20,9 @@ import android.graphics.Rect import android.graphics.RectF import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.InputDevice.SOURCE_MOUSE import android.view.InputDevice.SOURCE_TOUCHSCREEN import android.view.MotionEvent import android.view.SurfaceControl import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito Loading Loading @@ -49,6 +52,7 @@ import org.mockito.ArgumentMatchers.anyInt import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.verify import org.mockito.kotlin.whenever Loading Loading @@ -85,6 +89,8 @@ class PipTouchHandlerTest : ShellTestCase() { private val mockDisplayLayout = mock<DisplayLayout>() private val mockTouchPosition = PointF() private val mockPipSurfaceTransactionHelper = mock<PipSurfaceTransactionHelper>() private val mockMotionEvent = mock<MotionEvent>() private val mockPipDismissTargetHandler = mock<PipDismissTargetHandler>() private lateinit var pipTouchHandler: PipTouchHandler private lateinit var pipTouchGesture: PipTouchGesture Loading @@ -108,12 +114,16 @@ class PipTouchHandlerTest : ShellTestCase() { ) pipTouchGesture = pipTouchHandler.touchGesture pipTouchHandler.setPipTouchState(pipTouchState) pipTouchHandler.setPipDismissTargetHandler(mockPipDismissTargetHandler) whenever(pipTouchState.downTouchPosition).thenReturn(mockTouchPosition) whenever(pipTouchState.velocity).thenReturn(mockTouchPosition) whenever(pipTouchState.lastTouchPosition).thenReturn(mockTouchPosition) whenever(pipTouchState.lastTouchDisplayId).thenReturn(ORIGIN_DISPLAY_ID) whenever(pipTouchState.lastTouchDelta).thenReturn(mockTouchPosition) whenever(pipTouchState.isUserInteracting).thenReturn(true) whenever(pipTouchState.allowInputEvents).thenReturn(true) whenever(pipTouchState.latestMotionEvent).thenReturn(mockMotionEvent) whenever(pipTransitionState.pinnedTaskLeash).thenReturn(mockLeash) whenever(mockPipBoundsState.movementBounds).thenReturn(PIP_BOUNDS) whenever(mockPipBoundsState.motionBoundsState).thenReturn(mockMotionBoundsState) Loading @@ -133,11 +143,11 @@ class PipTouchHandlerTest : ShellTestCase() { @Test fun pipTouchGesture_crossDisplayDragFlagEnabled_onMove_showsMirrors() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(pipTouchState.isUserInteracting).thenReturn(true) whenever(pipTouchState.isDragging).thenReturn(true) // Initialize variables that are set on down pipTouchGesture.onDown(pipTouchState) pipTouchHandler.handleTouchEvent(mockMotionEvent) pipTouchGesture.onMove(pipTouchState) ExtendedMockito.verify { Loading @@ -152,14 +162,14 @@ class PipTouchHandlerTest : ShellTestCase() { ) } verify(mockPipDisplayTransferHandler).showDragMirrorOnConnectedDisplays( eq(GLOBAL_BOUNDS), eq(ORIGIN_DISPLAY_ID)) eq(GLOBAL_BOUNDS), eq(ORIGIN_DISPLAY_ID) ) verify(mockPipMotionHelper).movePip(eq(PIP_BOUNDS), eq(true), eq(ORIGIN_DISPLAY_ID)) } @Test fun pipTouchGesture_crossDisplayDragFlagEnabled_onUpOnADifferentDisplay_schedulesMovePip() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(pipTouchState.isUserInteracting).thenReturn(true) pipTouchGesture.onDown(pipTouchState) pipTouchHandler.mEnableStash = false Loading @@ -183,6 +193,72 @@ class PipTouchHandlerTest : ShellTestCase() { verify(mockPipDisplayTransferHandler).removeMirrors() } @Test fun handleTouchEvent_crossDisplayFlagDisabled_shouldAllowDismissTargetHandler() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(false) whenever(mockMotionEvent.source).thenReturn(SOURCE_MOUSE) pipTouchHandler.handleTouchEvent(mockMotionEvent) verify(mockPipDismissTargetHandler).maybeConsumeMotionEvent(any()) } @Test fun handleTouchEvent_crossDisplayFlagEnabled_touchScreenInput_shouldAllowDismissTargetHandler() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(mockMotionEvent.source).thenReturn(SOURCE_TOUCHSCREEN) pipTouchHandler.handleTouchEvent(mockMotionEvent) verify(mockPipDismissTargetHandler).maybeConsumeMotionEvent(any()) } @Test fun handleTouchEvent_crossDisplayFlagEnabled_mouseInput_shouldNotAllowDismissTargetHandler() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(mockMotionEvent.source).thenReturn(SOURCE_MOUSE) pipTouchHandler.handleTouchEvent(mockMotionEvent) verify(mockPipDismissTargetHandler, never()).maybeConsumeMotionEvent(any()) } @Test fun onMove_crossDisplayFlagDisabled_shouldShowDismissTarget() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(false) whenever(pipTouchState.startedDragging()).thenReturn(true) whenever(mockMotionEvent.source).thenReturn(SOURCE_MOUSE) pipTouchHandler.handleTouchEvent(mockMotionEvent) pipTouchGesture.onMove(pipTouchState) verify(mockPipDismissTargetHandler).showDismissTargetMaybe() } @Test fun onMove_crossDisplayFlagEnabled_touchScreenInput_shouldShowDismissTarget() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(pipTouchState.startedDragging()).thenReturn(true) whenever(mockMotionEvent.source).thenReturn(SOURCE_TOUCHSCREEN) pipTouchHandler.handleTouchEvent(mockMotionEvent) pipTouchGesture.onMove(pipTouchState) verify(mockPipDismissTargetHandler).showDismissTargetMaybe() } @Test fun onMove_crossDisplayFlagEnabled_mouseInput_shouldShowDismissTarget() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(pipTouchState.startedDragging()).thenReturn(true) whenever(mockMotionEvent.source).thenReturn(SOURCE_MOUSE) pipTouchHandler.handleTouchEvent(mockMotionEvent) pipTouchGesture.onMove(pipTouchState) verify(mockPipDismissTargetHandler, never()).showDismissTargetMaybe() } private companion object { const val ORIGIN_DISPLAY_ID = 0 const val TARGET_DISPLAY_ID = 1 Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java +25 −7 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import android.os.SystemProperties; import android.provider.DeviceConfig; import android.util.Size; import android.view.DisplayCutout; import android.view.InputDevice; import android.view.InputEvent; import android.view.MotionEvent; import android.view.ViewConfiguration; Loading Loading @@ -98,7 +99,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha @NonNull private final SizeSpecSource mSizeSpecSource; @NonNull private final PipDisplayLayoutState mPipDisplayLayoutState; private final PipUiEventLogger mPipUiEventLogger; private final PipDismissTargetHandler mPipDismissTargetHandler; private PipDismissTargetHandler mPipDismissTargetHandler; private final ShellExecutor mMainExecutor; @Nullable private final PipPerfHintController mPipPerfHintController; Loading Loading @@ -554,6 +555,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha } if ((ev.getAction() == MotionEvent.ACTION_DOWN || mTouchState.isUserInteracting()) && isDismissTargetEnabled(ev) && mPipDismissTargetHandler.maybeConsumeMotionEvent(ev)) { // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event // to the touch state. Touch state needs a DOWN event in order to later process MOVE Loading Loading @@ -787,22 +789,29 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha return mMotionHelper; } @VisibleForTesting public PipResizeGestureHandler getPipResizeGestureHandler() { @VisibleForTesting PipResizeGestureHandler getPipResizeGestureHandler() { return mPipResizeGestureHandler; } @VisibleForTesting public void setPipResizeGestureHandler(PipResizeGestureHandler pipResizeGestureHandler) { void setPipResizeGestureHandler(PipResizeGestureHandler pipResizeGestureHandler) { mPipResizeGestureHandler = pipResizeGestureHandler; } @VisibleForTesting PipDismissTargetHandler getPipDismissTargetHandler() { return mPipDismissTargetHandler; } @VisibleForTesting public void setPipMotionHelper(PipMotionHelper pipMotionHelper) { void setPipDismissTargetHandler(PipDismissTargetHandler pipDismissTargetHandler) { mPipDismissTargetHandler = pipDismissTargetHandler; } @VisibleForTesting void setPipMotionHelper(PipMotionHelper pipMotionHelper) { mMotionHelper = pipMotionHelper; } @VisibleForTesting public void setPipTouchState(PipTouchState pipTouchState) { @VisibleForTesting void setPipTouchState(PipTouchState pipTouchState) { mTouchState = pipTouchState; } Loading Loading @@ -876,8 +885,10 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha if (touchState.startedDragging()) { mSavedSnapFraction = -1f; if (isDismissTargetEnabled(touchState.getLatestMotionEvent())) { mPipDismissTargetHandler.showDismissTargetMaybe(); } } if (touchState.isDragging()) { mPipBoundsState.setHasUserMovedPip(true); Loading Loading @@ -1087,6 +1098,13 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha } } private boolean isDismissTargetEnabled(MotionEvent ev) { // Only allow dismiss target to be shown and enabled on touch screen and stylus input return !mPipDesktopState.isDraggingPipAcrossDisplaysEnabled() || ev.getSource() == InputDevice.SOURCE_TOUCHSCREEN || ev.getSource() == InputDevice.SOURCE_STYLUS; } /** * Updates the current movement bounds based on whether the menu is currently visible and * resized. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchState.java +10 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ public class PipTouchState { private final PointF mLastTouch = new PointF(); private final PointF mLastDelta = new PointF(); private final PointF mVelocity = new PointF(); private MotionEvent mLatestMotionEvent; private boolean mAllowTouches = true; // Set to false to block both PipTouchHandler and PipResizeGestureHandler's input processing Loading Loading @@ -119,6 +120,7 @@ public class PipTouchState { initOrResetVelocityTracker(); addMovementToVelocityTracker(ev); mLatestMotionEvent = ev; mActivePointerId = ev.getPointerId(0); if (DEBUG) { ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, Loading Loading @@ -247,6 +249,13 @@ public class PipTouchState { return mLastTouch; } /** * @return the motion event of the latest touch event. */ public MotionEvent getLatestMotionEvent() { return mLatestMotionEvent; } /** * @return the movement delta between the last handled touch event and the previous touch * position. Loading Loading @@ -419,6 +428,7 @@ public class PipTouchState { pw.println(innerPrefix + "mLastTouch=" + mLastTouch); pw.println(innerPrefix + "mLastDelta=" + mLastDelta); pw.println(innerPrefix + "mVelocity=" + mVelocity); pw.println(innerPrefix + "mLatestMotionEvent=" + mLatestMotionEvent); pw.println(innerPrefix + "mIsUserInteracting=" + mIsUserInteracting); pw.println(innerPrefix + "mIsDragging=" + mIsDragging); pw.println(innerPrefix + "mStartedDragging=" + mStartedDragging); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTouchHandlerTest.kt +79 −3 Original line number Diff line number Diff line Loading @@ -20,6 +20,9 @@ import android.graphics.Rect import android.graphics.RectF import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.InputDevice.SOURCE_MOUSE import android.view.InputDevice.SOURCE_TOUCHSCREEN import android.view.MotionEvent import android.view.SurfaceControl import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito Loading Loading @@ -49,6 +52,7 @@ import org.mockito.ArgumentMatchers.anyInt import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.verify import org.mockito.kotlin.whenever Loading Loading @@ -85,6 +89,8 @@ class PipTouchHandlerTest : ShellTestCase() { private val mockDisplayLayout = mock<DisplayLayout>() private val mockTouchPosition = PointF() private val mockPipSurfaceTransactionHelper = mock<PipSurfaceTransactionHelper>() private val mockMotionEvent = mock<MotionEvent>() private val mockPipDismissTargetHandler = mock<PipDismissTargetHandler>() private lateinit var pipTouchHandler: PipTouchHandler private lateinit var pipTouchGesture: PipTouchGesture Loading @@ -108,12 +114,16 @@ class PipTouchHandlerTest : ShellTestCase() { ) pipTouchGesture = pipTouchHandler.touchGesture pipTouchHandler.setPipTouchState(pipTouchState) pipTouchHandler.setPipDismissTargetHandler(mockPipDismissTargetHandler) whenever(pipTouchState.downTouchPosition).thenReturn(mockTouchPosition) whenever(pipTouchState.velocity).thenReturn(mockTouchPosition) whenever(pipTouchState.lastTouchPosition).thenReturn(mockTouchPosition) whenever(pipTouchState.lastTouchDisplayId).thenReturn(ORIGIN_DISPLAY_ID) whenever(pipTouchState.lastTouchDelta).thenReturn(mockTouchPosition) whenever(pipTouchState.isUserInteracting).thenReturn(true) whenever(pipTouchState.allowInputEvents).thenReturn(true) whenever(pipTouchState.latestMotionEvent).thenReturn(mockMotionEvent) whenever(pipTransitionState.pinnedTaskLeash).thenReturn(mockLeash) whenever(mockPipBoundsState.movementBounds).thenReturn(PIP_BOUNDS) whenever(mockPipBoundsState.motionBoundsState).thenReturn(mockMotionBoundsState) Loading @@ -133,11 +143,11 @@ class PipTouchHandlerTest : ShellTestCase() { @Test fun pipTouchGesture_crossDisplayDragFlagEnabled_onMove_showsMirrors() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(pipTouchState.isUserInteracting).thenReturn(true) whenever(pipTouchState.isDragging).thenReturn(true) // Initialize variables that are set on down pipTouchGesture.onDown(pipTouchState) pipTouchHandler.handleTouchEvent(mockMotionEvent) pipTouchGesture.onMove(pipTouchState) ExtendedMockito.verify { Loading @@ -152,14 +162,14 @@ class PipTouchHandlerTest : ShellTestCase() { ) } verify(mockPipDisplayTransferHandler).showDragMirrorOnConnectedDisplays( eq(GLOBAL_BOUNDS), eq(ORIGIN_DISPLAY_ID)) eq(GLOBAL_BOUNDS), eq(ORIGIN_DISPLAY_ID) ) verify(mockPipMotionHelper).movePip(eq(PIP_BOUNDS), eq(true), eq(ORIGIN_DISPLAY_ID)) } @Test fun pipTouchGesture_crossDisplayDragFlagEnabled_onUpOnADifferentDisplay_schedulesMovePip() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(pipTouchState.isUserInteracting).thenReturn(true) pipTouchGesture.onDown(pipTouchState) pipTouchHandler.mEnableStash = false Loading @@ -183,6 +193,72 @@ class PipTouchHandlerTest : ShellTestCase() { verify(mockPipDisplayTransferHandler).removeMirrors() } @Test fun handleTouchEvent_crossDisplayFlagDisabled_shouldAllowDismissTargetHandler() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(false) whenever(mockMotionEvent.source).thenReturn(SOURCE_MOUSE) pipTouchHandler.handleTouchEvent(mockMotionEvent) verify(mockPipDismissTargetHandler).maybeConsumeMotionEvent(any()) } @Test fun handleTouchEvent_crossDisplayFlagEnabled_touchScreenInput_shouldAllowDismissTargetHandler() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(mockMotionEvent.source).thenReturn(SOURCE_TOUCHSCREEN) pipTouchHandler.handleTouchEvent(mockMotionEvent) verify(mockPipDismissTargetHandler).maybeConsumeMotionEvent(any()) } @Test fun handleTouchEvent_crossDisplayFlagEnabled_mouseInput_shouldNotAllowDismissTargetHandler() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(mockMotionEvent.source).thenReturn(SOURCE_MOUSE) pipTouchHandler.handleTouchEvent(mockMotionEvent) verify(mockPipDismissTargetHandler, never()).maybeConsumeMotionEvent(any()) } @Test fun onMove_crossDisplayFlagDisabled_shouldShowDismissTarget() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(false) whenever(pipTouchState.startedDragging()).thenReturn(true) whenever(mockMotionEvent.source).thenReturn(SOURCE_MOUSE) pipTouchHandler.handleTouchEvent(mockMotionEvent) pipTouchGesture.onMove(pipTouchState) verify(mockPipDismissTargetHandler).showDismissTargetMaybe() } @Test fun onMove_crossDisplayFlagEnabled_touchScreenInput_shouldShowDismissTarget() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(pipTouchState.startedDragging()).thenReturn(true) whenever(mockMotionEvent.source).thenReturn(SOURCE_TOUCHSCREEN) pipTouchHandler.handleTouchEvent(mockMotionEvent) pipTouchGesture.onMove(pipTouchState) verify(mockPipDismissTargetHandler).showDismissTargetMaybe() } @Test fun onMove_crossDisplayFlagEnabled_mouseInput_shouldShowDismissTarget() { whenever(mockPipDesktopState.isDraggingPipAcrossDisplaysEnabled()).thenReturn(true) whenever(pipTouchState.startedDragging()).thenReturn(true) whenever(mockMotionEvent.source).thenReturn(SOURCE_MOUSE) pipTouchHandler.handleTouchEvent(mockMotionEvent) pipTouchGesture.onMove(pipTouchState) verify(mockPipDismissTargetHandler, never()).showDismissTargetMaybe() } private companion object { const val ORIGIN_DISPLAY_ID = 0 const val TARGET_DISPLAY_ID = 1 Loading