Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDisplayTransferHandler.java +27 −6 Original line number Diff line number Diff line Loading @@ -203,18 +203,19 @@ public class PipDisplayTransferHandler implements public void showDragMirrorOnConnectedDisplays(RectF globalDpPipBounds, int focusedDisplayId) { final Transaction transaction = mSurfaceControlTransactionFactory.getTransaction(); mIsMirrorShown = false; // If PiP is on a display that's not in the topology, don't show drag mirrors on other // displays because it can't be dragged over. if (!mDisplayController.isDisplayInTopology(focusedDisplayId)) return; // Iterate through each connected display ID to ensure partial PiP bounds are shown on // all corresponding displays while dragging for (int displayId : mRootTaskDisplayAreaOrganizer.getDisplayIds()) { DisplayLayout displayLayout = mDisplayController.getDisplayLayout(displayId); if (displayLayout == null) continue; boolean shouldShowOnDisplay = RectF.intersects(globalDpPipBounds, displayLayout.globalBoundsDp()); // Hide mirror if it's the currently focused display or if the PiP bounds do not // intersect with the boundaries of a given display bounds if (displayId == focusedDisplayId || !shouldShowOnDisplay) { // Hide mirror(s) if it shouldn't be shown on this display. if (!canShowMirrorForDisplay(displayId, focusedDisplayId, displayLayout, globalDpPipBounds)) { if (mOnDragMirrorPerDisplayId.containsKey(displayId)) { SurfaceControl pipMirror = mOnDragMirrorPerDisplayId.get(displayId); transaction.hide(pipMirror); Loading Loading @@ -244,6 +245,26 @@ public class PipDisplayTransferHandler implements transaction.apply(); } /** * Drag mirrors can only be shown on non-focused display(s) in the topology that intersect * with the PiP global DP bounds. * * @param displayId the given display ID on which drag mirror should be shown * @param focusedDisplayId the display ID of where the PiP window is focused on * (where the pointer is) * @param displayLayout the display layout of the given display ID * @param globalDpBounds the PiP bounds in global DP * @return whether drag mirror can be shown on a given display ID. */ private boolean canShowMirrorForDisplay(int displayId, int focusedDisplayId, DisplayLayout displayLayout, RectF globalDpBounds) { boolean pipBoundsIntersectDisplay = RectF.intersects(globalDpBounds, displayLayout.globalBoundsDp()); return displayId != focusedDisplayId && pipBoundsIntersectDisplay && mDisplayController.isDisplayInTopology(displayId); } /** * Remove all drag indicator mirrors from each connected display. */ Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipDisplayTransferHandlerTest.kt +65 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,7 @@ class PipDisplayTransferHandlerTest : ShellTestCase() { TestDisplay.entries.find { it.id == id }?.getSpyDisplayLayout(resources) displayLayouts.put(id, displayLayout) whenever(mockDisplayController.getDisplayLayout(id)).thenReturn(displayLayout) whenever(mockDisplayController.isDisplayInTopology(id)).thenReturn(true) } pipDisplayTransferHandler = Loading Loading @@ -385,6 +386,70 @@ class PipDisplayTransferHandlerTest : ShellTestCase() { assertThat(pipDisplayTransferHandler.isMirrorShown()).isTrue() } @Test fun showDragMirrorOnConnectedDisplays_displayNotInTopology_createsOneFewerMirror() { val globalDpBounds = MultiDisplayDragMoveBoundsCalculator.calculateGlobalDpBoundsForDrag( displayLayouts.get(ORIGIN_DISPLAY_ID)!!, START_DRAG_COORDINATES, PIP_BOUNDS, displayLayouts.get(TARGET_DISPLAY_ID)!!, 1000f, -100f) whenever(mockDisplayController.isDisplayInTopology(SECONDARY_DISPLAY_ID)).thenReturn(false) pipDisplayTransferHandler.showDragMirrorOnConnectedDisplays( globalDpBounds, ORIGIN_DISPLAY_ID ) verify(mockRootTaskDisplayAreaOrganizer).reparentToDisplayArea( eq(TARGET_DISPLAY_ID), any(), any() ) assertThat(pipDisplayTransferHandler.mOnDragMirrorPerDisplayId.size).isEqualTo(1) assertThat( pipDisplayTransferHandler.mOnDragMirrorPerDisplayId.containsKey( SECONDARY_DISPLAY_ID ) ).isFalse() assertThat( pipDisplayTransferHandler.mOnDragMirrorPerDisplayId.containsKey( TARGET_DISPLAY_ID ) ).isTrue() verify(mockSurfaceTransactionHelper, times(1)).setPipTransformations( any(), any(), any(), any(), any() ) verify(mockSurfaceTransactionHelper, times(1)).setMirrorTransformations(any(), any()) verify(mockTransaction, times(1)).apply() assertThat(pipDisplayTransferHandler.isMirrorShown()).isTrue() } @Test fun showDragMirrorOnConnectedDisplays_focusedDisplayNotInTopology_doesNotCreateMirrors() { val globalDpBounds = MultiDisplayDragMoveBoundsCalculator.calculateGlobalDpBoundsForDrag( displayLayouts.get(ORIGIN_DISPLAY_ID)!!, START_DRAG_COORDINATES, PIP_BOUNDS, displayLayouts.get(TARGET_DISPLAY_ID)!!, 1000f, -100f) whenever(mockDisplayController.isDisplayInTopology(ORIGIN_DISPLAY_ID)).thenReturn(false) pipDisplayTransferHandler.showDragMirrorOnConnectedDisplays( globalDpBounds, ORIGIN_DISPLAY_ID ) verify(mockRootTaskDisplayAreaOrganizer, never()).reparentToDisplayArea( any(), any(), any() ) assertThat(pipDisplayTransferHandler.mOnDragMirrorPerDisplayId.isEmpty()).isTrue() verify(mockSurfaceTransactionHelper, never()).setPipTransformations( any(), any(), any(), any(), any() ) verify(mockSurfaceTransactionHelper, never()).setMirrorTransformations(any(), any()) verify(mockTransaction, never()).apply() assertThat(pipDisplayTransferHandler.isMirrorShown()).isFalse() } @Test fun removeMirrors_removesAllMirrorsAndAppliesTransactionOnce() { pipDisplayTransferHandler.mOnDragMirrorPerDisplayId = ArrayMap() Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDisplayTransferHandler.java +27 −6 Original line number Diff line number Diff line Loading @@ -203,18 +203,19 @@ public class PipDisplayTransferHandler implements public void showDragMirrorOnConnectedDisplays(RectF globalDpPipBounds, int focusedDisplayId) { final Transaction transaction = mSurfaceControlTransactionFactory.getTransaction(); mIsMirrorShown = false; // If PiP is on a display that's not in the topology, don't show drag mirrors on other // displays because it can't be dragged over. if (!mDisplayController.isDisplayInTopology(focusedDisplayId)) return; // Iterate through each connected display ID to ensure partial PiP bounds are shown on // all corresponding displays while dragging for (int displayId : mRootTaskDisplayAreaOrganizer.getDisplayIds()) { DisplayLayout displayLayout = mDisplayController.getDisplayLayout(displayId); if (displayLayout == null) continue; boolean shouldShowOnDisplay = RectF.intersects(globalDpPipBounds, displayLayout.globalBoundsDp()); // Hide mirror if it's the currently focused display or if the PiP bounds do not // intersect with the boundaries of a given display bounds if (displayId == focusedDisplayId || !shouldShowOnDisplay) { // Hide mirror(s) if it shouldn't be shown on this display. if (!canShowMirrorForDisplay(displayId, focusedDisplayId, displayLayout, globalDpPipBounds)) { if (mOnDragMirrorPerDisplayId.containsKey(displayId)) { SurfaceControl pipMirror = mOnDragMirrorPerDisplayId.get(displayId); transaction.hide(pipMirror); Loading Loading @@ -244,6 +245,26 @@ public class PipDisplayTransferHandler implements transaction.apply(); } /** * Drag mirrors can only be shown on non-focused display(s) in the topology that intersect * with the PiP global DP bounds. * * @param displayId the given display ID on which drag mirror should be shown * @param focusedDisplayId the display ID of where the PiP window is focused on * (where the pointer is) * @param displayLayout the display layout of the given display ID * @param globalDpBounds the PiP bounds in global DP * @return whether drag mirror can be shown on a given display ID. */ private boolean canShowMirrorForDisplay(int displayId, int focusedDisplayId, DisplayLayout displayLayout, RectF globalDpBounds) { boolean pipBoundsIntersectDisplay = RectF.intersects(globalDpBounds, displayLayout.globalBoundsDp()); return displayId != focusedDisplayId && pipBoundsIntersectDisplay && mDisplayController.isDisplayInTopology(displayId); } /** * Remove all drag indicator mirrors from each connected display. */ Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipDisplayTransferHandlerTest.kt +65 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,7 @@ class PipDisplayTransferHandlerTest : ShellTestCase() { TestDisplay.entries.find { it.id == id }?.getSpyDisplayLayout(resources) displayLayouts.put(id, displayLayout) whenever(mockDisplayController.getDisplayLayout(id)).thenReturn(displayLayout) whenever(mockDisplayController.isDisplayInTopology(id)).thenReturn(true) } pipDisplayTransferHandler = Loading Loading @@ -385,6 +386,70 @@ class PipDisplayTransferHandlerTest : ShellTestCase() { assertThat(pipDisplayTransferHandler.isMirrorShown()).isTrue() } @Test fun showDragMirrorOnConnectedDisplays_displayNotInTopology_createsOneFewerMirror() { val globalDpBounds = MultiDisplayDragMoveBoundsCalculator.calculateGlobalDpBoundsForDrag( displayLayouts.get(ORIGIN_DISPLAY_ID)!!, START_DRAG_COORDINATES, PIP_BOUNDS, displayLayouts.get(TARGET_DISPLAY_ID)!!, 1000f, -100f) whenever(mockDisplayController.isDisplayInTopology(SECONDARY_DISPLAY_ID)).thenReturn(false) pipDisplayTransferHandler.showDragMirrorOnConnectedDisplays( globalDpBounds, ORIGIN_DISPLAY_ID ) verify(mockRootTaskDisplayAreaOrganizer).reparentToDisplayArea( eq(TARGET_DISPLAY_ID), any(), any() ) assertThat(pipDisplayTransferHandler.mOnDragMirrorPerDisplayId.size).isEqualTo(1) assertThat( pipDisplayTransferHandler.mOnDragMirrorPerDisplayId.containsKey( SECONDARY_DISPLAY_ID ) ).isFalse() assertThat( pipDisplayTransferHandler.mOnDragMirrorPerDisplayId.containsKey( TARGET_DISPLAY_ID ) ).isTrue() verify(mockSurfaceTransactionHelper, times(1)).setPipTransformations( any(), any(), any(), any(), any() ) verify(mockSurfaceTransactionHelper, times(1)).setMirrorTransformations(any(), any()) verify(mockTransaction, times(1)).apply() assertThat(pipDisplayTransferHandler.isMirrorShown()).isTrue() } @Test fun showDragMirrorOnConnectedDisplays_focusedDisplayNotInTopology_doesNotCreateMirrors() { val globalDpBounds = MultiDisplayDragMoveBoundsCalculator.calculateGlobalDpBoundsForDrag( displayLayouts.get(ORIGIN_DISPLAY_ID)!!, START_DRAG_COORDINATES, PIP_BOUNDS, displayLayouts.get(TARGET_DISPLAY_ID)!!, 1000f, -100f) whenever(mockDisplayController.isDisplayInTopology(ORIGIN_DISPLAY_ID)).thenReturn(false) pipDisplayTransferHandler.showDragMirrorOnConnectedDisplays( globalDpBounds, ORIGIN_DISPLAY_ID ) verify(mockRootTaskDisplayAreaOrganizer, never()).reparentToDisplayArea( any(), any(), any() ) assertThat(pipDisplayTransferHandler.mOnDragMirrorPerDisplayId.isEmpty()).isTrue() verify(mockSurfaceTransactionHelper, never()).setPipTransformations( any(), any(), any(), any(), any() ) verify(mockSurfaceTransactionHelper, never()).setMirrorTransformations(any(), any()) verify(mockTransaction, never()).apply() assertThat(pipDisplayTransferHandler.isMirrorShown()).isFalse() } @Test fun removeMirrors_removesAllMirrorsAndAppliesTransactionOnce() { pipDisplayTransferHandler.mOnDragMirrorPerDisplayId = ArrayMap() Loading