Merge "Let top-fullscreen-app window keep controlling status bar" into rvc-dev
This commit is contained in:
@@ -2756,19 +2756,22 @@ public class DisplayPolicy {
|
|||||||
* @return Whether the top app should hide the statusbar based on the top fullscreen opaque
|
* @return Whether the top app should hide the statusbar based on the top fullscreen opaque
|
||||||
* window.
|
* window.
|
||||||
*/
|
*/
|
||||||
private boolean topAppHidesStatusBar() {
|
boolean topAppHidesStatusBar() {
|
||||||
if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
|
if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final int fl = PolicyControl.getWindowFlags(null,
|
final LayoutParams attrs = mTopFullscreenOpaqueWindowState.getAttrs();
|
||||||
mTopFullscreenOpaqueWindowState.getAttrs());
|
final int fl = PolicyControl.getWindowFlags(null, attrs);
|
||||||
|
final int sysui = PolicyControl.getSystemUiVisibility(null, attrs);
|
||||||
|
final InsetsSource request = mTopFullscreenOpaqueWindowState.getRequestedInsetsState()
|
||||||
|
.peekSource(ITYPE_STATUS_BAR);
|
||||||
if (WindowManagerDebugConfig.DEBUG) {
|
if (WindowManagerDebugConfig.DEBUG) {
|
||||||
Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw());
|
Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw());
|
||||||
Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
|
Slog.d(TAG, "attr: " + attrs + " request: " + request);
|
||||||
+ " lp.flags=0x" + Integer.toHexString(fl));
|
|
||||||
}
|
}
|
||||||
return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
|
return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
|
||||||
|| (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
|
|| (sysui & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0
|
||||||
|
|| (request != null && !request.isVisible());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -117,13 +117,8 @@ class InsetsPolicy {
|
|||||||
if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
|
if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mStatusBar.setVisible(focusedWin == null
|
mStatusBar.updateVisibility(getStatusControlTarget(focusedWin), ITYPE_STATUS_BAR);
|
||||||
|| focusedWin != getStatusControlTarget(focusedWin)
|
mNavBar.updateVisibility(getNavControlTarget(focusedWin), ITYPE_NAVIGATION_BAR);
|
||||||
|| focusedWin.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
|
|
||||||
mNavBar.setVisible(focusedWin == null
|
|
||||||
|| focusedWin != getNavControlTarget(focusedWin)
|
|
||||||
|| focusedWin.getRequestedInsetsState().getSource(ITYPE_NAVIGATION_BAR)
|
|
||||||
.isVisible());
|
|
||||||
mPolicy.updateHideNavInputEventReceiver();
|
mPolicy.updateHideNavInputEventReceiver();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,16 +210,7 @@ class InsetsPolicy {
|
|||||||
void onInsetsModified(WindowState windowState, InsetsState state) {
|
void onInsetsModified(WindowState windowState, InsetsState state) {
|
||||||
mStateController.onInsetsModified(windowState, state);
|
mStateController.onInsetsModified(windowState, state);
|
||||||
checkAbortTransient(windowState, state);
|
checkAbortTransient(windowState, state);
|
||||||
if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
|
updateBarControlTarget(mFocusedWin);
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (windowState == getStatusControlTarget(mFocusedWin)) {
|
|
||||||
mStatusBar.setVisible(state.getSource(ITYPE_STATUS_BAR).isVisible());
|
|
||||||
}
|
|
||||||
if (windowState == getNavControlTarget(mFocusedWin)) {
|
|
||||||
mNavBar.setVisible(state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
|
|
||||||
}
|
|
||||||
mPolicy.updateHideNavInputEventReceiver();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -248,7 +234,6 @@ class InsetsPolicy {
|
|||||||
if (abortTypes.size() > 0) {
|
if (abortTypes.size() > 0) {
|
||||||
mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(),
|
mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(),
|
||||||
abortTypes.toArray());
|
abortTypes.toArray());
|
||||||
updateBarControlTarget(mFocusedWin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,6 +274,11 @@ class InsetsPolicy {
|
|||||||
// fake control to the client, so that it can re-show the bar during this scenario.
|
// fake control to the client, so that it can re-show the bar during this scenario.
|
||||||
return mDummyControlTarget;
|
return mDummyControlTarget;
|
||||||
}
|
}
|
||||||
|
if (mPolicy.topAppHidesStatusBar()) {
|
||||||
|
// Non-fullscreen focused window should not break the state that the top-fullscreen-app
|
||||||
|
// window hides status bar.
|
||||||
|
return mPolicy.getTopFullscreenOpaqueWindow();
|
||||||
|
}
|
||||||
return focusedWin;
|
return focusedWin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,6 +368,14 @@ class InsetsPolicy {
|
|||||||
mId = id;
|
mId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateVisibility(InsetsControlTarget controlTarget,
|
||||||
|
@InternalInsetsType int type) {
|
||||||
|
final WindowState controllingWin =
|
||||||
|
controlTarget instanceof WindowState ? (WindowState) controlTarget : null;
|
||||||
|
setVisible(controllingWin == null
|
||||||
|
|| controllingWin.getRequestedInsetsState().getSource(type).isVisible());
|
||||||
|
}
|
||||||
|
|
||||||
private void setVisible(boolean visible) {
|
private void setVisible(boolean visible) {
|
||||||
final int state = visible ? WINDOW_STATE_SHOWING : WINDOW_STATE_HIDDEN;
|
final int state = visible ? WINDOW_STATE_SHOWING : WINDOW_STATE_HIDDEN;
|
||||||
if (mState != state) {
|
if (mState != state) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
|||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||||
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||||
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||||
|
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||||
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
|
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
|
||||||
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
|
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
|
||||||
@@ -182,6 +183,47 @@ public class InsetsPolicyTest extends WindowTestsBase {
|
|||||||
assertNull(controls);
|
assertNull(controls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testControlsForDispatch_topAppHidesStatusBar() {
|
||||||
|
addWindow(TYPE_STATUS_BAR, "statusBar");
|
||||||
|
addWindow(TYPE_NAVIGATION_BAR, "navBar");
|
||||||
|
|
||||||
|
// Add a fullscreen (MATCH_PARENT x MATCH_PARENT) app window which hides status bar.
|
||||||
|
final WindowState fullscreenApp = addWindow(TYPE_APPLICATION, "fullscreenApp");
|
||||||
|
final InsetsState requestedState = new InsetsState();
|
||||||
|
requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
|
||||||
|
fullscreenApp.updateRequestedInsetsState(requestedState);
|
||||||
|
|
||||||
|
// Add a non-fullscreen dialog window.
|
||||||
|
final WindowState dialog = addWindow(TYPE_APPLICATION, "dialog");
|
||||||
|
dialog.mAttrs.width = WRAP_CONTENT;
|
||||||
|
dialog.mAttrs.height = WRAP_CONTENT;
|
||||||
|
|
||||||
|
// Let fullscreenApp be mTopFullscreenOpaqueWindowState.
|
||||||
|
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
|
||||||
|
displayPolicy.beginPostLayoutPolicyLw();
|
||||||
|
displayPolicy.applyPostLayoutPolicyLw(dialog, dialog.mAttrs, fullscreenApp, null);
|
||||||
|
displayPolicy.applyPostLayoutPolicyLw(fullscreenApp, fullscreenApp.mAttrs, null, null);
|
||||||
|
displayPolicy.finishPostLayoutPolicyLw();
|
||||||
|
mDisplayContent.getInsetsPolicy().updateBarControlTarget(dialog);
|
||||||
|
|
||||||
|
assertEquals(fullscreenApp, displayPolicy.getTopFullscreenOpaqueWindow());
|
||||||
|
|
||||||
|
// dialog is the focused window, but it can only control navigation bar.
|
||||||
|
final InsetsSourceControl[] dialogControls =
|
||||||
|
mDisplayContent.getInsetsStateController().getControlsForDispatch(dialog);
|
||||||
|
assertNotNull(dialogControls);
|
||||||
|
assertEquals(1, dialogControls.length);
|
||||||
|
assertEquals(ITYPE_NAVIGATION_BAR, dialogControls[0].getType());
|
||||||
|
|
||||||
|
// fullscreenApp is hiding status bar, and it can keep controlling status bar.
|
||||||
|
final InsetsSourceControl[] fullscreenAppControls =
|
||||||
|
mDisplayContent.getInsetsStateController().getControlsForDispatch(fullscreenApp);
|
||||||
|
assertNotNull(fullscreenAppControls);
|
||||||
|
assertEquals(1, fullscreenAppControls.length);
|
||||||
|
assertEquals(ITYPE_STATUS_BAR, fullscreenAppControls[0].getType());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
|
public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
|
||||||
addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
|
addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
|
||||||
|
|||||||
Reference in New Issue
Block a user