• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wm.shell.windowdecor
18 
19 import android.app.ActivityManager.RunningTaskInfo
20 import android.content.Context
21 import android.graphics.PixelFormat
22 import android.graphics.Point
23 import android.view.SurfaceControl
24 import android.view.SurfaceControlViewHost
25 import android.view.WindowInsets.Type.systemBars
26 import android.view.WindowManager
27 import android.view.WindowlessWindowManager
28 import android.window.DesktopModeFlags
29 import android.window.TaskConstants
30 import android.window.TaskSnapshot
31 import androidx.compose.ui.graphics.toArgb
32 import com.android.internal.annotations.VisibleForTesting
33 import com.android.wm.shell.RootTaskDisplayAreaOrganizer
34 import com.android.wm.shell.common.DisplayController
35 import com.android.wm.shell.desktopmode.DesktopUserRepositories
36 import com.android.wm.shell.shared.multiinstance.ManageWindowsViewContainer
37 import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
38 import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewContainer
39 import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer
40 import com.android.wm.shell.windowdecor.common.DecorThemeUtil
41 import java.util.function.Supplier
42 
43 /**
44  * Implementation of [ManageWindowsViewContainer] meant to be used in desktop header and app
45  * handle.
46  */
47 class DesktopHeaderManageWindowsMenu(
48     private val callerTaskInfo: RunningTaskInfo,
49     private val x: Int,
50     private val y: Int,
51     private val displayController: DisplayController,
52     private val rootTdaOrganizer: RootTaskDisplayAreaOrganizer,
53     context: Context,
54     private val desktopUserRepositories: DesktopUserRepositories,
55     private val surfaceControlBuilderSupplier: Supplier<SurfaceControl.Builder>,
56     private val surfaceControlTransactionSupplier: Supplier<SurfaceControl.Transaction>,
57     snapshotList: List<Pair<Int, TaskSnapshot?>>,
58     onIconClickListener: ((Int) -> Unit),
59     onOutsideClickListener: (() -> Unit)
60 ) : ManageWindowsViewContainer(
61     context,
62     DecorThemeUtil(context).getColorScheme(callerTaskInfo).background.toArgb()
63 ) {
64     @VisibleForTesting
65     var menuViewContainer: AdditionalViewContainer? = null
66 
67     init {
68         createMenu(snapshotList, onIconClickListener, onOutsideClickListener)
69         menuView.rootView.pivotX = 0f
70         menuView.rootView.pivotY = 0f
71         animateOpen()
72     }
73 
addToContainernull74     override fun addToContainer(menuView: ManageWindowsView) {
75         val menuPosition = Point(x, y)
76         val flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
77                 WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
78         val desktopRepository = desktopUserRepositories.getProfile(callerTaskInfo.userId)
79         menuViewContainer = if (DesktopModeFlags.ENABLE_FULLY_IMMERSIVE_IN_DESKTOP.isTrue
80             && desktopRepository.isTaskInFullImmersiveState(callerTaskInfo.taskId)) {
81             // Use system view container so that forcibly shown system bars take effect in
82             // immersive.
83             createAsSystemViewContainer(menuPosition, flags)
84         } else {
85             createAsViewHostContainer(menuPosition, flags)
86         }
87     }
88 
createAsSystemViewContainernull89     private fun createAsSystemViewContainer(position: Point, flags: Int): AdditionalViewContainer {
90         return AdditionalSystemViewContainer(
91             windowManagerWrapper = WindowManagerWrapper(
92                 context.getSystemService(WindowManager::class.java)
93             ),
94             taskId = callerTaskInfo.taskId,
95             x = position.x,
96             y = position.y,
97             width = menuView.menuWidth,
98             height = menuView.menuHeight,
99             flags = flags,
100             forciblyShownTypes = systemBars(),
101             view = menuView.rootView
102         )
103     }
104 
createAsViewHostContainernull105     private fun createAsViewHostContainer(position: Point, flags: Int): AdditionalViewContainer {
106         val builder = surfaceControlBuilderSupplier.get()
107         rootTdaOrganizer.attachToDisplayArea(callerTaskInfo.displayId, builder)
108         val leash = builder
109             .setName("Manage Windows Menu")
110             .setContainerLayer()
111             .build()
112         val lp = WindowManager.LayoutParams(
113             menuView.menuWidth,
114             menuView.menuHeight,
115             WindowManager.LayoutParams.TYPE_APPLICATION,
116             flags,
117             PixelFormat.TRANSPARENT
118         )
119         val windowManager = WindowlessWindowManager(
120             callerTaskInfo.configuration,
121             leash,
122             null // HostInputToken
123         )
124         val viewHost = SurfaceControlViewHost(
125             context,
126             displayController.getDisplay(callerTaskInfo.displayId), windowManager,
127             "MaximizeMenu"
128         )
129         menuView.let { viewHost.setView(it.rootView, lp) }
130         val t = surfaceControlTransactionSupplier.get()
131         t.setLayer(leash, TaskConstants.TASK_CHILD_LAYER_FLOATING_MENU)
132             .setPosition(leash, position.x.toFloat(), position.y.toFloat())
133             .show(leash)
134         t.apply()
135         return AdditionalViewHostViewContainer(
136             leash,
137             viewHost,
138             surfaceControlTransactionSupplier
139         )
140     }
141 
removeFromContainernull142     override fun removeFromContainer() {
143         menuViewContainer?.releaseView()
144     }
145 }
146