Loading libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java +47 −11 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.wm.shell; import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT; import com.android.wm.shell.apppairs.AppPairs; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; Loading Loading @@ -107,10 +109,14 @@ public final class ShellCommandHandlerImpl { return runPair(args, pw); case "unpair": return runUnpair(args, pw); case "pinTask": return runPinTask(args, pw); case "unpinTask": return runUnpinTask(args, pw); case "moveToSideStage": return runMoveToSideStage(args, pw); case "removeFromSideStage": return runRemoveFromSideStage(args, pw); case "setSideStagePosition": return runSetSideStagePosition(args, pw); case "setSideStageVisibility": return runSetSideStageVisibility(args, pw); case "help": return runHelp(pw); default: Loading Loading @@ -141,25 +147,50 @@ public final class ShellCommandHandlerImpl { return true; } private boolean runPinTask(String[] args, PrintWriter pw) { private boolean runMoveToSideStage(String[] args, PrintWriter pw) { if (args.length < 3) { // First arguments are "WMShell" and command name. pw.println("Error: task id should be provided as arguments"); return false; } final int taskId = new Integer(args[2]); mSplitScreenOptional.ifPresent(split -> split.pinTask(taskId)); final int sideStagePosition = args.length > 3 ? new Integer(args[3]) : SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT; mSplitScreenOptional.ifPresent(split -> split.moveToSideStage(taskId, sideStagePosition)); return true; } private boolean runUnpinTask(String[] args, PrintWriter pw) { private boolean runRemoveFromSideStage(String[] args, PrintWriter pw) { if (args.length < 3) { // First arguments are "WMShell" and command name. pw.println("Error: task id should be provided as arguments"); return false; } final int taskId = new Integer(args[2]); mSplitScreenOptional.ifPresent(split -> split.unpinTask(taskId)); mSplitScreenOptional.ifPresent(split -> split.removeFromSideStage(taskId)); return true; } private boolean runSetSideStagePosition(String[] args, PrintWriter pw) { if (args.length < 3) { // First arguments are "WMShell" and command name. pw.println("Error: side stage position should be provided as arguments"); return false; } final int position = new Integer(args[2]); mSplitScreenOptional.ifPresent(split -> split.setSideStagePosition(position)); return true; } private boolean runSetSideStageVisibility(String[] args, PrintWriter pw) { if (args.length < 3) { // First arguments are "WMShell" and command name. pw.println("Error: side stage position should be provided as arguments"); return false; } final Boolean visible = new Boolean(args[2]); mSplitScreenOptional.ifPresent(split -> split.setSideStageVisibility(visible)); return true; } Loading @@ -172,9 +203,14 @@ public final class ShellCommandHandlerImpl { pw.println(" pair <taskId1> <taskId2>"); pw.println(" unpair <taskId>"); pw.println(" Pairs/unpairs tasks with given ids."); pw.println(" pinTask <taskId>"); pw.println(" unpinTask <taskId>"); pw.println(" Pin/Unpin a task with given id in split-screen mode."); pw.println(" moveToSideStage <taskId> <SideStagePosition>"); pw.println(" Move a task with given id in split-screen mode."); pw.println(" removeFromSideStage <taskId>"); pw.println(" Remove a task with given id in split-screen mode."); pw.println(" setSideStagePosition <SideStagePosition>"); pw.println(" Sets the position of the side-stage."); pw.println(" setSideStageVisibility <true/false>"); pw.println(" Show/hide side-stage."); return true; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java +3 −3 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ class SideStage extends StageTaskListener { super(taskOrganizer, displayId, callbacks, syncQueue); } public void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds, void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds, WindowContainerTransaction wct) { final WindowContainerToken rootToken = mRootTaskInfo.token; wct.setHidden(rootToken, false) Loading @@ -48,13 +48,13 @@ class SideStage extends StageTaskListener { .reorder(rootToken, true); } public boolean removeTask(int taskId, WindowContainerTransaction wct) { boolean removeTask(int taskId, WindowContainerToken newParent, WindowContainerTransaction wct) { final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.get(taskId); if (task == null) return false; wct.setHidden(mRootTaskInfo.token, true) .reorder(mRootTaskInfo.token, false) .reparent(task.token, null, false /* onTop */); .reparent(task.token, newParent, false /* onTop */); return true; } } libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +32 −7 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.splitscreen; import android.annotation.IntDef; import android.app.ActivityManager; import androidx.annotation.NonNull; Loading @@ -29,13 +30,37 @@ import java.io.PrintWriter; */ @ExternalThread public interface SplitScreen { /** Unpin a task in the side-stage of split-screen. */ boolean pinTask(int taskId); /** Unpin a task in the side-stage of split-screen. */ boolean pinTask(ActivityManager.RunningTaskInfo task); /** Unpin a task from the side-stage of split-screen. */ boolean unpinTask(int taskId); // TODO: Do we need show/hide side stage or is startActivity and sendToBack good enough? /** * Specifies that the side-stage is positioned at the top half of the screen if * in portrait mode or at the left half of the screen if in landscape mode. */ int SIDE_STAGE_POSITION_TOP_OR_LEFT = 0; /** * Specifies that the side-stage is positioned at the bottom half of the screen if * in portrait mode or at the right half of the screen if in landscape mode. */ int SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT = 1; @IntDef(prefix = { "SIDE_STAGE_POSITION_" }, value = { SIDE_STAGE_POSITION_TOP_OR_LEFT, SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT }) @interface SideStagePosition {} /** @return {@code true} if split-screen is currently visible. */ boolean isSplitScreenVisible(); /** Moves a task in the side-stage of split-screen. */ boolean moveToSideStage(int taskId, @SideStagePosition int sideStagePosition); /** Moves a task in the side-stage of split-screen. */ boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SideStagePosition int sideStagePosition); /** Removes a task from the side-stage of split-screen. */ boolean removeFromSideStage(int taskId); /** Sets the position of the side-stage. */ void setSideStagePosition(@SideStagePosition int sideStagePosition); /** Hides the side-stage if it is currently visible. */ void setSideStageVisibility(boolean visible); /** Dumps current status of split-screen. */ void dump(@NonNull PrintWriter pw, String prefix); /** Called when the shell organizer has been registered. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +22 −6 Original line number Diff line number Diff line Loading @@ -62,19 +62,35 @@ public class SplitScreenController implements SplitScreen { } @Override public boolean pinTask(int taskId) { public boolean isSplitScreenVisible() { return mStageCoordinator.isSplitScreenVisible(); } @Override public boolean moveToSideStage(int taskId, @SideStagePosition int sideStagePosition) { final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); return task != null && pinTask(task); return task != null && moveToSideStage(task, sideStagePosition); } @Override public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SideStagePosition int sideStagePosition) { return mStageCoordinator.moveToSideStage(task, sideStagePosition); } @Override public boolean removeFromSideStage(int taskId) { return mStageCoordinator.removeFromSideStage(taskId); } @Override public boolean pinTask(ActivityManager.RunningTaskInfo task) { return mStageCoordinator.pinTask(task); public void setSideStagePosition(@SideStagePosition int sideStagePosition) { mStageCoordinator.setSideStagePosition(sideStagePosition); } @Override public boolean unpinTask(int taskId) { return mStageCoordinator.unpinTask(taskId); public void setSideStageVisibility(boolean visible) { mStageCoordinator.setSideStageVisibility(visible); } @Override Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +45 −14 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ package com.android.wm.shell.splitscreen; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_TOP_OR_LEFT; import android.app.ActivityManager; import android.content.Context; import android.graphics.Rect; Loading Loading @@ -58,6 +61,8 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, private final StageListenerImpl mMainStageListener = new StageListenerImpl(); private final SideStage mSideStage; private final StageListenerImpl mSideStageListener = new StageListenerImpl(); private @SplitScreen.SideStagePosition int mSideStagePosition = SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT; private final int mDisplayId; private SplitLayout mSplitLayout; Loading Loading @@ -94,27 +99,49 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, mRootTDAOrganizer.registerListener(displayId, this); } boolean pinTask(ActivityManager.RunningTaskInfo task) { final WindowContainerTransaction wct = new WindowContainerTransaction(); boolean isSplitScreenVisible() { return mSideStageListener.mVisible && mMainStageListener.mVisible; } boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitScreen.SideStagePosition int sideStagePosition) { final WindowContainerTransaction wct = new WindowContainerTransaction(); mSideStagePosition = sideStagePosition; mMainStage.activate(getMainStageBounds(), wct); mSideStage.addTask(task, getSideStageBounds(), wct); mTaskOrganizer.applyTransaction(wct); return true; } boolean unpinTask(int taskId) { boolean removeFromSideStage(int taskId) { final WindowContainerTransaction wct = new WindowContainerTransaction(); /** * {@link MainStage} will be deactivated in {@link #onStageHasChildrenChanged} if the * {@link SideStage} no longer has children. */ final boolean result = mSideStage.removeTask(taskId, wct); final boolean result = mSideStage.removeTask(taskId, mMainStage.isActive() ? mMainStage.mRootTaskInfo.token : null, wct); mTaskOrganizer.applyTransaction(wct); return result; } void setSideStagePosition(@SplitScreen.SideStagePosition int sideStagePosition) { mSideStagePosition = sideStagePosition; if (mSideStageListener.mVisible) { onStageVisibilityChanged(mSideStageListener); } } void setSideStageVisibility(boolean visible) { if (!mSideStageListener.mVisible == visible) return; final WindowContainerTransaction wct = new WindowContainerTransaction(); mSideStage.setVisibility(visible, wct); mTaskOrganizer.applyTransaction(wct); } private void onStageRootTaskVanished(StageListenerImpl stageListener) { if (stageListener == mMainStageListener || stageListener == mSideStageListener) { final WindowContainerTransaction wct = new WindowContainerTransaction(); Loading Loading @@ -171,6 +198,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, t.hide(dividerLeash); } } if (sideStageVisible) { final Rect sideStageBounds = getSideStageBounds(); t.show(sideStageLeash) Loading @@ -181,17 +209,18 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, } else { t.hide(sideStageLeash); } if (mainStageVisible) { final Rect mainStageBounds = getMainStageBounds(); t.show(mainStageLeash) .setPosition(mainStageLeash, mainStageBounds.left, mainStageBounds.top); t.show(mainStageLeash); if (sideStageVisible) { t.setWindowCrop(mainStageLeash, t.setPosition(mainStageLeash, mainStageBounds.left, mainStageBounds.top) .setWindowCrop(mainStageLeash, mainStageBounds.width(), mainStageBounds.height()); } else { // Clear window crop if side stage isn't visible. t.setWindowCrop(mainStageLeash, null); // Clear window crop and position if side stage isn't visible. t.setPosition(mainStageLeash, 0, 0) .setWindowCrop(mainStageLeash, null); } } else { t.hide(mainStageLeash); Loading @@ -204,7 +233,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, final WindowContainerTransaction wct = new WindowContainerTransaction(); if (mSideStageListener.mHasChildren) { // Make sure the main stage is active. mMainStage.activate(mSplitLayout.getBounds1(), wct); mMainStage.activate(getMainStageBounds(), wct); } else { // The side stage no long has children so we can deactivate the main stage. mMainStage.deactivate(wct); Loading Loading @@ -291,11 +320,13 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, } private Rect getSideStageBounds() { return mSplitLayout.getBounds2(); return mSideStagePosition == SIDE_STAGE_POSITION_TOP_OR_LEFT ? mSplitLayout.getBounds1() : mSplitLayout.getBounds2(); } private Rect getMainStageBounds() { return mSplitLayout.getBounds1(); return mSideStagePosition == SIDE_STAGE_POSITION_TOP_OR_LEFT ? mSplitLayout.getBounds2() : mSplitLayout.getBounds1(); } @Override Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java +47 −11 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.wm.shell; import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT; import com.android.wm.shell.apppairs.AppPairs; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; Loading Loading @@ -107,10 +109,14 @@ public final class ShellCommandHandlerImpl { return runPair(args, pw); case "unpair": return runUnpair(args, pw); case "pinTask": return runPinTask(args, pw); case "unpinTask": return runUnpinTask(args, pw); case "moveToSideStage": return runMoveToSideStage(args, pw); case "removeFromSideStage": return runRemoveFromSideStage(args, pw); case "setSideStagePosition": return runSetSideStagePosition(args, pw); case "setSideStageVisibility": return runSetSideStageVisibility(args, pw); case "help": return runHelp(pw); default: Loading Loading @@ -141,25 +147,50 @@ public final class ShellCommandHandlerImpl { return true; } private boolean runPinTask(String[] args, PrintWriter pw) { private boolean runMoveToSideStage(String[] args, PrintWriter pw) { if (args.length < 3) { // First arguments are "WMShell" and command name. pw.println("Error: task id should be provided as arguments"); return false; } final int taskId = new Integer(args[2]); mSplitScreenOptional.ifPresent(split -> split.pinTask(taskId)); final int sideStagePosition = args.length > 3 ? new Integer(args[3]) : SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT; mSplitScreenOptional.ifPresent(split -> split.moveToSideStage(taskId, sideStagePosition)); return true; } private boolean runUnpinTask(String[] args, PrintWriter pw) { private boolean runRemoveFromSideStage(String[] args, PrintWriter pw) { if (args.length < 3) { // First arguments are "WMShell" and command name. pw.println("Error: task id should be provided as arguments"); return false; } final int taskId = new Integer(args[2]); mSplitScreenOptional.ifPresent(split -> split.unpinTask(taskId)); mSplitScreenOptional.ifPresent(split -> split.removeFromSideStage(taskId)); return true; } private boolean runSetSideStagePosition(String[] args, PrintWriter pw) { if (args.length < 3) { // First arguments are "WMShell" and command name. pw.println("Error: side stage position should be provided as arguments"); return false; } final int position = new Integer(args[2]); mSplitScreenOptional.ifPresent(split -> split.setSideStagePosition(position)); return true; } private boolean runSetSideStageVisibility(String[] args, PrintWriter pw) { if (args.length < 3) { // First arguments are "WMShell" and command name. pw.println("Error: side stage position should be provided as arguments"); return false; } final Boolean visible = new Boolean(args[2]); mSplitScreenOptional.ifPresent(split -> split.setSideStageVisibility(visible)); return true; } Loading @@ -172,9 +203,14 @@ public final class ShellCommandHandlerImpl { pw.println(" pair <taskId1> <taskId2>"); pw.println(" unpair <taskId>"); pw.println(" Pairs/unpairs tasks with given ids."); pw.println(" pinTask <taskId>"); pw.println(" unpinTask <taskId>"); pw.println(" Pin/Unpin a task with given id in split-screen mode."); pw.println(" moveToSideStage <taskId> <SideStagePosition>"); pw.println(" Move a task with given id in split-screen mode."); pw.println(" removeFromSideStage <taskId>"); pw.println(" Remove a task with given id in split-screen mode."); pw.println(" setSideStagePosition <SideStagePosition>"); pw.println(" Sets the position of the side-stage."); pw.println(" setSideStageVisibility <true/false>"); pw.println(" Show/hide side-stage."); return true; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java +3 −3 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ class SideStage extends StageTaskListener { super(taskOrganizer, displayId, callbacks, syncQueue); } public void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds, void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds, WindowContainerTransaction wct) { final WindowContainerToken rootToken = mRootTaskInfo.token; wct.setHidden(rootToken, false) Loading @@ -48,13 +48,13 @@ class SideStage extends StageTaskListener { .reorder(rootToken, true); } public boolean removeTask(int taskId, WindowContainerTransaction wct) { boolean removeTask(int taskId, WindowContainerToken newParent, WindowContainerTransaction wct) { final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.get(taskId); if (task == null) return false; wct.setHidden(mRootTaskInfo.token, true) .reorder(mRootTaskInfo.token, false) .reparent(task.token, null, false /* onTop */); .reparent(task.token, newParent, false /* onTop */); return true; } }
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +32 −7 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.splitscreen; import android.annotation.IntDef; import android.app.ActivityManager; import androidx.annotation.NonNull; Loading @@ -29,13 +30,37 @@ import java.io.PrintWriter; */ @ExternalThread public interface SplitScreen { /** Unpin a task in the side-stage of split-screen. */ boolean pinTask(int taskId); /** Unpin a task in the side-stage of split-screen. */ boolean pinTask(ActivityManager.RunningTaskInfo task); /** Unpin a task from the side-stage of split-screen. */ boolean unpinTask(int taskId); // TODO: Do we need show/hide side stage or is startActivity and sendToBack good enough? /** * Specifies that the side-stage is positioned at the top half of the screen if * in portrait mode or at the left half of the screen if in landscape mode. */ int SIDE_STAGE_POSITION_TOP_OR_LEFT = 0; /** * Specifies that the side-stage is positioned at the bottom half of the screen if * in portrait mode or at the right half of the screen if in landscape mode. */ int SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT = 1; @IntDef(prefix = { "SIDE_STAGE_POSITION_" }, value = { SIDE_STAGE_POSITION_TOP_OR_LEFT, SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT }) @interface SideStagePosition {} /** @return {@code true} if split-screen is currently visible. */ boolean isSplitScreenVisible(); /** Moves a task in the side-stage of split-screen. */ boolean moveToSideStage(int taskId, @SideStagePosition int sideStagePosition); /** Moves a task in the side-stage of split-screen. */ boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SideStagePosition int sideStagePosition); /** Removes a task from the side-stage of split-screen. */ boolean removeFromSideStage(int taskId); /** Sets the position of the side-stage. */ void setSideStagePosition(@SideStagePosition int sideStagePosition); /** Hides the side-stage if it is currently visible. */ void setSideStageVisibility(boolean visible); /** Dumps current status of split-screen. */ void dump(@NonNull PrintWriter pw, String prefix); /** Called when the shell organizer has been registered. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +22 −6 Original line number Diff line number Diff line Loading @@ -62,19 +62,35 @@ public class SplitScreenController implements SplitScreen { } @Override public boolean pinTask(int taskId) { public boolean isSplitScreenVisible() { return mStageCoordinator.isSplitScreenVisible(); } @Override public boolean moveToSideStage(int taskId, @SideStagePosition int sideStagePosition) { final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); return task != null && pinTask(task); return task != null && moveToSideStage(task, sideStagePosition); } @Override public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SideStagePosition int sideStagePosition) { return mStageCoordinator.moveToSideStage(task, sideStagePosition); } @Override public boolean removeFromSideStage(int taskId) { return mStageCoordinator.removeFromSideStage(taskId); } @Override public boolean pinTask(ActivityManager.RunningTaskInfo task) { return mStageCoordinator.pinTask(task); public void setSideStagePosition(@SideStagePosition int sideStagePosition) { mStageCoordinator.setSideStagePosition(sideStagePosition); } @Override public boolean unpinTask(int taskId) { return mStageCoordinator.unpinTask(taskId); public void setSideStageVisibility(boolean visible) { mStageCoordinator.setSideStageVisibility(visible); } @Override Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +45 −14 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ package com.android.wm.shell.splitscreen; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_TOP_OR_LEFT; import android.app.ActivityManager; import android.content.Context; import android.graphics.Rect; Loading Loading @@ -58,6 +61,8 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, private final StageListenerImpl mMainStageListener = new StageListenerImpl(); private final SideStage mSideStage; private final StageListenerImpl mSideStageListener = new StageListenerImpl(); private @SplitScreen.SideStagePosition int mSideStagePosition = SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT; private final int mDisplayId; private SplitLayout mSplitLayout; Loading Loading @@ -94,27 +99,49 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, mRootTDAOrganizer.registerListener(displayId, this); } boolean pinTask(ActivityManager.RunningTaskInfo task) { final WindowContainerTransaction wct = new WindowContainerTransaction(); boolean isSplitScreenVisible() { return mSideStageListener.mVisible && mMainStageListener.mVisible; } boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitScreen.SideStagePosition int sideStagePosition) { final WindowContainerTransaction wct = new WindowContainerTransaction(); mSideStagePosition = sideStagePosition; mMainStage.activate(getMainStageBounds(), wct); mSideStage.addTask(task, getSideStageBounds(), wct); mTaskOrganizer.applyTransaction(wct); return true; } boolean unpinTask(int taskId) { boolean removeFromSideStage(int taskId) { final WindowContainerTransaction wct = new WindowContainerTransaction(); /** * {@link MainStage} will be deactivated in {@link #onStageHasChildrenChanged} if the * {@link SideStage} no longer has children. */ final boolean result = mSideStage.removeTask(taskId, wct); final boolean result = mSideStage.removeTask(taskId, mMainStage.isActive() ? mMainStage.mRootTaskInfo.token : null, wct); mTaskOrganizer.applyTransaction(wct); return result; } void setSideStagePosition(@SplitScreen.SideStagePosition int sideStagePosition) { mSideStagePosition = sideStagePosition; if (mSideStageListener.mVisible) { onStageVisibilityChanged(mSideStageListener); } } void setSideStageVisibility(boolean visible) { if (!mSideStageListener.mVisible == visible) return; final WindowContainerTransaction wct = new WindowContainerTransaction(); mSideStage.setVisibility(visible, wct); mTaskOrganizer.applyTransaction(wct); } private void onStageRootTaskVanished(StageListenerImpl stageListener) { if (stageListener == mMainStageListener || stageListener == mSideStageListener) { final WindowContainerTransaction wct = new WindowContainerTransaction(); Loading Loading @@ -171,6 +198,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, t.hide(dividerLeash); } } if (sideStageVisible) { final Rect sideStageBounds = getSideStageBounds(); t.show(sideStageLeash) Loading @@ -181,17 +209,18 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, } else { t.hide(sideStageLeash); } if (mainStageVisible) { final Rect mainStageBounds = getMainStageBounds(); t.show(mainStageLeash) .setPosition(mainStageLeash, mainStageBounds.left, mainStageBounds.top); t.show(mainStageLeash); if (sideStageVisible) { t.setWindowCrop(mainStageLeash, t.setPosition(mainStageLeash, mainStageBounds.left, mainStageBounds.top) .setWindowCrop(mainStageLeash, mainStageBounds.width(), mainStageBounds.height()); } else { // Clear window crop if side stage isn't visible. t.setWindowCrop(mainStageLeash, null); // Clear window crop and position if side stage isn't visible. t.setPosition(mainStageLeash, 0, 0) .setWindowCrop(mainStageLeash, null); } } else { t.hide(mainStageLeash); Loading @@ -204,7 +233,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, final WindowContainerTransaction wct = new WindowContainerTransaction(); if (mSideStageListener.mHasChildren) { // Make sure the main stage is active. mMainStage.activate(mSplitLayout.getBounds1(), wct); mMainStage.activate(getMainStageBounds(), wct); } else { // The side stage no long has children so we can deactivate the main stage. mMainStage.deactivate(wct); Loading Loading @@ -291,11 +320,13 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener, } private Rect getSideStageBounds() { return mSplitLayout.getBounds2(); return mSideStagePosition == SIDE_STAGE_POSITION_TOP_OR_LEFT ? mSplitLayout.getBounds1() : mSplitLayout.getBounds2(); } private Rect getMainStageBounds() { return mSplitLayout.getBounds1(); return mSideStagePosition == SIDE_STAGE_POSITION_TOP_OR_LEFT ? mSplitLayout.getBounds2() : mSplitLayout.getBounds1(); } @Override Loading