Loading libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt +27 −1 Original line number Diff line number Diff line Loading @@ -18,9 +18,12 @@ package com.android.wm.shell.shared.desktopmode import android.app.TaskInfo import android.content.Context import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED import android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION import android.window.DesktopModeFlags import com.android.internal.R import java.util.ArrayList import com.android.window.flags.Flags /** * Class to decide whether to apply app compat policies in desktop mode. Loading Loading @@ -50,6 +53,21 @@ class DesktopModeCompatPolicy(private val context: Context) { || isTransparentTask(isActivityStackTransparent, numActivities)) && !isTopActivityNoDisplay) /** * Whether the caption insets should be excluded from configuration for system to handle. * * The treatment is enabled when all the of the following is true: * * Any flags to forcibly consume caption insets are enabled. * * Top activity have configuration coupled with insets. * * Task is not resizeable. */ fun shouldExcludeCaptionFromAppBounds(taskInfo: TaskInfo): Boolean = Flags.excludeCaptionFromAppBounds() && isAnyForceConsumptionFlagsEnabled() && taskInfo.topActivityInfo?.let { isInsetsCoupledWithConfiguration(it) && !taskInfo.isResizeable } ?: false /** * Returns true if all activities in a tasks stack are transparent. If there are no activities * will return false. Loading @@ -67,4 +85,12 @@ class DesktopModeCompatPolicy(private val context: Context) { */ private fun isPartOfDefaultHomePackage(packageName: String?) = packageName != null && packageName == defaultHomePackage private fun isAnyForceConsumptionFlagsEnabled(): Boolean = DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isTrue || DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isTrue private fun isInsetsCoupledWithConfiguration(info: ActivityInfo): Boolean = !(info.isChangeEnabled(OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION) || info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)) } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt +35 −6 Original line number Diff line number Diff line Loading @@ -18,8 +18,10 @@ package com.android.wm.shell.desktopmode import android.annotation.DimenRes import android.app.ActivityManager.RunningTaskInfo import android.app.TaskInfo import android.content.Context import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED import android.content.pm.ActivityInfo.isFixedOrientationLandscape import android.content.pm.ActivityInfo.isFixedOrientationPortrait Loading @@ -28,6 +30,7 @@ import android.content.res.Configuration.ORIENTATION_PORTRAIT import android.graphics.Rect import android.os.SystemProperties import android.util.Size import com.android.wm.shell.R import com.android.wm.shell.common.DisplayController import com.android.wm.shell.common.DisplayLayout Loading @@ -53,10 +56,12 @@ fun calculateDefaultDesktopTaskBounds(displayLayout: DisplayLayout): Rect { * aspect ratio, orientation and resizability to calculate an area this is compatible with the * applications previous configuration. */ @JvmOverloads fun calculateInitialBounds( displayLayout: DisplayLayout, taskInfo: RunningTaskInfo, scale: Float = DESKTOP_MODE_INITIAL_BOUNDS_SCALE, captionInsets: Int = 0, ): Rect { val screenBounds = Rect(0, 0, displayLayout.width(), displayLayout.height()) val appAspectRatio = calculateAspectRatio(taskInfo) Loading Loading @@ -92,7 +97,7 @@ fun calculateInitialBounds( } else { // If activity is unresizeable, regardless of orientation, calculate maximum // size (within the ideal size) maintaining original aspect ratio. maximizeSizeGivenAspectRatio(taskInfo, idealSize, appAspectRatio) maximizeSizeGivenAspectRatio(taskInfo, idealSize, appAspectRatio, captionInsets) } } ORIENTATION_PORTRAIT -> { Loading @@ -119,11 +124,17 @@ fun calculateInitialBounds( taskInfo, Size(customPortraitWidthForLandscapeApp, idealSize.height), appAspectRatio, captionInsets, ) } else { // For portrait unresizeable activities, calculate maximum size (within the // ideal size) maintaining original aspect ratio. maximizeSizeGivenAspectRatio(taskInfo, idealSize, appAspectRatio) maximizeSizeGivenAspectRatio( taskInfo, idealSize, appAspectRatio, captionInsets, ) } } } Loading @@ -148,11 +159,16 @@ fun calculateMaximizeBounds(displayLayout: DisplayLayout, taskInfo: RunningTaskI } else { // if non-resizable then calculate max bounds according to aspect ratio val activityAspectRatio = calculateAspectRatio(taskInfo) val captionInsets = taskInfo.configuration.windowConfiguration.appBounds?.let { it.top - taskInfo.configuration.windowConfiguration.bounds.top } ?: 0 val newSize = maximizeSizeGivenAspectRatio( taskInfo, Size(stableBounds.width(), stableBounds.height()), activityAspectRatio, captionInsets, ) return centerInArea(newSize, stableBounds, stableBounds.left, stableBounds.top) } Loading @@ -166,8 +182,9 @@ fun maximizeSizeGivenAspectRatio( taskInfo: RunningTaskInfo, targetArea: Size, aspectRatio: Float, captionInsets: Int = 0, ): Size { val targetHeight = targetArea.height val targetHeight = targetArea.height - captionInsets val targetWidth = targetArea.width val finalHeight: Int val finalWidth: Int Loading @@ -191,13 +208,18 @@ fun maximizeSizeGivenAspectRatio( finalHeight = (finalWidth / aspectRatio).toInt() } } return Size(finalWidth, finalHeight) return Size(finalWidth, finalHeight + captionInsets) } /** Calculates the aspect ratio of an activity from its fullscreen bounds. */ fun calculateAspectRatio(taskInfo: RunningTaskInfo): Float { if (taskInfo.appCompatTaskInfo.topActivityAppBounds.isEmpty) return 1f val appBounds = taskInfo.appCompatTaskInfo.topActivityAppBounds val appBounds = if (taskInfo.appCompatTaskInfo.topActivityAppBounds.isEmpty) { taskInfo.configuration.windowConfiguration.appBounds ?: taskInfo.configuration.windowConfiguration.bounds } else { taskInfo.appCompatTaskInfo.topActivityAppBounds } return maxOf(appBounds.height(), appBounds.width()) / minOf(appBounds.height(), appBounds.width()).toFloat() } Loading Loading @@ -233,6 +255,13 @@ fun isTaskBoundsEqual(taskBounds: Rect, stableBounds: Rect): Boolean { return taskBounds == stableBounds } /** Returns the app header height in desktop mode in pixels. */ fun getAppHeaderHeight(context: Context): Int = context.resources.getDimensionPixelSize(getAppHeaderHeightId()) /** Returns the resource id of the app header height in desktop mode. */ @DimenRes fun getAppHeaderHeightId(): Int = R.dimen.desktop_mode_freeform_decor_caption_height /** * Calculates the desired initial bounds for applications in desktop windowing. This is done as a * scale of the screen bounds. Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +10 −20 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import android.os.Handler import android.os.IBinder import android.os.SystemProperties import android.os.UserHandle import android.util.Size import android.view.Display.DEFAULT_DISPLAY import android.view.DragEvent import android.view.MotionEvent Loading Loading @@ -1223,7 +1222,6 @@ class DesktopTasksController( // and toggle to the stable bounds. desktopTilingDecorViewModel.removeTaskIfTiled(taskInfo.displayId, taskInfo.taskId) taskRepository.saveBoundsBeforeMaximize(taskInfo.taskId, currentTaskBounds) destinationBounds.set(calculateMaximizeBounds(displayLayout, taskInfo)) } Loading Loading @@ -1288,23 +1286,6 @@ class DesktopTasksController( ) } private fun getMaximizeBounds(taskInfo: RunningTaskInfo, stableBounds: Rect): Rect { if (taskInfo.isResizeable) { // if resizable then expand to entire stable bounds (full display minus insets) return Rect(stableBounds) } else { // if non-resizable then calculate max bounds according to aspect ratio val activityAspectRatio = calculateAspectRatio(taskInfo) val newSize = maximizeSizeGivenAspectRatio( taskInfo, Size(stableBounds.width(), stableBounds.height()), activityAspectRatio, ) return centerInArea(newSize, stableBounds, stableBounds.left, stableBounds.top) } } private fun isMaximizedToStableBoundsEdges( taskInfo: RunningTaskInfo, stableBounds: Rect, Loading Loading @@ -2385,7 +2366,16 @@ class DesktopTasksController( ): Rect { val bounds = if (ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isTrue) { calculateInitialBounds(displayLayout, taskInfo) // If caption insets should be excluded from app bounds, ensure caption insets // are excluded from the ideal initial bounds when scaling non-resizeable apps. // Caption insets stay fixed and don't scale with bounds. val captionInsets = if (desktopModeCompatPolicy.shouldExcludeCaptionFromAppBounds(taskInfo)) { getAppHeaderHeight(context) } else { 0 } calculateInitialBounds(displayLayout, taskInfo, captionInsets = captionInsets) } else { calculateDefaultDesktopTaskBounds(displayLayout) } Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +2 −1 Original line number Diff line number Diff line Loading @@ -1712,7 +1712,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mWindowDecorViewHostSupplier, mMultiInstanceHelper, mWindowDecorCaptionHandleRepository, mDesktopModeEventLogger); mDesktopModeEventLogger, mDesktopModeCompatPolicy); mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration); final TaskPositioner taskPositioner = mTaskPositionerFactory.create( Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +32 −14 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ import com.android.wm.shell.desktopmode.DesktopUserRepositories; import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource; import com.android.wm.shell.shared.multiinstance.ManageWindowsViewContainer; Loading Loading @@ -191,6 +192,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private final HandleMenuFactory mHandleMenuFactory; private final AppToWebGenericLinksParser mGenericLinksParser; private final AssistContentRequester mAssistContentRequester; private final DesktopModeCompatPolicy mDesktopModeCompatPolicy; // Hover state for the maximize menu and button. The menu will remain open as long as either of // these is true. See {@link #onMaximizeHoverStateChanged()}. Loading Loading @@ -232,7 +234,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin @NonNull WindowDecorViewHostSupplier<WindowDecorViewHost> windowDecorViewHostSupplier, MultiInstanceHelper multiInstanceHelper, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, DesktopModeEventLogger desktopModeEventLogger) { DesktopModeEventLogger desktopModeEventLogger, DesktopModeCompatPolicy desktopModeCompatPolicy) { this (context, userContext, displayController, taskResourceLoader, splitScreenController, desktopUserRepositories, taskOrganizer, taskInfo, taskSurface, handler, mainExecutor, mainDispatcher, bgScope, bgExecutor, choreographer, syncQueue, Loading @@ -245,7 +248,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin windowDecorViewHostSupplier, DefaultMaximizeMenuFactory.INSTANCE, DefaultHandleMenuFactory.INSTANCE, multiInstanceHelper, windowDecorCaptionHandleRepository, desktopModeEventLogger); windowDecorCaptionHandleRepository, desktopModeEventLogger, desktopModeCompatPolicy); } DesktopModeWindowDecoration( Loading Loading @@ -280,7 +284,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin HandleMenuFactory handleMenuFactory, MultiInstanceHelper multiInstanceHelper, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, DesktopModeEventLogger desktopModeEventLogger) { DesktopModeEventLogger desktopModeEventLogger, DesktopModeCompatPolicy desktopModeCompatPolicy) { super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface, surfaceControlBuilderSupplier, surfaceControlTransactionSupplier, windowContainerTransactionSupplier, surfaceControlSupplier, Loading @@ -305,6 +310,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mDesktopUserRepositories = desktopUserRepositories; mTaskResourceLoader = taskResourceLoader; mTaskResourceLoader.onWindowDecorCreated(taskInfo); mDesktopModeCompatPolicy = desktopModeCompatPolicy; } /** Loading Loading @@ -507,7 +513,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin applyStartTransactionOnDraw, shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible, mIsKeyguardVisibleAndOccluded, inFullImmersive, mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus, displayExclusionRegion, mIsRecentsTransitionRunning); displayExclusionRegion, mIsRecentsTransitionRunning, mDesktopModeCompatPolicy.shouldExcludeCaptionFromAppBounds(taskInfo)); final WindowDecorLinearLayout oldRootView = mResult.mRootView; final SurfaceControl oldDecorationSurface = mDecorationContainerSurface; Loading Loading @@ -891,7 +898,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin @NonNull InsetsState displayInsetsState, boolean hasGlobalFocus, @NonNull Region displayExclusionRegion, boolean shouldIgnoreCornerRadius) { boolean shouldIgnoreCornerRadius, boolean shouldExcludeCaptionFromAppBounds) { final int captionLayoutId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode()); final boolean isAppHeader = captionLayoutId == R.layout.desktop_mode_app_header; Loading Loading @@ -951,16 +959,24 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } } else { if (ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isTrue()) { // Force-consume the caption bar insets when the app tries to hide the caption. // This improves app compatibility of immersive apps. if (shouldExcludeCaptionFromAppBounds) { relayoutParams.mShouldSetAppBounds = true; } else { // Force-consume the caption bar insets when the app tries to hide the // caption. This improves app compatibility of immersive apps. relayoutParams.mInsetSourceFlags |= FLAG_FORCE_CONSUMING; } } } if (ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isTrue()) { if (shouldExcludeCaptionFromAppBounds) { relayoutParams.mShouldSetAppBounds = true; } else { // Always force-consume the caption bar insets for maximum app compatibility, // including non-immersive apps that just don't handle caption insets properly. relayoutParams.mInsetSourceFlags |= FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR; } } if (DesktopModeFlags.ENABLE_FULLY_IMMERSIVE_IN_DESKTOP.isTrue() && inFullImmersiveMode) { final Insets systemBarInsets = displayInsetsState.calculateInsets( Loading Loading @@ -1747,7 +1763,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private static int getCaptionHeightIdStatic(@WindowingMode int windowingMode) { return windowingMode == WINDOWING_MODE_FULLSCREEN ? com.android.internal.R.dimen.status_bar_height_default : R.dimen.desktop_mode_freeform_decor_caption_height; : DesktopModeUtils.getAppHeaderHeightId(); } private int getCaptionHeight(@WindowingMode int windowingMode) { Loading Loading @@ -1845,7 +1861,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin windowDecorViewHostSupplier, MultiInstanceHelper multiInstanceHelper, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, DesktopModeEventLogger desktopModeEventLogger) { DesktopModeEventLogger desktopModeEventLogger, DesktopModeCompatPolicy desktopModeCompatPolicy) { return new DesktopModeWindowDecoration( context, userContext, Loading @@ -1870,7 +1887,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin windowDecorViewHostSupplier, multiInstanceHelper, windowDecorCaptionHandleRepository, desktopModeEventLogger); desktopModeEventLogger, desktopModeCompatPolicy); } } Loading Loading
libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt +27 −1 Original line number Diff line number Diff line Loading @@ -18,9 +18,12 @@ package com.android.wm.shell.shared.desktopmode import android.app.TaskInfo import android.content.Context import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED import android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION import android.window.DesktopModeFlags import com.android.internal.R import java.util.ArrayList import com.android.window.flags.Flags /** * Class to decide whether to apply app compat policies in desktop mode. Loading Loading @@ -50,6 +53,21 @@ class DesktopModeCompatPolicy(private val context: Context) { || isTransparentTask(isActivityStackTransparent, numActivities)) && !isTopActivityNoDisplay) /** * Whether the caption insets should be excluded from configuration for system to handle. * * The treatment is enabled when all the of the following is true: * * Any flags to forcibly consume caption insets are enabled. * * Top activity have configuration coupled with insets. * * Task is not resizeable. */ fun shouldExcludeCaptionFromAppBounds(taskInfo: TaskInfo): Boolean = Flags.excludeCaptionFromAppBounds() && isAnyForceConsumptionFlagsEnabled() && taskInfo.topActivityInfo?.let { isInsetsCoupledWithConfiguration(it) && !taskInfo.isResizeable } ?: false /** * Returns true if all activities in a tasks stack are transparent. If there are no activities * will return false. Loading @@ -67,4 +85,12 @@ class DesktopModeCompatPolicy(private val context: Context) { */ private fun isPartOfDefaultHomePackage(packageName: String?) = packageName != null && packageName == defaultHomePackage private fun isAnyForceConsumptionFlagsEnabled(): Boolean = DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isTrue || DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isTrue private fun isInsetsCoupledWithConfiguration(info: ActivityInfo): Boolean = !(info.isChangeEnabled(OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION) || info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)) }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt +35 −6 Original line number Diff line number Diff line Loading @@ -18,8 +18,10 @@ package com.android.wm.shell.desktopmode import android.annotation.DimenRes import android.app.ActivityManager.RunningTaskInfo import android.app.TaskInfo import android.content.Context import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED import android.content.pm.ActivityInfo.isFixedOrientationLandscape import android.content.pm.ActivityInfo.isFixedOrientationPortrait Loading @@ -28,6 +30,7 @@ import android.content.res.Configuration.ORIENTATION_PORTRAIT import android.graphics.Rect import android.os.SystemProperties import android.util.Size import com.android.wm.shell.R import com.android.wm.shell.common.DisplayController import com.android.wm.shell.common.DisplayLayout Loading @@ -53,10 +56,12 @@ fun calculateDefaultDesktopTaskBounds(displayLayout: DisplayLayout): Rect { * aspect ratio, orientation and resizability to calculate an area this is compatible with the * applications previous configuration. */ @JvmOverloads fun calculateInitialBounds( displayLayout: DisplayLayout, taskInfo: RunningTaskInfo, scale: Float = DESKTOP_MODE_INITIAL_BOUNDS_SCALE, captionInsets: Int = 0, ): Rect { val screenBounds = Rect(0, 0, displayLayout.width(), displayLayout.height()) val appAspectRatio = calculateAspectRatio(taskInfo) Loading Loading @@ -92,7 +97,7 @@ fun calculateInitialBounds( } else { // If activity is unresizeable, regardless of orientation, calculate maximum // size (within the ideal size) maintaining original aspect ratio. maximizeSizeGivenAspectRatio(taskInfo, idealSize, appAspectRatio) maximizeSizeGivenAspectRatio(taskInfo, idealSize, appAspectRatio, captionInsets) } } ORIENTATION_PORTRAIT -> { Loading @@ -119,11 +124,17 @@ fun calculateInitialBounds( taskInfo, Size(customPortraitWidthForLandscapeApp, idealSize.height), appAspectRatio, captionInsets, ) } else { // For portrait unresizeable activities, calculate maximum size (within the // ideal size) maintaining original aspect ratio. maximizeSizeGivenAspectRatio(taskInfo, idealSize, appAspectRatio) maximizeSizeGivenAspectRatio( taskInfo, idealSize, appAspectRatio, captionInsets, ) } } } Loading @@ -148,11 +159,16 @@ fun calculateMaximizeBounds(displayLayout: DisplayLayout, taskInfo: RunningTaskI } else { // if non-resizable then calculate max bounds according to aspect ratio val activityAspectRatio = calculateAspectRatio(taskInfo) val captionInsets = taskInfo.configuration.windowConfiguration.appBounds?.let { it.top - taskInfo.configuration.windowConfiguration.bounds.top } ?: 0 val newSize = maximizeSizeGivenAspectRatio( taskInfo, Size(stableBounds.width(), stableBounds.height()), activityAspectRatio, captionInsets, ) return centerInArea(newSize, stableBounds, stableBounds.left, stableBounds.top) } Loading @@ -166,8 +182,9 @@ fun maximizeSizeGivenAspectRatio( taskInfo: RunningTaskInfo, targetArea: Size, aspectRatio: Float, captionInsets: Int = 0, ): Size { val targetHeight = targetArea.height val targetHeight = targetArea.height - captionInsets val targetWidth = targetArea.width val finalHeight: Int val finalWidth: Int Loading @@ -191,13 +208,18 @@ fun maximizeSizeGivenAspectRatio( finalHeight = (finalWidth / aspectRatio).toInt() } } return Size(finalWidth, finalHeight) return Size(finalWidth, finalHeight + captionInsets) } /** Calculates the aspect ratio of an activity from its fullscreen bounds. */ fun calculateAspectRatio(taskInfo: RunningTaskInfo): Float { if (taskInfo.appCompatTaskInfo.topActivityAppBounds.isEmpty) return 1f val appBounds = taskInfo.appCompatTaskInfo.topActivityAppBounds val appBounds = if (taskInfo.appCompatTaskInfo.topActivityAppBounds.isEmpty) { taskInfo.configuration.windowConfiguration.appBounds ?: taskInfo.configuration.windowConfiguration.bounds } else { taskInfo.appCompatTaskInfo.topActivityAppBounds } return maxOf(appBounds.height(), appBounds.width()) / minOf(appBounds.height(), appBounds.width()).toFloat() } Loading Loading @@ -233,6 +255,13 @@ fun isTaskBoundsEqual(taskBounds: Rect, stableBounds: Rect): Boolean { return taskBounds == stableBounds } /** Returns the app header height in desktop mode in pixels. */ fun getAppHeaderHeight(context: Context): Int = context.resources.getDimensionPixelSize(getAppHeaderHeightId()) /** Returns the resource id of the app header height in desktop mode. */ @DimenRes fun getAppHeaderHeightId(): Int = R.dimen.desktop_mode_freeform_decor_caption_height /** * Calculates the desired initial bounds for applications in desktop windowing. This is done as a * scale of the screen bounds. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +10 −20 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import android.os.Handler import android.os.IBinder import android.os.SystemProperties import android.os.UserHandle import android.util.Size import android.view.Display.DEFAULT_DISPLAY import android.view.DragEvent import android.view.MotionEvent Loading Loading @@ -1223,7 +1222,6 @@ class DesktopTasksController( // and toggle to the stable bounds. desktopTilingDecorViewModel.removeTaskIfTiled(taskInfo.displayId, taskInfo.taskId) taskRepository.saveBoundsBeforeMaximize(taskInfo.taskId, currentTaskBounds) destinationBounds.set(calculateMaximizeBounds(displayLayout, taskInfo)) } Loading Loading @@ -1288,23 +1286,6 @@ class DesktopTasksController( ) } private fun getMaximizeBounds(taskInfo: RunningTaskInfo, stableBounds: Rect): Rect { if (taskInfo.isResizeable) { // if resizable then expand to entire stable bounds (full display minus insets) return Rect(stableBounds) } else { // if non-resizable then calculate max bounds according to aspect ratio val activityAspectRatio = calculateAspectRatio(taskInfo) val newSize = maximizeSizeGivenAspectRatio( taskInfo, Size(stableBounds.width(), stableBounds.height()), activityAspectRatio, ) return centerInArea(newSize, stableBounds, stableBounds.left, stableBounds.top) } } private fun isMaximizedToStableBoundsEdges( taskInfo: RunningTaskInfo, stableBounds: Rect, Loading Loading @@ -2385,7 +2366,16 @@ class DesktopTasksController( ): Rect { val bounds = if (ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isTrue) { calculateInitialBounds(displayLayout, taskInfo) // If caption insets should be excluded from app bounds, ensure caption insets // are excluded from the ideal initial bounds when scaling non-resizeable apps. // Caption insets stay fixed and don't scale with bounds. val captionInsets = if (desktopModeCompatPolicy.shouldExcludeCaptionFromAppBounds(taskInfo)) { getAppHeaderHeight(context) } else { 0 } calculateInitialBounds(displayLayout, taskInfo, captionInsets = captionInsets) } else { calculateDefaultDesktopTaskBounds(displayLayout) } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +2 −1 Original line number Diff line number Diff line Loading @@ -1712,7 +1712,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mWindowDecorViewHostSupplier, mMultiInstanceHelper, mWindowDecorCaptionHandleRepository, mDesktopModeEventLogger); mDesktopModeEventLogger, mDesktopModeCompatPolicy); mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration); final TaskPositioner taskPositioner = mTaskPositionerFactory.create( Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +32 −14 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ import com.android.wm.shell.desktopmode.DesktopUserRepositories; import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource; import com.android.wm.shell.shared.multiinstance.ManageWindowsViewContainer; Loading Loading @@ -191,6 +192,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private final HandleMenuFactory mHandleMenuFactory; private final AppToWebGenericLinksParser mGenericLinksParser; private final AssistContentRequester mAssistContentRequester; private final DesktopModeCompatPolicy mDesktopModeCompatPolicy; // Hover state for the maximize menu and button. The menu will remain open as long as either of // these is true. See {@link #onMaximizeHoverStateChanged()}. Loading Loading @@ -232,7 +234,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin @NonNull WindowDecorViewHostSupplier<WindowDecorViewHost> windowDecorViewHostSupplier, MultiInstanceHelper multiInstanceHelper, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, DesktopModeEventLogger desktopModeEventLogger) { DesktopModeEventLogger desktopModeEventLogger, DesktopModeCompatPolicy desktopModeCompatPolicy) { this (context, userContext, displayController, taskResourceLoader, splitScreenController, desktopUserRepositories, taskOrganizer, taskInfo, taskSurface, handler, mainExecutor, mainDispatcher, bgScope, bgExecutor, choreographer, syncQueue, Loading @@ -245,7 +248,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin windowDecorViewHostSupplier, DefaultMaximizeMenuFactory.INSTANCE, DefaultHandleMenuFactory.INSTANCE, multiInstanceHelper, windowDecorCaptionHandleRepository, desktopModeEventLogger); windowDecorCaptionHandleRepository, desktopModeEventLogger, desktopModeCompatPolicy); } DesktopModeWindowDecoration( Loading Loading @@ -280,7 +284,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin HandleMenuFactory handleMenuFactory, MultiInstanceHelper multiInstanceHelper, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, DesktopModeEventLogger desktopModeEventLogger) { DesktopModeEventLogger desktopModeEventLogger, DesktopModeCompatPolicy desktopModeCompatPolicy) { super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface, surfaceControlBuilderSupplier, surfaceControlTransactionSupplier, windowContainerTransactionSupplier, surfaceControlSupplier, Loading @@ -305,6 +310,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mDesktopUserRepositories = desktopUserRepositories; mTaskResourceLoader = taskResourceLoader; mTaskResourceLoader.onWindowDecorCreated(taskInfo); mDesktopModeCompatPolicy = desktopModeCompatPolicy; } /** Loading Loading @@ -507,7 +513,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin applyStartTransactionOnDraw, shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible, mIsKeyguardVisibleAndOccluded, inFullImmersive, mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus, displayExclusionRegion, mIsRecentsTransitionRunning); displayExclusionRegion, mIsRecentsTransitionRunning, mDesktopModeCompatPolicy.shouldExcludeCaptionFromAppBounds(taskInfo)); final WindowDecorLinearLayout oldRootView = mResult.mRootView; final SurfaceControl oldDecorationSurface = mDecorationContainerSurface; Loading Loading @@ -891,7 +898,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin @NonNull InsetsState displayInsetsState, boolean hasGlobalFocus, @NonNull Region displayExclusionRegion, boolean shouldIgnoreCornerRadius) { boolean shouldIgnoreCornerRadius, boolean shouldExcludeCaptionFromAppBounds) { final int captionLayoutId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode()); final boolean isAppHeader = captionLayoutId == R.layout.desktop_mode_app_header; Loading Loading @@ -951,16 +959,24 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } } else { if (ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isTrue()) { // Force-consume the caption bar insets when the app tries to hide the caption. // This improves app compatibility of immersive apps. if (shouldExcludeCaptionFromAppBounds) { relayoutParams.mShouldSetAppBounds = true; } else { // Force-consume the caption bar insets when the app tries to hide the // caption. This improves app compatibility of immersive apps. relayoutParams.mInsetSourceFlags |= FLAG_FORCE_CONSUMING; } } } if (ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isTrue()) { if (shouldExcludeCaptionFromAppBounds) { relayoutParams.mShouldSetAppBounds = true; } else { // Always force-consume the caption bar insets for maximum app compatibility, // including non-immersive apps that just don't handle caption insets properly. relayoutParams.mInsetSourceFlags |= FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR; } } if (DesktopModeFlags.ENABLE_FULLY_IMMERSIVE_IN_DESKTOP.isTrue() && inFullImmersiveMode) { final Insets systemBarInsets = displayInsetsState.calculateInsets( Loading Loading @@ -1747,7 +1763,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private static int getCaptionHeightIdStatic(@WindowingMode int windowingMode) { return windowingMode == WINDOWING_MODE_FULLSCREEN ? com.android.internal.R.dimen.status_bar_height_default : R.dimen.desktop_mode_freeform_decor_caption_height; : DesktopModeUtils.getAppHeaderHeightId(); } private int getCaptionHeight(@WindowingMode int windowingMode) { Loading Loading @@ -1845,7 +1861,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin windowDecorViewHostSupplier, MultiInstanceHelper multiInstanceHelper, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, DesktopModeEventLogger desktopModeEventLogger) { DesktopModeEventLogger desktopModeEventLogger, DesktopModeCompatPolicy desktopModeCompatPolicy) { return new DesktopModeWindowDecoration( context, userContext, Loading @@ -1870,7 +1887,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin windowDecorViewHostSupplier, multiInstanceHelper, windowDecorCaptionHandleRepository, desktopModeEventLogger); desktopModeEventLogger, desktopModeCompatPolicy); } } Loading