Loading libs/WindowManager/Shell/src/com/android/wm/shell/common/TabletopModeController.java +46 −0 Original line number Diff line number Diff line Loading @@ -22,10 +22,12 @@ import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_UNKNOWN; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_FOLDABLE; import android.annotation.IntDef; import android.annotation.NonNull; import android.app.WindowConfiguration; import android.content.Context; import android.content.res.Configuration; import android.os.SystemProperties; import android.util.ArraySet; import android.view.Surface; Loading @@ -34,6 +36,8 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.sysui.ShellInit; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Set; Loading @@ -49,8 +53,34 @@ import java.util.Set; public class TabletopModeController implements DevicePostureController.OnDevicePostureChangedListener, DisplayController.OnDisplaysChangedListener { /** * When {@code true}, floating windows like PiP would auto move to the position * specified by {@link #PREFER_TOP_HALF_IN_TABLETOP} when in tabletop mode. */ private static final boolean ENABLE_MOVE_FLOATING_WINDOW_IN_TABLETOP = SystemProperties.getBoolean( "persist.wm.debug.enable_move_floating_window_in_tabletop", false); /** * Prefer the {@link #PREFERRED_TABLETOP_HALF_TOP} if this flag is enabled, * {@link #PREFERRED_TABLETOP_HALF_BOTTOM} otherwise. * See also {@link #getPreferredHalfInTabletopMode()}. */ private static final boolean PREFER_TOP_HALF_IN_TABLETOP = SystemProperties.getBoolean("persist.wm.debug.prefer_top_half_in_tabletop", true); private static final long TABLETOP_MODE_DELAY_MILLIS = 1_000; @IntDef(prefix = {"PREFERRED_TABLETOP_HALF_"}, value = { PREFERRED_TABLETOP_HALF_TOP, PREFERRED_TABLETOP_HALF_BOTTOM }) @Retention(RetentionPolicy.SOURCE) public @interface PreferredTabletopHalf {} public static final int PREFERRED_TABLETOP_HALF_TOP = 0; public static final int PREFERRED_TABLETOP_HALF_BOTTOM = 1; private final Context mContext; private final DevicePostureController mDevicePostureController; Loading Loading @@ -132,6 +162,22 @@ public class TabletopModeController implements } } /** * @return {@code true} if floating windows like PiP would auto move to the position * specified by {@link #getPreferredHalfInTabletopMode()} when in tabletop mode. */ public boolean enableMoveFloatingWindowInTabletop() { return ENABLE_MOVE_FLOATING_WINDOW_IN_TABLETOP; } /** @return Preferred half for floating windows like PiP when in tabletop mode. */ @PreferredTabletopHalf public int getPreferredHalfInTabletopMode() { return PREFER_TOP_HALF_IN_TABLETOP ? PREFERRED_TABLETOP_HALF_TOP : PREFERRED_TABLETOP_HALF_BOTTOM; } /** Register {@link OnTabletopModeChangedListener} to listen for tabletop mode change. */ public void registerOnTabletopModeChangedListener( @NonNull OnTabletopModeChangedListener listener) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +3 −1 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TabletopModeController; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.annotations.ShellBackgroundThread; Loading Loading @@ -353,6 +354,7 @@ public abstract class WMShellModule { TaskStackListenerImpl taskStackListener, PipParamsChangedForwarder pipParamsChangedForwarder, DisplayInsetsController displayInsetsController, TabletopModeController pipTabletopController, Optional<OneHandedController> oneHandedController, @ShellMainThread ShellExecutor mainExecutor) { return Optional.ofNullable(PipController.create( Loading @@ -362,7 +364,7 @@ public abstract class WMShellModule { pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, displayInsetsController, oneHandedController, mainExecutor)); pipTabletopController, oneHandedController, mainExecutor)); } @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java +22 −1 Original line number Diff line number Diff line Loading @@ -44,7 +44,9 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Consumer; Loading Loading @@ -115,6 +117,12 @@ public class PipBoundsState { * @see android.view.View#setPreferKeepClearRects */ private final Set<Rect> mUnrestrictedKeepClearAreas = new ArraySet<>(); /** * Additional to {@link #mUnrestrictedKeepClearAreas}, allow the caller to append named bounds * as unrestricted keep clear area. Values in this map would be appended to * {@link #getUnrestrictedKeepClearAreas()} and this is meant for internal usage only. */ private final Map<String, Rect> mNamedUnrestrictedKeepClearAreas = new HashMap<>(); private @Nullable Runnable mOnMinimalSizeChangeCallback; private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback; Loading Loading @@ -393,6 +401,16 @@ public class PipBoundsState { mUnrestrictedKeepClearAreas.addAll(unrestrictedAreas); } /** Add a named unrestricted keep clear area. */ public void addNamedUnrestrictedKeepClearArea(@NonNull String name, Rect unrestrictedArea) { mNamedUnrestrictedKeepClearAreas.put(name, unrestrictedArea); } /** Remove a named unrestricted keep clear area. */ public void removeNamedUnrestrictedKeepClearArea(@NonNull String name) { mNamedUnrestrictedKeepClearAreas.remove(name); } @NonNull public Set<Rect> getRestrictedKeepClearAreas() { return mRestrictedKeepClearAreas; Loading @@ -400,7 +418,10 @@ public class PipBoundsState { @NonNull public Set<Rect> getUnrestrictedKeepClearAreas() { return mUnrestrictedKeepClearAreas; if (mNamedUnrestrictedKeepClearAreas.isEmpty()) return mUnrestrictedKeepClearAreas; final Set<Rect> unrestrictedAreas = new ArraySet<>(mUnrestrictedKeepClearAreas); unrestrictedAreas.addAll(mNamedUnrestrictedKeepClearAreas.values()); return unrestrictedAreas; } /** Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +43 −1 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; import android.os.RemoteException; import android.os.SystemProperties; Loading Loading @@ -71,6 +72,7 @@ import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.common.TabletopModeController; import com.android.wm.shell.common.TaskStackListenerCallback; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.onehanded.OneHandedController; Loading Loading @@ -145,6 +147,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb private TaskStackListenerImpl mTaskStackListener; private PipParamsChangedForwarder mPipParamsChangedForwarder; private DisplayInsetsController mDisplayInsetsController; private TabletopModeController mTabletopModeController; private Optional<OneHandedController> mOneHandedController; private final ShellCommandHandler mShellCommandHandler; private final ShellController mShellController; Loading Loading @@ -400,6 +403,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb TaskStackListenerImpl taskStackListener, PipParamsChangedForwarder pipParamsChangedForwarder, DisplayInsetsController displayInsetsController, TabletopModeController pipTabletopController, Optional<OneHandedController> oneHandedController, ShellExecutor mainExecutor) { if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { Loading @@ -414,7 +418,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb pipMotionHelper, pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, displayInsetsController, oneHandedController, mainExecutor) displayInsetsController, pipTabletopController, oneHandedController, mainExecutor) .mImpl; } Loading @@ -440,6 +444,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb TaskStackListenerImpl taskStackListener, PipParamsChangedForwarder pipParamsChangedForwarder, DisplayInsetsController displayInsetsController, TabletopModeController tabletopModeController, Optional<OneHandedController> oneHandedController, ShellExecutor mainExecutor ) { Loading Loading @@ -472,6 +477,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb .getInteger(R.integer.config_pipEnterAnimationDuration); mPipParamsChangedForwarder = pipParamsChangedForwarder; mDisplayInsetsController = displayInsetsController; mTabletopModeController = tabletopModeController; shellInit.addInitCallback(this::onInit, this); } Loading Loading @@ -655,6 +661,42 @@ public class PipController implements PipTransitionController.PipTransitionCallb } }); mTabletopModeController.registerOnTabletopModeChangedListener((isInTabletopMode) -> { if (!mTabletopModeController.enableMoveFloatingWindowInTabletop()) return; final String tag = "tabletop-mode"; if (!isInTabletopMode) { mPipBoundsState.removeNamedUnrestrictedKeepClearArea(tag); return; } // To prepare for the entry bounds. final Rect displayBounds = mPipBoundsState.getDisplayBounds(); if (mTabletopModeController.getPreferredHalfInTabletopMode() == TabletopModeController.PREFERRED_TABLETOP_HALF_TOP) { // Prefer top, avoid the bottom half of the display. mPipBoundsState.addNamedUnrestrictedKeepClearArea(tag, new Rect( displayBounds.left, displayBounds.centerY(), displayBounds.right, displayBounds.bottom)); } else { // Prefer bottom, avoid the top half of the display. mPipBoundsState.addNamedUnrestrictedKeepClearArea(tag, new Rect( displayBounds.left, displayBounds.top, displayBounds.right, displayBounds.centerY())); } // Try to move the PiP window if we have entered PiP mode. if (mPipTransitionState.hasEnteredPip()) { final Rect pipBounds = mPipBoundsState.getBounds(); final Point edgeInsets = mPipSizeSpecHandler.getScreenEdgeInsets(); if ((pipBounds.height() + 2 * edgeInsets.y) > (displayBounds.height() / 2)) { // PiP bounds is too big to fit either half, bail early. return; } mMainExecutor.removeCallbacks(mMovePipInResponseToKeepClearAreasChangeCallback); mMainExecutor.execute(mMovePipInResponseToKeepClearAreasChangeCallback); } }); mOneHandedController.ifPresent(controller -> { controller.registerTransitionCallback( new OneHandedTransitionCallback() { Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java +4 −2 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TabletopModeController; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.onehanded.OneHandedController; import com.android.wm.shell.pip.PipAnimationController; Loading Loading @@ -113,6 +114,7 @@ public class PipControllerTest extends ShellTestCase { @Mock private Optional<OneHandedController> mMockOneHandedController; @Mock private PipParamsChangedForwarder mMockPipParamsChangedForwarder; @Mock private DisplayInsetsController mMockDisplayInsetsController; @Mock private TabletopModeController mMockTabletopModeController; @Mock private DisplayLayout mMockDisplayLayout1; @Mock private DisplayLayout mMockDisplayLayout2; Loading @@ -135,7 +137,7 @@ public class PipControllerTest extends ShellTestCase { mMockPipTransitionState, mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper, mMockTaskStackListener, mMockPipParamsChangedForwarder, mMockDisplayInsetsController, mMockOneHandedController, mMockExecutor); mMockTabletopModeController, mMockOneHandedController, mMockExecutor); mShellInit.init(); when(mMockPipBoundsAlgorithm.getSnapAlgorithm()).thenReturn(mMockPipSnapAlgorithm); when(mMockPipTouchHandler.getMotionHelper()).thenReturn(mMockPipMotionHelper); Loading Loading @@ -226,7 +228,7 @@ public class PipControllerTest extends ShellTestCase { mMockPipTransitionState, mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper, mMockTaskStackListener, mMockPipParamsChangedForwarder, mMockDisplayInsetsController, mMockOneHandedController, mMockExecutor)); mMockTabletopModeController, mMockOneHandedController, mMockExecutor)); } @Test Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/common/TabletopModeController.java +46 −0 Original line number Diff line number Diff line Loading @@ -22,10 +22,12 @@ import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_UNKNOWN; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_FOLDABLE; import android.annotation.IntDef; import android.annotation.NonNull; import android.app.WindowConfiguration; import android.content.Context; import android.content.res.Configuration; import android.os.SystemProperties; import android.util.ArraySet; import android.view.Surface; Loading @@ -34,6 +36,8 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.sysui.ShellInit; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Set; Loading @@ -49,8 +53,34 @@ import java.util.Set; public class TabletopModeController implements DevicePostureController.OnDevicePostureChangedListener, DisplayController.OnDisplaysChangedListener { /** * When {@code true}, floating windows like PiP would auto move to the position * specified by {@link #PREFER_TOP_HALF_IN_TABLETOP} when in tabletop mode. */ private static final boolean ENABLE_MOVE_FLOATING_WINDOW_IN_TABLETOP = SystemProperties.getBoolean( "persist.wm.debug.enable_move_floating_window_in_tabletop", false); /** * Prefer the {@link #PREFERRED_TABLETOP_HALF_TOP} if this flag is enabled, * {@link #PREFERRED_TABLETOP_HALF_BOTTOM} otherwise. * See also {@link #getPreferredHalfInTabletopMode()}. */ private static final boolean PREFER_TOP_HALF_IN_TABLETOP = SystemProperties.getBoolean("persist.wm.debug.prefer_top_half_in_tabletop", true); private static final long TABLETOP_MODE_DELAY_MILLIS = 1_000; @IntDef(prefix = {"PREFERRED_TABLETOP_HALF_"}, value = { PREFERRED_TABLETOP_HALF_TOP, PREFERRED_TABLETOP_HALF_BOTTOM }) @Retention(RetentionPolicy.SOURCE) public @interface PreferredTabletopHalf {} public static final int PREFERRED_TABLETOP_HALF_TOP = 0; public static final int PREFERRED_TABLETOP_HALF_BOTTOM = 1; private final Context mContext; private final DevicePostureController mDevicePostureController; Loading Loading @@ -132,6 +162,22 @@ public class TabletopModeController implements } } /** * @return {@code true} if floating windows like PiP would auto move to the position * specified by {@link #getPreferredHalfInTabletopMode()} when in tabletop mode. */ public boolean enableMoveFloatingWindowInTabletop() { return ENABLE_MOVE_FLOATING_WINDOW_IN_TABLETOP; } /** @return Preferred half for floating windows like PiP when in tabletop mode. */ @PreferredTabletopHalf public int getPreferredHalfInTabletopMode() { return PREFER_TOP_HALF_IN_TABLETOP ? PREFERRED_TABLETOP_HALF_TOP : PREFERRED_TABLETOP_HALF_BOTTOM; } /** Register {@link OnTabletopModeChangedListener} to listen for tabletop mode change. */ public void registerOnTabletopModeChangedListener( @NonNull OnTabletopModeChangedListener listener) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +3 −1 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TabletopModeController; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.annotations.ShellBackgroundThread; Loading Loading @@ -353,6 +354,7 @@ public abstract class WMShellModule { TaskStackListenerImpl taskStackListener, PipParamsChangedForwarder pipParamsChangedForwarder, DisplayInsetsController displayInsetsController, TabletopModeController pipTabletopController, Optional<OneHandedController> oneHandedController, @ShellMainThread ShellExecutor mainExecutor) { return Optional.ofNullable(PipController.create( Loading @@ -362,7 +364,7 @@ public abstract class WMShellModule { pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, displayInsetsController, oneHandedController, mainExecutor)); pipTabletopController, oneHandedController, mainExecutor)); } @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java +22 −1 Original line number Diff line number Diff line Loading @@ -44,7 +44,9 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Consumer; Loading Loading @@ -115,6 +117,12 @@ public class PipBoundsState { * @see android.view.View#setPreferKeepClearRects */ private final Set<Rect> mUnrestrictedKeepClearAreas = new ArraySet<>(); /** * Additional to {@link #mUnrestrictedKeepClearAreas}, allow the caller to append named bounds * as unrestricted keep clear area. Values in this map would be appended to * {@link #getUnrestrictedKeepClearAreas()} and this is meant for internal usage only. */ private final Map<String, Rect> mNamedUnrestrictedKeepClearAreas = new HashMap<>(); private @Nullable Runnable mOnMinimalSizeChangeCallback; private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback; Loading Loading @@ -393,6 +401,16 @@ public class PipBoundsState { mUnrestrictedKeepClearAreas.addAll(unrestrictedAreas); } /** Add a named unrestricted keep clear area. */ public void addNamedUnrestrictedKeepClearArea(@NonNull String name, Rect unrestrictedArea) { mNamedUnrestrictedKeepClearAreas.put(name, unrestrictedArea); } /** Remove a named unrestricted keep clear area. */ public void removeNamedUnrestrictedKeepClearArea(@NonNull String name) { mNamedUnrestrictedKeepClearAreas.remove(name); } @NonNull public Set<Rect> getRestrictedKeepClearAreas() { return mRestrictedKeepClearAreas; Loading @@ -400,7 +418,10 @@ public class PipBoundsState { @NonNull public Set<Rect> getUnrestrictedKeepClearAreas() { return mUnrestrictedKeepClearAreas; if (mNamedUnrestrictedKeepClearAreas.isEmpty()) return mUnrestrictedKeepClearAreas; final Set<Rect> unrestrictedAreas = new ArraySet<>(mUnrestrictedKeepClearAreas); unrestrictedAreas.addAll(mNamedUnrestrictedKeepClearAreas.values()); return unrestrictedAreas; } /** Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +43 −1 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; import android.os.RemoteException; import android.os.SystemProperties; Loading Loading @@ -71,6 +72,7 @@ import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.common.TabletopModeController; import com.android.wm.shell.common.TaskStackListenerCallback; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.onehanded.OneHandedController; Loading Loading @@ -145,6 +147,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb private TaskStackListenerImpl mTaskStackListener; private PipParamsChangedForwarder mPipParamsChangedForwarder; private DisplayInsetsController mDisplayInsetsController; private TabletopModeController mTabletopModeController; private Optional<OneHandedController> mOneHandedController; private final ShellCommandHandler mShellCommandHandler; private final ShellController mShellController; Loading Loading @@ -400,6 +403,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb TaskStackListenerImpl taskStackListener, PipParamsChangedForwarder pipParamsChangedForwarder, DisplayInsetsController displayInsetsController, TabletopModeController pipTabletopController, Optional<OneHandedController> oneHandedController, ShellExecutor mainExecutor) { if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { Loading @@ -414,7 +418,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb pipMotionHelper, pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, displayInsetsController, oneHandedController, mainExecutor) displayInsetsController, pipTabletopController, oneHandedController, mainExecutor) .mImpl; } Loading @@ -440,6 +444,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb TaskStackListenerImpl taskStackListener, PipParamsChangedForwarder pipParamsChangedForwarder, DisplayInsetsController displayInsetsController, TabletopModeController tabletopModeController, Optional<OneHandedController> oneHandedController, ShellExecutor mainExecutor ) { Loading Loading @@ -472,6 +477,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb .getInteger(R.integer.config_pipEnterAnimationDuration); mPipParamsChangedForwarder = pipParamsChangedForwarder; mDisplayInsetsController = displayInsetsController; mTabletopModeController = tabletopModeController; shellInit.addInitCallback(this::onInit, this); } Loading Loading @@ -655,6 +661,42 @@ public class PipController implements PipTransitionController.PipTransitionCallb } }); mTabletopModeController.registerOnTabletopModeChangedListener((isInTabletopMode) -> { if (!mTabletopModeController.enableMoveFloatingWindowInTabletop()) return; final String tag = "tabletop-mode"; if (!isInTabletopMode) { mPipBoundsState.removeNamedUnrestrictedKeepClearArea(tag); return; } // To prepare for the entry bounds. final Rect displayBounds = mPipBoundsState.getDisplayBounds(); if (mTabletopModeController.getPreferredHalfInTabletopMode() == TabletopModeController.PREFERRED_TABLETOP_HALF_TOP) { // Prefer top, avoid the bottom half of the display. mPipBoundsState.addNamedUnrestrictedKeepClearArea(tag, new Rect( displayBounds.left, displayBounds.centerY(), displayBounds.right, displayBounds.bottom)); } else { // Prefer bottom, avoid the top half of the display. mPipBoundsState.addNamedUnrestrictedKeepClearArea(tag, new Rect( displayBounds.left, displayBounds.top, displayBounds.right, displayBounds.centerY())); } // Try to move the PiP window if we have entered PiP mode. if (mPipTransitionState.hasEnteredPip()) { final Rect pipBounds = mPipBoundsState.getBounds(); final Point edgeInsets = mPipSizeSpecHandler.getScreenEdgeInsets(); if ((pipBounds.height() + 2 * edgeInsets.y) > (displayBounds.height() / 2)) { // PiP bounds is too big to fit either half, bail early. return; } mMainExecutor.removeCallbacks(mMovePipInResponseToKeepClearAreasChangeCallback); mMainExecutor.execute(mMovePipInResponseToKeepClearAreasChangeCallback); } }); mOneHandedController.ifPresent(controller -> { controller.registerTransitionCallback( new OneHandedTransitionCallback() { Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java +4 −2 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TabletopModeController; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.onehanded.OneHandedController; import com.android.wm.shell.pip.PipAnimationController; Loading Loading @@ -113,6 +114,7 @@ public class PipControllerTest extends ShellTestCase { @Mock private Optional<OneHandedController> mMockOneHandedController; @Mock private PipParamsChangedForwarder mMockPipParamsChangedForwarder; @Mock private DisplayInsetsController mMockDisplayInsetsController; @Mock private TabletopModeController mMockTabletopModeController; @Mock private DisplayLayout mMockDisplayLayout1; @Mock private DisplayLayout mMockDisplayLayout2; Loading @@ -135,7 +137,7 @@ public class PipControllerTest extends ShellTestCase { mMockPipTransitionState, mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper, mMockTaskStackListener, mMockPipParamsChangedForwarder, mMockDisplayInsetsController, mMockOneHandedController, mMockExecutor); mMockTabletopModeController, mMockOneHandedController, mMockExecutor); mShellInit.init(); when(mMockPipBoundsAlgorithm.getSnapAlgorithm()).thenReturn(mMockPipSnapAlgorithm); when(mMockPipTouchHandler.getMotionHelper()).thenReturn(mMockPipMotionHelper); Loading Loading @@ -226,7 +228,7 @@ public class PipControllerTest extends ShellTestCase { mMockPipTransitionState, mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper, mMockTaskStackListener, mMockPipParamsChangedForwarder, mMockDisplayInsetsController, mMockOneHandedController, mMockExecutor)); mMockTabletopModeController, mMockOneHandedController, mMockExecutor)); } @Test Loading