Loading libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialog.kt +26 −7 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.wm.shell.apptoweb import android.app.ActivityManager.RunningTaskInfo import android.app.TaskInfo import android.content.Context import android.content.pm.verify.domain.DomainVerificationManager import android.graphics.Bitmap Loading @@ -36,8 +35,17 @@ import android.widget.TextView import android.window.TaskConstants import com.android.wm.shell.R import com.android.wm.shell.common.DisplayController import com.android.wm.shell.shared.annotations.ShellBackgroundThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader import java.util.function.Supplier import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.MainCoroutineDispatcher import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext /** Loading @@ -45,13 +53,14 @@ import java.util.function.Supplier */ internal class OpenByDefaultDialog( private val context: Context, private val taskInfo: TaskInfo, private val taskInfo: RunningTaskInfo, private val taskSurface: SurfaceControl, private val displayController: DisplayController, private val taskResourceLoader: WindowDecorTaskResourceLoader, private val surfaceControlTransactionSupplier: Supplier<SurfaceControl.Transaction>, @ShellMainThread private val mainDispatcher: MainCoroutineDispatcher, @ShellBackgroundThread private val bgScope: CoroutineScope, private val listener: DialogLifecycleListener, appIconBitmap: Bitmap?, appName: CharSequence? ) { private lateinit var dialog: OpenByDefaultDialogView private lateinit var viewHost: SurfaceControlViewHost Loading @@ -67,11 +76,20 @@ internal class OpenByDefaultDialog( context.getSystemService(DomainVerificationManager::class.java)!! private val packageName = taskInfo.baseActivity?.packageName!! private var loadAppInfoJob: Job? = null init { createDialog() initializeRadioButtons() bindAppInfo(appIconBitmap, appName) loadAppInfoJob = bgScope.launch { if (!isActive) return@launch val name = taskResourceLoader.getName(taskInfo) val icon = taskResourceLoader.getHeaderIcon(taskInfo) withContext(mainDispatcher.immediate) { if (!isActive) return@withContext bindAppInfo(icon, name) } } } /** Creates an open by default settings dialog. */ Loading Loading @@ -147,14 +165,15 @@ internal class OpenByDefaultDialog( } private fun closeMenu() { loadAppInfoJob?.cancel() dialogContainer?.releaseView() dialogContainer = null listener.onDialogDismissed() } private fun bindAppInfo( appIconBitmap: Bitmap?, appName: CharSequence? appIconBitmap: Bitmap, appName: CharSequence ) { appIconView.setImageBitmap(appIconBitmap) appNameView.text = appName Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +27 −5 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ import com.android.wm.shell.windowdecor.CaptionWindowDecorViewModel; import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel; import com.android.wm.shell.windowdecor.WindowDecorViewModel; import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer; import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader; import com.android.wm.shell.windowdecor.common.viewhost.DefaultWindowDecorViewHostSupplier; import com.android.wm.shell.windowdecor.common.viewhost.PooledWindowDecorViewHostSupplier; import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost; Loading Loading @@ -769,6 +770,8 @@ public abstract class WMShellModule { @WMSingleton @Provides static DesktopTilingDecorViewModel provideDesktopTilingViewModel(Context context, @ShellMainThread MainCoroutineDispatcher mainDispatcher, @ShellBackgroundThread CoroutineScope bgScope, DisplayController displayController, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, SyncTransactionQueue syncQueue, Loading @@ -777,9 +780,12 @@ public abstract class WMShellModule { ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler, ReturnToDragStartAnimator returnToDragStartAnimator, @DynamicOverride DesktopUserRepositories desktopUserRepositories, DesktopModeEventLogger desktopModeEventLogger) { DesktopModeEventLogger desktopModeEventLogger, WindowDecorTaskResourceLoader windowDecorTaskResourceLoader) { return new DesktopTilingDecorViewModel( context, mainDispatcher, bgScope, displayController, rootTaskDisplayAreaOrganizer, syncQueue, Loading @@ -788,7 +794,8 @@ public abstract class WMShellModule { toggleResizeDesktopTaskTransitionHandler, returnToDragStartAnimator, desktopUserRepositories, desktopModeEventLogger desktopModeEventLogger, windowDecorTaskResourceLoader ); } Loading Loading @@ -905,6 +912,8 @@ public abstract class WMShellModule { @ShellMainThread ShellExecutor shellExecutor, @ShellMainThread Handler mainHandler, @ShellMainThread Choreographer mainChoreographer, @ShellMainThread MainCoroutineDispatcher mainDispatcher, @ShellBackgroundThread CoroutineScope bgScope, @ShellBackgroundThread ShellExecutor bgExecutor, ShellInit shellInit, ShellCommandHandler shellCommandHandler, Loading @@ -931,13 +940,15 @@ public abstract class WMShellModule { Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger DesktopModeUiEventLogger desktopModeUiEventLogger, WindowDecorTaskResourceLoader taskResourceLoader ) { if (!DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(context)) { return Optional.empty(); } return Optional.of(new DesktopModeWindowDecorViewModel(context, shellExecutor, mainHandler, mainChoreographer, bgExecutor, shellInit, shellCommandHandler, windowManager, mainChoreographer, mainDispatcher, bgScope, bgExecutor, shellInit, shellCommandHandler, windowManager, taskOrganizer, desktopUserRepositories, displayController, shellController, displayInsetsController, syncQueue, transitions, desktopTasksController, desktopImmersiveController.get(), Loading @@ -945,7 +956,18 @@ public abstract class WMShellModule { assistContentRequester, windowDecorViewHostSupplier, multiInstanceHelper, desktopTasksLimiter, appHandleEducationController, appToWebEducationController, windowDecorCaptionHandleRepository, activityOrientationChangeHandler, focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger)); focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger, taskResourceLoader)); } @WMSingleton @Provides static WindowDecorTaskResourceLoader provideWindowDecorTaskResourceLoader( @NonNull Context context, @NonNull ShellInit shellInit, @NonNull ShellController shellController, @NonNull ShellCommandHandler shellCommandHandler) { return new WindowDecorTaskResourceLoader(context, shellInit, shellController, shellCommandHandler); } @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +25 −3 Original line number Diff line number Diff line Loading @@ -140,6 +140,7 @@ import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.FocusTransitionObserver; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration.ExclusionRegionListener; import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader; import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost; import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier; import com.android.wm.shell.windowdecor.extension.InsetsStateKt; Loading @@ -150,7 +151,9 @@ import kotlin.Pair; import kotlin.Unit; import kotlin.jvm.functions.Function1; import kotlinx.coroutines.CoroutineScope; import kotlinx.coroutines.ExperimentalCoroutinesApi; import kotlinx.coroutines.MainCoroutineDispatcher; import java.io.PrintWriter; import java.util.ArrayList; Loading @@ -177,6 +180,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private final ShellController mShellController; private final Context mContext; private final @ShellMainThread Handler mMainHandler; private final @ShellMainThread MainCoroutineDispatcher mMainDispatcher; private final @ShellBackgroundThread CoroutineScope mBgScope; private final @ShellBackgroundThread ShellExecutor mBgExecutor; private final Choreographer mMainChoreographer; private final DisplayController mDisplayController; Loading Loading @@ -241,12 +246,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private final FocusTransitionObserver mFocusTransitionObserver; private final DesktopModeEventLogger mDesktopModeEventLogger; private final DesktopModeUiEventLogger mDesktopModeUiEventLogger; private final WindowDecorTaskResourceLoader mTaskResourceLoader; public DesktopModeWindowDecorViewModel( Context context, ShellExecutor shellExecutor, @ShellMainThread Handler mainHandler, Choreographer mainChoreographer, @ShellMainThread MainCoroutineDispatcher mainDispatcher, @ShellBackgroundThread CoroutineScope bgScope, @ShellBackgroundThread ShellExecutor bgExecutor, ShellInit shellInit, ShellCommandHandler shellCommandHandler, Loading @@ -273,12 +281,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger) { DesktopModeUiEventLogger desktopModeUiEventLogger, WindowDecorTaskResourceLoader taskResourceLoader) { this( context, shellExecutor, mainHandler, mainChoreographer, mainDispatcher, bgScope, bgExecutor, shellInit, shellCommandHandler, Loading Loading @@ -311,7 +322,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, new TaskPositionerFactory(), focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger); desktopModeUiEventLogger, taskResourceLoader); } @VisibleForTesting Loading @@ -320,6 +332,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, ShellExecutor shellExecutor, @ShellMainThread Handler mainHandler, Choreographer mainChoreographer, @ShellMainThread MainCoroutineDispatcher mainDispatcher, @ShellBackgroundThread CoroutineScope bgScope, @ShellBackgroundThread ShellExecutor bgExecutor, ShellInit shellInit, ShellCommandHandler shellCommandHandler, Loading Loading @@ -352,11 +366,14 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, TaskPositionerFactory taskPositionerFactory, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger) { DesktopModeUiEventLogger desktopModeUiEventLogger, WindowDecorTaskResourceLoader taskResourceLoader) { mContext = context; mMainExecutor = shellExecutor; mMainHandler = mainHandler; mMainChoreographer = mainChoreographer; mMainDispatcher = mainDispatcher; mBgScope = bgScope; mBgExecutor = bgExecutor; mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class); mTaskOrganizer = taskOrganizer; Loading Loading @@ -418,6 +435,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mFocusTransitionObserver = focusTransitionObserver; mDesktopModeEventLogger = desktopModeEventLogger; mDesktopModeUiEventLogger = desktopModeUiEventLogger; mTaskResourceLoader = taskResourceLoader; shellInit.addInitCallback(this::onInit, this); } Loading Loading @@ -1640,12 +1658,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, : mContext, mContext.createContextAsUser(UserHandle.of(taskInfo.userId), 0 /* flags */), mDisplayController, mTaskResourceLoader, mSplitScreenController, mDesktopUserRepositories, mTaskOrganizer, taskInfo, taskSurface, mMainHandler, mMainExecutor, mMainDispatcher, mBgScope, mBgExecutor, mMainChoreographer, mSyncQueue, Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +97 −76 File changed.Preview size limit exceeded, changes collapsed. Show changes libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt +55 −26 Original line number Diff line number Diff line Loading @@ -47,15 +47,25 @@ import androidx.compose.ui.graphics.toArgb import androidx.core.view.isGone import com.android.window.flags.Flags import com.android.wm.shell.R import com.android.wm.shell.shared.annotations.ShellBackgroundThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.split.SplitScreenConstants import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewContainer import com.android.wm.shell.windowdecor.common.DecorThemeUtil import com.android.wm.shell.windowdecor.common.calculateMenuPosition import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader import com.android.wm.shell.windowdecor.extension.isFullscreen import com.android.wm.shell.windowdecor.extension.isMultiWindow import com.android.wm.shell.windowdecor.extension.isPinned import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.MainCoroutineDispatcher import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext /** * Handle menu opened when the appropriate button is clicked on. Loading @@ -66,11 +76,12 @@ import com.android.wm.shell.windowdecor.extension.isPinned * Additional Options: Miscellaneous functions including screenshot and closing task. */ class HandleMenu( @ShellMainThread private val mainDispatcher: CoroutineDispatcher, @ShellBackgroundThread private val bgScope: CoroutineScope, private val parentDecor: DesktopModeWindowDecoration, private val windowManagerWrapper: WindowManagerWrapper, private val taskResourceLoader: WindowDecorTaskResourceLoader, private val layoutResId: Int, private val appIconBitmap: Bitmap?, private val appName: CharSequence?, private val splitScreenController: SplitScreenController, private val shouldShowWindowingPill: Boolean, private val shouldShowNewWindowButton: Boolean, Loading Loading @@ -103,7 +114,8 @@ class HandleMenu( @VisibleForTesting var handleMenuViewContainer: AdditionalViewContainer? = null private var handleMenuView: HandleMenuView? = null @VisibleForTesting var handleMenuView: HandleMenuView? = null // Position of the handle menu used for laying out the handle view. @VisibleForTesting Loading @@ -122,6 +134,8 @@ class HandleMenu( get() = SHOULD_SHOW_SCREENSHOT_BUTTON || shouldShowNewWindowButton || shouldShowManageWindowsButton || shouldShowChangeAspectRatioButton private var loadAppInfoJob: Job? = null init { updateHandleMenuPillPositions(captionX, captionY) } Loading Loading @@ -190,7 +204,7 @@ class HandleMenu( shouldShowDesktopModeButton = shouldShowDesktopModeButton, isBrowserApp = isBrowserApp ).apply { bind(taskInfo, appIconBitmap, appName, shouldShowMoreActionsPill) bind(taskInfo, shouldShowMoreActionsPill) this.onToDesktopClickListener = onToDesktopClickListener this.onToFullscreenClickListener = onToFullscreenClickListener this.onToSplitScreenClickListener = onToSplitScreenClickListener Loading @@ -204,7 +218,16 @@ class HandleMenu( this.onCloseMenuClickListener = onCloseMenuClickListener this.onOutsideTouchListener = onOutsideTouchListener } loadAppInfoJob = bgScope.launch { if (!isActive) return@launch val name = taskResourceLoader.getName(taskInfo) val icon = taskResourceLoader.getHeaderIcon(taskInfo) withContext(mainDispatcher) { if (!isActive) return@withContext handleMenuView.setAppName(name) handleMenuView.setAppIcon(icon) } } val x = handleMenuPosition.x.toInt() val y = handleMenuPosition.y.toInt() handleMenuViewContainer = Loading Loading @@ -412,6 +435,7 @@ class HandleMenu( resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL fun close() { loadAppInfoJob?.cancel() handleMenuView?.animateCloseMenu { handleMenuViewContainer?.releaseView() handleMenuViewContainer = null Loading Loading @@ -439,8 +463,10 @@ class HandleMenu( private val appInfoPill = rootView.requireViewById<View>(R.id.app_info_pill) private val collapseMenuButton = appInfoPill.requireViewById<HandleMenuImageButton>( R.id.collapse_menu_button) private val appIconView = appInfoPill.requireViewById<ImageView>(R.id.application_icon) private val appNameView = appInfoPill.requireViewById<TextView>(R.id.application_name) @VisibleForTesting val appIconView = appInfoPill.requireViewById<ImageView>(R.id.application_icon) @VisibleForTesting val appNameView = appInfoPill.requireViewById<TextView>(R.id.application_name) // Windowing Pill. private val windowingPill = rootView.requireViewById<View>(R.id.windowing_pill) Loading Loading @@ -509,14 +535,12 @@ class HandleMenu( /** Binds the menu views to the new data. */ fun bind( taskInfo: RunningTaskInfo, appIconBitmap: Bitmap?, appName: CharSequence?, shouldShowMoreActionsPill: Boolean ) { this.taskInfo = taskInfo this.style = calculateMenuStyle(taskInfo) bindAppInfoPill(style, appIconBitmap, appName) bindAppInfoPill(style) if (shouldShowWindowingPill) { bindWindowingPill(style) } Loading @@ -527,6 +551,16 @@ class HandleMenu( bindOpenInAppOrBrowserPill(style) } /** Sets the app's name. */ fun setAppName(name: CharSequence) { appNameView.text = name } /** Sets the app's icon. */ fun setAppIcon(icon: Bitmap) { appIconView.setImageBitmap(icon) } /** Animates the menu openInAppOrBrowserg. */ fun animateOpenMenu() { if (taskInfo.isFullscreen || taskInfo.isMultiWindow) { Loading Loading @@ -593,22 +627,14 @@ class HandleMenu( ) } private fun bindAppInfoPill( style: MenuStyle, appIconBitmap: Bitmap?, appName: CharSequence? ) { private fun bindAppInfoPill(style: MenuStyle) { appInfoPill.background.setTint(style.backgroundColor) collapseMenuButton.apply { imageTintList = ColorStateList.valueOf(style.textColor) this.taskInfo = this@HandleMenuView.taskInfo } appIconView.setImageBitmap(appIconBitmap) appNameView.apply { text = appName setTextColor(style.textColor) } appNameView.setTextColor(style.textColor) } private fun bindWindowingPill(style: MenuStyle) { Loading Loading @@ -698,11 +724,12 @@ class HandleMenu( /** A factory interface to create a [HandleMenu]. */ interface HandleMenuFactory { fun create( @ShellMainThread mainDispatcher: MainCoroutineDispatcher, @ShellBackgroundThread bgScope: CoroutineScope, parentDecor: DesktopModeWindowDecoration, windowManagerWrapper: WindowManagerWrapper, taskResourceLoader: WindowDecorTaskResourceLoader, layoutResId: Int, appIconBitmap: Bitmap?, appName: CharSequence?, splitScreenController: SplitScreenController, shouldShowWindowingPill: Boolean, shouldShowNewWindowButton: Boolean, Loading @@ -721,11 +748,12 @@ interface HandleMenuFactory { /** A [HandleMenuFactory] implementation that creates a [HandleMenu]. */ object DefaultHandleMenuFactory : HandleMenuFactory { override fun create( @ShellMainThread mainDispatcher: MainCoroutineDispatcher, @ShellBackgroundThread bgScope: CoroutineScope, parentDecor: DesktopModeWindowDecoration, windowManagerWrapper: WindowManagerWrapper, taskResourceLoader: WindowDecorTaskResourceLoader, layoutResId: Int, appIconBitmap: Bitmap?, appName: CharSequence?, splitScreenController: SplitScreenController, shouldShowWindowingPill: Boolean, shouldShowNewWindowButton: Boolean, Loading @@ -740,11 +768,12 @@ object DefaultHandleMenuFactory : HandleMenuFactory { captionY: Int, ): HandleMenu { return HandleMenu( mainDispatcher, bgScope, parentDecor, windowManagerWrapper, taskResourceLoader, layoutResId, appIconBitmap, appName, splitScreenController, shouldShowWindowingPill, shouldShowNewWindowButton, Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialog.kt +26 −7 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.wm.shell.apptoweb import android.app.ActivityManager.RunningTaskInfo import android.app.TaskInfo import android.content.Context import android.content.pm.verify.domain.DomainVerificationManager import android.graphics.Bitmap Loading @@ -36,8 +35,17 @@ import android.widget.TextView import android.window.TaskConstants import com.android.wm.shell.R import com.android.wm.shell.common.DisplayController import com.android.wm.shell.shared.annotations.ShellBackgroundThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader import java.util.function.Supplier import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.MainCoroutineDispatcher import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext /** Loading @@ -45,13 +53,14 @@ import java.util.function.Supplier */ internal class OpenByDefaultDialog( private val context: Context, private val taskInfo: TaskInfo, private val taskInfo: RunningTaskInfo, private val taskSurface: SurfaceControl, private val displayController: DisplayController, private val taskResourceLoader: WindowDecorTaskResourceLoader, private val surfaceControlTransactionSupplier: Supplier<SurfaceControl.Transaction>, @ShellMainThread private val mainDispatcher: MainCoroutineDispatcher, @ShellBackgroundThread private val bgScope: CoroutineScope, private val listener: DialogLifecycleListener, appIconBitmap: Bitmap?, appName: CharSequence? ) { private lateinit var dialog: OpenByDefaultDialogView private lateinit var viewHost: SurfaceControlViewHost Loading @@ -67,11 +76,20 @@ internal class OpenByDefaultDialog( context.getSystemService(DomainVerificationManager::class.java)!! private val packageName = taskInfo.baseActivity?.packageName!! private var loadAppInfoJob: Job? = null init { createDialog() initializeRadioButtons() bindAppInfo(appIconBitmap, appName) loadAppInfoJob = bgScope.launch { if (!isActive) return@launch val name = taskResourceLoader.getName(taskInfo) val icon = taskResourceLoader.getHeaderIcon(taskInfo) withContext(mainDispatcher.immediate) { if (!isActive) return@withContext bindAppInfo(icon, name) } } } /** Creates an open by default settings dialog. */ Loading Loading @@ -147,14 +165,15 @@ internal class OpenByDefaultDialog( } private fun closeMenu() { loadAppInfoJob?.cancel() dialogContainer?.releaseView() dialogContainer = null listener.onDialogDismissed() } private fun bindAppInfo( appIconBitmap: Bitmap?, appName: CharSequence? appIconBitmap: Bitmap, appName: CharSequence ) { appIconView.setImageBitmap(appIconBitmap) appNameView.text = appName Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +27 −5 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ import com.android.wm.shell.windowdecor.CaptionWindowDecorViewModel; import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel; import com.android.wm.shell.windowdecor.WindowDecorViewModel; import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer; import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader; import com.android.wm.shell.windowdecor.common.viewhost.DefaultWindowDecorViewHostSupplier; import com.android.wm.shell.windowdecor.common.viewhost.PooledWindowDecorViewHostSupplier; import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost; Loading Loading @@ -769,6 +770,8 @@ public abstract class WMShellModule { @WMSingleton @Provides static DesktopTilingDecorViewModel provideDesktopTilingViewModel(Context context, @ShellMainThread MainCoroutineDispatcher mainDispatcher, @ShellBackgroundThread CoroutineScope bgScope, DisplayController displayController, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, SyncTransactionQueue syncQueue, Loading @@ -777,9 +780,12 @@ public abstract class WMShellModule { ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler, ReturnToDragStartAnimator returnToDragStartAnimator, @DynamicOverride DesktopUserRepositories desktopUserRepositories, DesktopModeEventLogger desktopModeEventLogger) { DesktopModeEventLogger desktopModeEventLogger, WindowDecorTaskResourceLoader windowDecorTaskResourceLoader) { return new DesktopTilingDecorViewModel( context, mainDispatcher, bgScope, displayController, rootTaskDisplayAreaOrganizer, syncQueue, Loading @@ -788,7 +794,8 @@ public abstract class WMShellModule { toggleResizeDesktopTaskTransitionHandler, returnToDragStartAnimator, desktopUserRepositories, desktopModeEventLogger desktopModeEventLogger, windowDecorTaskResourceLoader ); } Loading Loading @@ -905,6 +912,8 @@ public abstract class WMShellModule { @ShellMainThread ShellExecutor shellExecutor, @ShellMainThread Handler mainHandler, @ShellMainThread Choreographer mainChoreographer, @ShellMainThread MainCoroutineDispatcher mainDispatcher, @ShellBackgroundThread CoroutineScope bgScope, @ShellBackgroundThread ShellExecutor bgExecutor, ShellInit shellInit, ShellCommandHandler shellCommandHandler, Loading @@ -931,13 +940,15 @@ public abstract class WMShellModule { Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger DesktopModeUiEventLogger desktopModeUiEventLogger, WindowDecorTaskResourceLoader taskResourceLoader ) { if (!DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(context)) { return Optional.empty(); } return Optional.of(new DesktopModeWindowDecorViewModel(context, shellExecutor, mainHandler, mainChoreographer, bgExecutor, shellInit, shellCommandHandler, windowManager, mainChoreographer, mainDispatcher, bgScope, bgExecutor, shellInit, shellCommandHandler, windowManager, taskOrganizer, desktopUserRepositories, displayController, shellController, displayInsetsController, syncQueue, transitions, desktopTasksController, desktopImmersiveController.get(), Loading @@ -945,7 +956,18 @@ public abstract class WMShellModule { assistContentRequester, windowDecorViewHostSupplier, multiInstanceHelper, desktopTasksLimiter, appHandleEducationController, appToWebEducationController, windowDecorCaptionHandleRepository, activityOrientationChangeHandler, focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger)); focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger, taskResourceLoader)); } @WMSingleton @Provides static WindowDecorTaskResourceLoader provideWindowDecorTaskResourceLoader( @NonNull Context context, @NonNull ShellInit shellInit, @NonNull ShellController shellController, @NonNull ShellCommandHandler shellCommandHandler) { return new WindowDecorTaskResourceLoader(context, shellInit, shellController, shellCommandHandler); } @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +25 −3 Original line number Diff line number Diff line Loading @@ -140,6 +140,7 @@ import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.FocusTransitionObserver; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration.ExclusionRegionListener; import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader; import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost; import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier; import com.android.wm.shell.windowdecor.extension.InsetsStateKt; Loading @@ -150,7 +151,9 @@ import kotlin.Pair; import kotlin.Unit; import kotlin.jvm.functions.Function1; import kotlinx.coroutines.CoroutineScope; import kotlinx.coroutines.ExperimentalCoroutinesApi; import kotlinx.coroutines.MainCoroutineDispatcher; import java.io.PrintWriter; import java.util.ArrayList; Loading @@ -177,6 +180,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private final ShellController mShellController; private final Context mContext; private final @ShellMainThread Handler mMainHandler; private final @ShellMainThread MainCoroutineDispatcher mMainDispatcher; private final @ShellBackgroundThread CoroutineScope mBgScope; private final @ShellBackgroundThread ShellExecutor mBgExecutor; private final Choreographer mMainChoreographer; private final DisplayController mDisplayController; Loading Loading @@ -241,12 +246,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private final FocusTransitionObserver mFocusTransitionObserver; private final DesktopModeEventLogger mDesktopModeEventLogger; private final DesktopModeUiEventLogger mDesktopModeUiEventLogger; private final WindowDecorTaskResourceLoader mTaskResourceLoader; public DesktopModeWindowDecorViewModel( Context context, ShellExecutor shellExecutor, @ShellMainThread Handler mainHandler, Choreographer mainChoreographer, @ShellMainThread MainCoroutineDispatcher mainDispatcher, @ShellBackgroundThread CoroutineScope bgScope, @ShellBackgroundThread ShellExecutor bgExecutor, ShellInit shellInit, ShellCommandHandler shellCommandHandler, Loading @@ -273,12 +281,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger) { DesktopModeUiEventLogger desktopModeUiEventLogger, WindowDecorTaskResourceLoader taskResourceLoader) { this( context, shellExecutor, mainHandler, mainChoreographer, mainDispatcher, bgScope, bgExecutor, shellInit, shellCommandHandler, Loading Loading @@ -311,7 +322,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, new TaskPositionerFactory(), focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger); desktopModeUiEventLogger, taskResourceLoader); } @VisibleForTesting Loading @@ -320,6 +332,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, ShellExecutor shellExecutor, @ShellMainThread Handler mainHandler, Choreographer mainChoreographer, @ShellMainThread MainCoroutineDispatcher mainDispatcher, @ShellBackgroundThread CoroutineScope bgScope, @ShellBackgroundThread ShellExecutor bgExecutor, ShellInit shellInit, ShellCommandHandler shellCommandHandler, Loading Loading @@ -352,11 +366,14 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, TaskPositionerFactory taskPositionerFactory, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger) { DesktopModeUiEventLogger desktopModeUiEventLogger, WindowDecorTaskResourceLoader taskResourceLoader) { mContext = context; mMainExecutor = shellExecutor; mMainHandler = mainHandler; mMainChoreographer = mainChoreographer; mMainDispatcher = mainDispatcher; mBgScope = bgScope; mBgExecutor = bgExecutor; mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class); mTaskOrganizer = taskOrganizer; Loading Loading @@ -418,6 +435,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mFocusTransitionObserver = focusTransitionObserver; mDesktopModeEventLogger = desktopModeEventLogger; mDesktopModeUiEventLogger = desktopModeUiEventLogger; mTaskResourceLoader = taskResourceLoader; shellInit.addInitCallback(this::onInit, this); } Loading Loading @@ -1640,12 +1658,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, : mContext, mContext.createContextAsUser(UserHandle.of(taskInfo.userId), 0 /* flags */), mDisplayController, mTaskResourceLoader, mSplitScreenController, mDesktopUserRepositories, mTaskOrganizer, taskInfo, taskSurface, mMainHandler, mMainExecutor, mMainDispatcher, mBgScope, mBgExecutor, mMainChoreographer, mSyncQueue, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +97 −76 File changed.Preview size limit exceeded, changes collapsed. Show changes
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt +55 −26 Original line number Diff line number Diff line Loading @@ -47,15 +47,25 @@ import androidx.compose.ui.graphics.toArgb import androidx.core.view.isGone import com.android.window.flags.Flags import com.android.wm.shell.R import com.android.wm.shell.shared.annotations.ShellBackgroundThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.split.SplitScreenConstants import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewContainer import com.android.wm.shell.windowdecor.common.DecorThemeUtil import com.android.wm.shell.windowdecor.common.calculateMenuPosition import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader import com.android.wm.shell.windowdecor.extension.isFullscreen import com.android.wm.shell.windowdecor.extension.isMultiWindow import com.android.wm.shell.windowdecor.extension.isPinned import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.MainCoroutineDispatcher import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext /** * Handle menu opened when the appropriate button is clicked on. Loading @@ -66,11 +76,12 @@ import com.android.wm.shell.windowdecor.extension.isPinned * Additional Options: Miscellaneous functions including screenshot and closing task. */ class HandleMenu( @ShellMainThread private val mainDispatcher: CoroutineDispatcher, @ShellBackgroundThread private val bgScope: CoroutineScope, private val parentDecor: DesktopModeWindowDecoration, private val windowManagerWrapper: WindowManagerWrapper, private val taskResourceLoader: WindowDecorTaskResourceLoader, private val layoutResId: Int, private val appIconBitmap: Bitmap?, private val appName: CharSequence?, private val splitScreenController: SplitScreenController, private val shouldShowWindowingPill: Boolean, private val shouldShowNewWindowButton: Boolean, Loading Loading @@ -103,7 +114,8 @@ class HandleMenu( @VisibleForTesting var handleMenuViewContainer: AdditionalViewContainer? = null private var handleMenuView: HandleMenuView? = null @VisibleForTesting var handleMenuView: HandleMenuView? = null // Position of the handle menu used for laying out the handle view. @VisibleForTesting Loading @@ -122,6 +134,8 @@ class HandleMenu( get() = SHOULD_SHOW_SCREENSHOT_BUTTON || shouldShowNewWindowButton || shouldShowManageWindowsButton || shouldShowChangeAspectRatioButton private var loadAppInfoJob: Job? = null init { updateHandleMenuPillPositions(captionX, captionY) } Loading Loading @@ -190,7 +204,7 @@ class HandleMenu( shouldShowDesktopModeButton = shouldShowDesktopModeButton, isBrowserApp = isBrowserApp ).apply { bind(taskInfo, appIconBitmap, appName, shouldShowMoreActionsPill) bind(taskInfo, shouldShowMoreActionsPill) this.onToDesktopClickListener = onToDesktopClickListener this.onToFullscreenClickListener = onToFullscreenClickListener this.onToSplitScreenClickListener = onToSplitScreenClickListener Loading @@ -204,7 +218,16 @@ class HandleMenu( this.onCloseMenuClickListener = onCloseMenuClickListener this.onOutsideTouchListener = onOutsideTouchListener } loadAppInfoJob = bgScope.launch { if (!isActive) return@launch val name = taskResourceLoader.getName(taskInfo) val icon = taskResourceLoader.getHeaderIcon(taskInfo) withContext(mainDispatcher) { if (!isActive) return@withContext handleMenuView.setAppName(name) handleMenuView.setAppIcon(icon) } } val x = handleMenuPosition.x.toInt() val y = handleMenuPosition.y.toInt() handleMenuViewContainer = Loading Loading @@ -412,6 +435,7 @@ class HandleMenu( resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL fun close() { loadAppInfoJob?.cancel() handleMenuView?.animateCloseMenu { handleMenuViewContainer?.releaseView() handleMenuViewContainer = null Loading Loading @@ -439,8 +463,10 @@ class HandleMenu( private val appInfoPill = rootView.requireViewById<View>(R.id.app_info_pill) private val collapseMenuButton = appInfoPill.requireViewById<HandleMenuImageButton>( R.id.collapse_menu_button) private val appIconView = appInfoPill.requireViewById<ImageView>(R.id.application_icon) private val appNameView = appInfoPill.requireViewById<TextView>(R.id.application_name) @VisibleForTesting val appIconView = appInfoPill.requireViewById<ImageView>(R.id.application_icon) @VisibleForTesting val appNameView = appInfoPill.requireViewById<TextView>(R.id.application_name) // Windowing Pill. private val windowingPill = rootView.requireViewById<View>(R.id.windowing_pill) Loading Loading @@ -509,14 +535,12 @@ class HandleMenu( /** Binds the menu views to the new data. */ fun bind( taskInfo: RunningTaskInfo, appIconBitmap: Bitmap?, appName: CharSequence?, shouldShowMoreActionsPill: Boolean ) { this.taskInfo = taskInfo this.style = calculateMenuStyle(taskInfo) bindAppInfoPill(style, appIconBitmap, appName) bindAppInfoPill(style) if (shouldShowWindowingPill) { bindWindowingPill(style) } Loading @@ -527,6 +551,16 @@ class HandleMenu( bindOpenInAppOrBrowserPill(style) } /** Sets the app's name. */ fun setAppName(name: CharSequence) { appNameView.text = name } /** Sets the app's icon. */ fun setAppIcon(icon: Bitmap) { appIconView.setImageBitmap(icon) } /** Animates the menu openInAppOrBrowserg. */ fun animateOpenMenu() { if (taskInfo.isFullscreen || taskInfo.isMultiWindow) { Loading Loading @@ -593,22 +627,14 @@ class HandleMenu( ) } private fun bindAppInfoPill( style: MenuStyle, appIconBitmap: Bitmap?, appName: CharSequence? ) { private fun bindAppInfoPill(style: MenuStyle) { appInfoPill.background.setTint(style.backgroundColor) collapseMenuButton.apply { imageTintList = ColorStateList.valueOf(style.textColor) this.taskInfo = this@HandleMenuView.taskInfo } appIconView.setImageBitmap(appIconBitmap) appNameView.apply { text = appName setTextColor(style.textColor) } appNameView.setTextColor(style.textColor) } private fun bindWindowingPill(style: MenuStyle) { Loading Loading @@ -698,11 +724,12 @@ class HandleMenu( /** A factory interface to create a [HandleMenu]. */ interface HandleMenuFactory { fun create( @ShellMainThread mainDispatcher: MainCoroutineDispatcher, @ShellBackgroundThread bgScope: CoroutineScope, parentDecor: DesktopModeWindowDecoration, windowManagerWrapper: WindowManagerWrapper, taskResourceLoader: WindowDecorTaskResourceLoader, layoutResId: Int, appIconBitmap: Bitmap?, appName: CharSequence?, splitScreenController: SplitScreenController, shouldShowWindowingPill: Boolean, shouldShowNewWindowButton: Boolean, Loading @@ -721,11 +748,12 @@ interface HandleMenuFactory { /** A [HandleMenuFactory] implementation that creates a [HandleMenu]. */ object DefaultHandleMenuFactory : HandleMenuFactory { override fun create( @ShellMainThread mainDispatcher: MainCoroutineDispatcher, @ShellBackgroundThread bgScope: CoroutineScope, parentDecor: DesktopModeWindowDecoration, windowManagerWrapper: WindowManagerWrapper, taskResourceLoader: WindowDecorTaskResourceLoader, layoutResId: Int, appIconBitmap: Bitmap?, appName: CharSequence?, splitScreenController: SplitScreenController, shouldShowWindowingPill: Boolean, shouldShowNewWindowButton: Boolean, Loading @@ -740,11 +768,12 @@ object DefaultHandleMenuFactory : HandleMenuFactory { captionY: Int, ): HandleMenu { return HandleMenu( mainDispatcher, bgScope, parentDecor, windowManagerWrapper, taskResourceLoader, layoutResId, appIconBitmap, appName, splitScreenController, shouldShowWindowingPill, shouldShowNewWindowButton, Loading