Merge "Fix flicker when task move to back" into sc-v2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d2f034f1d5
@@ -18,8 +18,6 @@ package com.android.wm.shell.splitscreen;
|
|||||||
|
|
||||||
import static android.app.ActivityOptions.KEY_LAUNCH_ROOT_TASK_TOKEN;
|
import static android.app.ActivityOptions.KEY_LAUNCH_ROOT_TASK_TOKEN;
|
||||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
|
||||||
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
|
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
|
||||||
import static android.view.WindowManager.TRANSIT_OPEN;
|
import static android.view.WindowManager.TRANSIT_OPEN;
|
||||||
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
||||||
@@ -515,7 +513,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
|||||||
mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
|
mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
|
||||||
mMainStage.deactivate(wct, childrenToTop == mMainStage);
|
mMainStage.deactivate(wct, childrenToTop == mMainStage);
|
||||||
mTaskOrganizer.applyTransaction(wct);
|
mTaskOrganizer.applyTransaction(wct);
|
||||||
// Reset divider position.
|
// Hide divider and reset its position.
|
||||||
|
setDividerVisibility(false);
|
||||||
mSplitLayout.resetDividerPosition();
|
mSplitLayout.resetDividerPosition();
|
||||||
mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
|
mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
|
||||||
if (childrenToTop != null) {
|
if (childrenToTop != null) {
|
||||||
@@ -649,10 +648,15 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
|||||||
private void onStageVisibilityChanged(StageListenerImpl stageListener) {
|
private void onStageVisibilityChanged(StageListenerImpl stageListener) {
|
||||||
final boolean sideStageVisible = mSideStageListener.mVisible;
|
final boolean sideStageVisible = mSideStageListener.mVisible;
|
||||||
final boolean mainStageVisible = mMainStageListener.mVisible;
|
final boolean mainStageVisible = mMainStageListener.mVisible;
|
||||||
// Divider is only visible if both the main stage and side stages are visible
|
final boolean bothStageVisible = sideStageVisible && mainStageVisible;
|
||||||
setDividerVisibility(isSplitScreenVisible());
|
final boolean sameVisibility = sideStageVisible == mainStageVisible;
|
||||||
|
// Only add or remove divider when both visible or both invisible to avoid sometimes we only
|
||||||
|
// got one stage visibility changed for a moment and it will cause flicker.
|
||||||
|
if (sameVisibility) {
|
||||||
|
setDividerVisibility(bothStageVisible);
|
||||||
|
}
|
||||||
|
|
||||||
if (!mainStageVisible && !sideStageVisible) {
|
if (!bothStageVisible) {
|
||||||
if (mExitSplitScreenOnHide
|
if (mExitSplitScreenOnHide
|
||||||
// Don't dismiss staged split when both stages are not visible due to sleeping display,
|
// Don't dismiss staged split when both stages are not visible due to sleeping display,
|
||||||
// like the cases keyguard showing or screen off.
|
// like the cases keyguard showing or screen off.
|
||||||
@@ -669,59 +673,32 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
|||||||
exitSplitScreen(toTop, SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP);
|
exitSplitScreen(toTop, SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When both stage's visibility changed to visible, main stage might receives visibility
|
|
||||||
// changed before side stage if it has higher z-order than side stage. Make sure we only
|
|
||||||
// update main stage's windowing mode with the visibility changed of side stage to prevent
|
|
||||||
// stacking multiple windowing mode transactions which result to flicker issue.
|
|
||||||
if (mainStageVisible && stageListener == mSideStageListener) {
|
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
|
||||||
if (sideStageVisible) {
|
|
||||||
// The main stage configuration should to follow split layout when side stage is
|
|
||||||
// visible.
|
|
||||||
mMainStage.updateConfiguration(
|
|
||||||
WINDOWING_MODE_MULTI_WINDOW, getMainStageBounds(), wct);
|
|
||||||
} else if (!mSideStage.mRootTaskInfo.isSleeping) {
|
|
||||||
// We want the main stage configuration to be fullscreen when the side stage isn't
|
|
||||||
// visible.
|
|
||||||
// We should not do it when side stage are not visible due to sleeping display too.
|
|
||||||
mMainStage.updateConfiguration(WINDOWING_MODE_FULLSCREEN, null, wct);
|
|
||||||
}
|
|
||||||
// TODO: Change to `mSyncQueue.queue(wct)` once BLAST is stable.
|
|
||||||
mTaskOrganizer.applyTransaction(wct);
|
|
||||||
}
|
|
||||||
|
|
||||||
mSyncQueue.runInSync(t -> {
|
mSyncQueue.runInSync(t -> {
|
||||||
final SurfaceControl sideStageLeash = mSideStage.mRootLeash;
|
final SurfaceControl sideStageLeash = mSideStage.mRootLeash;
|
||||||
final SurfaceControl mainStageLeash = mMainStage.mRootLeash;
|
final SurfaceControl mainStageLeash = mMainStage.mRootLeash;
|
||||||
|
|
||||||
if (sideStageVisible) {
|
if (sideStageVisible) {
|
||||||
final Rect sideStageBounds = getSideStageBounds();
|
final Rect sideStageBounds = getSideStageBounds();
|
||||||
t.show(sideStageLeash)
|
t.setPosition(sideStageLeash,
|
||||||
.setPosition(sideStageLeash,
|
|
||||||
sideStageBounds.left, sideStageBounds.top)
|
sideStageBounds.left, sideStageBounds.top)
|
||||||
.setWindowCrop(sideStageLeash,
|
.setWindowCrop(sideStageLeash,
|
||||||
sideStageBounds.width(), sideStageBounds.height());
|
sideStageBounds.width(), sideStageBounds.height());
|
||||||
} else {
|
|
||||||
t.hide(sideStageLeash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mainStageVisible) {
|
if (mainStageVisible) {
|
||||||
final Rect mainStageBounds = getMainStageBounds();
|
final Rect mainStageBounds = getMainStageBounds();
|
||||||
t.show(mainStageLeash);
|
|
||||||
if (sideStageVisible) {
|
|
||||||
t.setPosition(mainStageLeash, mainStageBounds.left, mainStageBounds.top)
|
t.setPosition(mainStageLeash, mainStageBounds.left, mainStageBounds.top)
|
||||||
.setWindowCrop(mainStageLeash,
|
.setWindowCrop(mainStageLeash,
|
||||||
mainStageBounds.width(), mainStageBounds.height());
|
mainStageBounds.width(), mainStageBounds.height());
|
||||||
} else {
|
|
||||||
// Clear window crop and position if side stage isn't visible.
|
|
||||||
t.setPosition(mainStageLeash, 0, 0)
|
|
||||||
.setWindowCrop(mainStageLeash, null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.hide(mainStageLeash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same above, we only set root tasks and divider leash visibility when both stage
|
||||||
|
// change to visible or invisible to avoid flicker.
|
||||||
|
if (sameVisibility) {
|
||||||
|
t.setVisibility(sideStageLeash, bothStageVisible)
|
||||||
|
.setVisibility(mainStageLeash, bothStageVisible);
|
||||||
applyDividerVisibility(t);
|
applyDividerVisibility(t);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user