Loading libs/WindowManager/Shell/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -142,6 +142,10 @@ Needs to be less that or equal to 1. --> <item name="config_pipLargeScreenOptimizedAspectRatio" format="float" type="dimen">0.5625</item> <!-- The opacity of the PiP window when it's being dragged to enter or exit an unfocused display in connected displays extended mode. Needs to be between 0 and 1. --> <item name="config_pipDraggingAcrossDisplaysOpacity" format="float" type="dimen">0.75</item> <!-- The default gravity for the picture-in-picture window. Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT --> <integer name="config_defaultPictureInPictureGravity">0x55</integer> Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +6 −6 Original line number Diff line number Diff line Loading @@ -167,11 +167,11 @@ public abstract class Pip2Module { Optional<SplitScreenController> splitScreenControllerOptional, Optional<DesktopPipTransitionController> desktopPipTransitionController, PipDesktopState pipDesktopState, DisplayController displayController) { DisplayController displayController, PipDisplayLayoutState pipDisplayLayoutState) { return new PipScheduler(context, pipSurfaceTransactionHelper, pipBoundsState, mainExecutor, pipTransitionState, splitScreenControllerOptional, desktopPipTransitionController, pipDesktopState, displayController); pipTransitionState, splitScreenControllerOptional, desktopPipTransitionController, pipDesktopState, displayController, pipDisplayLayoutState); } @WMSingleton Loading Loading @@ -240,10 +240,10 @@ public abstract class Pip2Module { PipScheduler pipScheduler, Optional<PipPerfHintController> pipPerfHintControllerOptional, PipTransitionState pipTransitionState, PipUiEventLogger pipUiEventLogger) { PipUiEventLogger pipUiEventLogger, PipDisplayLayoutState pipDisplayLayoutState) { return new PipMotionHelper(context, pipBoundsState, menuController, pipSnapAlgorithm, floatingContentCoordinator, pipScheduler, pipPerfHintControllerOptional, pipTransitionState, pipUiEventLogger); pipTransitionState, pipUiEventLogger, pipDisplayLayoutState); } @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/PipSurfaceTransactionHelper.java +13 −0 Original line number Diff line number Diff line Loading @@ -34,10 +34,13 @@ public class PipSurfaceTransactionHelper { private final int mCornerRadius; private final int mShadowRadius; private final float mMirrorOpacity; public PipSurfaceTransactionHelper(Context context) { mCornerRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius); mShadowRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_shadow_radius); mMirrorOpacity = context.getResources().getFloat( R.dimen.config_pipDraggingAcrossDisplaysOpacity); } /** Loading Loading @@ -163,6 +166,16 @@ public class PipSurfaceTransactionHelper { return this; } /** * Sets default transformations for mirrors a given mirror root of a PiP {@param leash}. */ public PipSurfaceTransactionHelper setMirrorTransformations(SurfaceControl.Transaction tx, SurfaceControl leash) { tx.setAlpha(leash, mMirrorOpacity); tx.setLayer(leash, Integer.MAX_VALUE); tx.show(leash); return this; } /** * Sets PiP translational, scaling and rotational transformations on a given transaction. Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDisplayTransferHandler.java +14 −8 Original line number Diff line number Diff line Loading @@ -119,23 +119,29 @@ public class PipDisplayTransferHandler implements * Show a drag indicator mirror on each connected display according to the current pointer * position. * * @param originDisplayId the display ID where the drag originated from * @param globalDpPipBounds the PiP bounds in display topology-aware global DP * @param focusedDisplayId the display ID where the cursor is currently on */ public void showDragMirrorOnConnectedDisplays(int originDisplayId, RectF globalDpPipBounds) { public void showDragMirrorOnConnectedDisplays(RectF globalDpPipBounds, int focusedDisplayId) { final Transaction transaction = mSurfaceControlTransactionFactory.getTransaction(); // Iterate through each connected display ID to ensure partial PiP bounds are shown on // all corresponding displays while dragging for (int displayId : mRootTaskDisplayAreaOrganizer.getDisplayIds()) { if (displayId == originDisplayId) continue; DisplayLayout displayLayout = mDisplayController.getDisplayLayout(displayId); if (displayLayout == null) continue; // If PiP does not cross the boundaries of a given display bounds, skip boolean shouldShowOnDisplay = RectF.intersects(globalDpPipBounds, displayLayout.globalBoundsDp()); if (!shouldShowOnDisplay) continue; // 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) { if (mOnDragMirrorPerDisplayId.containsKey(displayId)) { SurfaceControl pipMirror = mOnDragMirrorPerDisplayId.get(displayId); transaction.hide(pipMirror); } continue; } // Create a mirror for the current display if it hasn't been created yet SurfaceControl mirror; Loading @@ -151,9 +157,9 @@ public class PipDisplayTransferHandler implements MultiDisplayDragMoveBoundsCalculator.convertGlobalDpToLocalPxForRect( globalDpPipBounds, displayLayout); mPipSurfaceTransactionHelper.setPipTransformations(mirror, transaction, mPipBoundsState.getBounds(), boundsOnCurrentDisplay, /* degrees= */ 0); mPipBoundsState.getBounds(), boundsOnCurrentDisplay, /* degrees= */ 0).setMirrorTransformations(transaction, mirror); mRootTaskDisplayAreaOrganizer.reparentToDisplayArea(displayId, mirror, transaction); transaction.show(mirror); } transaction.apply(); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java +25 −9 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.wm.shell.animation.FloatProperties; import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.pip.PipAppOpsListener; import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipDisplayLayoutState; import com.android.wm.shell.common.pip.PipPerfHintController; import com.android.wm.shell.common.pip.PipSnapAlgorithm; import com.android.wm.shell.common.pip.PipUiEventLogger; Loading Loading @@ -82,6 +83,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, private final Context mContext; @NonNull private final PipBoundsState mPipBoundsState; @NonNull private final PipDisplayLayoutState mPipDisplayLayoutState; @NonNull private final PipScheduler mPipScheduler; @NonNull private final PipTransitionState mPipTransitionState; @NonNull private final PipUiEventLogger mPipUiEventLogger; Loading Loading @@ -171,7 +173,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, PhonePipMenuController menuController, PipSnapAlgorithm snapAlgorithm, FloatingContentCoordinator floatingContentCoordinator, PipScheduler pipScheduler, Optional<PipPerfHintController> pipPerfHintControllerOptional, PipTransitionState pipTransitionState, PipUiEventLogger pipUiEventLogger) { PipTransitionState pipTransitionState, PipUiEventLogger pipUiEventLogger, PipDisplayLayoutState pipDisplayLayoutState) { mContext = context; mPipBoundsState = pipBoundsState; mPipScheduler = pipScheduler; Loading @@ -189,6 +192,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, mPipTransitionState.addPipTransitionStateChangedListener(this); mPipUiEventLogger = pipUiEventLogger; mSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context); mPipDisplayLayoutState = pipDisplayLayoutState; } void init() { Loading Loading @@ -229,20 +233,32 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, } /** * Tries to move the pinned stack to the given {@param bounds}. * Tries to move the pinned stack to the given {@param toBounds} on the current display ID. */ void movePip(Rect toBounds) { movePip(toBounds, false /* isDragging */); movePip(toBounds, false /* isDragging */, mPipDisplayLayoutState.getDisplayId() /* focusedDisplayId */); } /** * Tries to move the pinned stack to {@param toBounds} on the {@param focusedDisplayId} which * follows the cursor's focus. */ void movePip(Rect toBounds, int focusedDisplayId) { movePip(toBounds, false /* isDragging */, focusedDisplayId /* focusedDisplayId */); } /** * Tries to move the pinned stack to the given {@param bounds}. * Tries to move the pinned stack to the given bounds. * * @param isDragging Whether this movement is the result of a drag touch gesture. If so, we * won't notify the floating content coordinator of this move, since that will * happen when the gesture ends. * @param toBounds bounds to move the pinned stack to * @param isDragging Whether this movement is the result of a drag touch gesture. If * so, we won't notify the floating content coordinator of this move, * since that will happen when the gesture ends. * @param focusedDisplayId the display ID of where the cursor currently is */ void movePip(Rect toBounds, boolean isDragging) { void movePip(Rect toBounds, boolean isDragging, int focusedDisplayId) { if (!isDragging) { mFloatingContentCoordinator.onContentMoved(this); } Loading @@ -257,7 +273,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, mPipBoundsState.setBounds(toBounds); } else { mPipBoundsState.getMotionBoundsState().setBoundsInMotion(toBounds); mPipScheduler.scheduleUserResizePip(toBounds); mPipScheduler.scheduleUserResizePip(toBounds, focusedDisplayId); } } else { // If PIP is 'catching up' after being stuck in the dismiss target, update the animation Loading Loading
libs/WindowManager/Shell/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -142,6 +142,10 @@ Needs to be less that or equal to 1. --> <item name="config_pipLargeScreenOptimizedAspectRatio" format="float" type="dimen">0.5625</item> <!-- The opacity of the PiP window when it's being dragged to enter or exit an unfocused display in connected displays extended mode. Needs to be between 0 and 1. --> <item name="config_pipDraggingAcrossDisplaysOpacity" format="float" type="dimen">0.75</item> <!-- The default gravity for the picture-in-picture window. Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT --> <integer name="config_defaultPictureInPictureGravity">0x55</integer> Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +6 −6 Original line number Diff line number Diff line Loading @@ -167,11 +167,11 @@ public abstract class Pip2Module { Optional<SplitScreenController> splitScreenControllerOptional, Optional<DesktopPipTransitionController> desktopPipTransitionController, PipDesktopState pipDesktopState, DisplayController displayController) { DisplayController displayController, PipDisplayLayoutState pipDisplayLayoutState) { return new PipScheduler(context, pipSurfaceTransactionHelper, pipBoundsState, mainExecutor, pipTransitionState, splitScreenControllerOptional, desktopPipTransitionController, pipDesktopState, displayController); pipTransitionState, splitScreenControllerOptional, desktopPipTransitionController, pipDesktopState, displayController, pipDisplayLayoutState); } @WMSingleton Loading Loading @@ -240,10 +240,10 @@ public abstract class Pip2Module { PipScheduler pipScheduler, Optional<PipPerfHintController> pipPerfHintControllerOptional, PipTransitionState pipTransitionState, PipUiEventLogger pipUiEventLogger) { PipUiEventLogger pipUiEventLogger, PipDisplayLayoutState pipDisplayLayoutState) { return new PipMotionHelper(context, pipBoundsState, menuController, pipSnapAlgorithm, floatingContentCoordinator, pipScheduler, pipPerfHintControllerOptional, pipTransitionState, pipUiEventLogger); pipTransitionState, pipUiEventLogger, pipDisplayLayoutState); } @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/PipSurfaceTransactionHelper.java +13 −0 Original line number Diff line number Diff line Loading @@ -34,10 +34,13 @@ public class PipSurfaceTransactionHelper { private final int mCornerRadius; private final int mShadowRadius; private final float mMirrorOpacity; public PipSurfaceTransactionHelper(Context context) { mCornerRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius); mShadowRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_shadow_radius); mMirrorOpacity = context.getResources().getFloat( R.dimen.config_pipDraggingAcrossDisplaysOpacity); } /** Loading Loading @@ -163,6 +166,16 @@ public class PipSurfaceTransactionHelper { return this; } /** * Sets default transformations for mirrors a given mirror root of a PiP {@param leash}. */ public PipSurfaceTransactionHelper setMirrorTransformations(SurfaceControl.Transaction tx, SurfaceControl leash) { tx.setAlpha(leash, mMirrorOpacity); tx.setLayer(leash, Integer.MAX_VALUE); tx.show(leash); return this; } /** * Sets PiP translational, scaling and rotational transformations on a given transaction. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDisplayTransferHandler.java +14 −8 Original line number Diff line number Diff line Loading @@ -119,23 +119,29 @@ public class PipDisplayTransferHandler implements * Show a drag indicator mirror on each connected display according to the current pointer * position. * * @param originDisplayId the display ID where the drag originated from * @param globalDpPipBounds the PiP bounds in display topology-aware global DP * @param focusedDisplayId the display ID where the cursor is currently on */ public void showDragMirrorOnConnectedDisplays(int originDisplayId, RectF globalDpPipBounds) { public void showDragMirrorOnConnectedDisplays(RectF globalDpPipBounds, int focusedDisplayId) { final Transaction transaction = mSurfaceControlTransactionFactory.getTransaction(); // Iterate through each connected display ID to ensure partial PiP bounds are shown on // all corresponding displays while dragging for (int displayId : mRootTaskDisplayAreaOrganizer.getDisplayIds()) { if (displayId == originDisplayId) continue; DisplayLayout displayLayout = mDisplayController.getDisplayLayout(displayId); if (displayLayout == null) continue; // If PiP does not cross the boundaries of a given display bounds, skip boolean shouldShowOnDisplay = RectF.intersects(globalDpPipBounds, displayLayout.globalBoundsDp()); if (!shouldShowOnDisplay) continue; // 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) { if (mOnDragMirrorPerDisplayId.containsKey(displayId)) { SurfaceControl pipMirror = mOnDragMirrorPerDisplayId.get(displayId); transaction.hide(pipMirror); } continue; } // Create a mirror for the current display if it hasn't been created yet SurfaceControl mirror; Loading @@ -151,9 +157,9 @@ public class PipDisplayTransferHandler implements MultiDisplayDragMoveBoundsCalculator.convertGlobalDpToLocalPxForRect( globalDpPipBounds, displayLayout); mPipSurfaceTransactionHelper.setPipTransformations(mirror, transaction, mPipBoundsState.getBounds(), boundsOnCurrentDisplay, /* degrees= */ 0); mPipBoundsState.getBounds(), boundsOnCurrentDisplay, /* degrees= */ 0).setMirrorTransformations(transaction, mirror); mRootTaskDisplayAreaOrganizer.reparentToDisplayArea(displayId, mirror, transaction); transaction.show(mirror); } transaction.apply(); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java +25 −9 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.wm.shell.animation.FloatProperties; import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.pip.PipAppOpsListener; import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipDisplayLayoutState; import com.android.wm.shell.common.pip.PipPerfHintController; import com.android.wm.shell.common.pip.PipSnapAlgorithm; import com.android.wm.shell.common.pip.PipUiEventLogger; Loading Loading @@ -82,6 +83,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, private final Context mContext; @NonNull private final PipBoundsState mPipBoundsState; @NonNull private final PipDisplayLayoutState mPipDisplayLayoutState; @NonNull private final PipScheduler mPipScheduler; @NonNull private final PipTransitionState mPipTransitionState; @NonNull private final PipUiEventLogger mPipUiEventLogger; Loading Loading @@ -171,7 +173,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, PhonePipMenuController menuController, PipSnapAlgorithm snapAlgorithm, FloatingContentCoordinator floatingContentCoordinator, PipScheduler pipScheduler, Optional<PipPerfHintController> pipPerfHintControllerOptional, PipTransitionState pipTransitionState, PipUiEventLogger pipUiEventLogger) { PipTransitionState pipTransitionState, PipUiEventLogger pipUiEventLogger, PipDisplayLayoutState pipDisplayLayoutState) { mContext = context; mPipBoundsState = pipBoundsState; mPipScheduler = pipScheduler; Loading @@ -189,6 +192,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, mPipTransitionState.addPipTransitionStateChangedListener(this); mPipUiEventLogger = pipUiEventLogger; mSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context); mPipDisplayLayoutState = pipDisplayLayoutState; } void init() { Loading Loading @@ -229,20 +233,32 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, } /** * Tries to move the pinned stack to the given {@param bounds}. * Tries to move the pinned stack to the given {@param toBounds} on the current display ID. */ void movePip(Rect toBounds) { movePip(toBounds, false /* isDragging */); movePip(toBounds, false /* isDragging */, mPipDisplayLayoutState.getDisplayId() /* focusedDisplayId */); } /** * Tries to move the pinned stack to {@param toBounds} on the {@param focusedDisplayId} which * follows the cursor's focus. */ void movePip(Rect toBounds, int focusedDisplayId) { movePip(toBounds, false /* isDragging */, focusedDisplayId /* focusedDisplayId */); } /** * Tries to move the pinned stack to the given {@param bounds}. * Tries to move the pinned stack to the given bounds. * * @param isDragging Whether this movement is the result of a drag touch gesture. If so, we * won't notify the floating content coordinator of this move, since that will * happen when the gesture ends. * @param toBounds bounds to move the pinned stack to * @param isDragging Whether this movement is the result of a drag touch gesture. If * so, we won't notify the floating content coordinator of this move, * since that will happen when the gesture ends. * @param focusedDisplayId the display ID of where the cursor currently is */ void movePip(Rect toBounds, boolean isDragging) { void movePip(Rect toBounds, boolean isDragging, int focusedDisplayId) { if (!isDragging) { mFloatingContentCoordinator.onContentMoved(this); } Loading @@ -257,7 +273,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, mPipBoundsState.setBounds(toBounds); } else { mPipBoundsState.getMotionBoundsState().setBoundsInMotion(toBounds); mPipScheduler.scheduleUserResizePip(toBounds); mPipScheduler.scheduleUserResizePip(toBounds, focusedDisplayId); } } else { // If PIP is 'catching up' after being stuck in the dismiss target, update the animation Loading