xref: /aosp_15_r20/frameworks/base/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)

<lambda>null1 package com.android.systemui.scene.ui.view
2 
3 import android.content.Context
4 import android.util.AttributeSet
5 import android.view.MotionEvent
6 import android.view.View
7 import android.view.WindowInsets
8 import com.android.systemui.qs.ui.adapter.QSSceneAdapter
9 import com.android.systemui.scene.shared.model.SceneContainerConfig
10 import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
11 import com.android.systemui.scene.ui.composable.Overlay
12 import com.android.systemui.scene.ui.composable.Scene
13 import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
14 import com.android.systemui.shade.TouchLogger
15 import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
16 import javax.inject.Provider
17 import kotlinx.coroutines.ExperimentalCoroutinesApi
18 import kotlinx.coroutines.flow.MutableStateFlow
19 
20 /** A root view of the main SysUI window that supports scenes. */
21 @ExperimentalCoroutinesApi
22 class SceneWindowRootView(context: Context, attrs: AttributeSet?) : WindowRootView(context, attrs) {
23 
24     private var motionEventHandler: SceneContainerViewModel.MotionEventHandler? = null
25     // TODO(b/298525212): remove once Compose exposes window inset bounds.
26     private val windowInsets: MutableStateFlow<WindowInsets?> = MutableStateFlow(null)
27 
28     fun init(
29         viewModelFactory: SceneContainerViewModel.Factory,
30         containerConfig: SceneContainerConfig,
31         sharedNotificationContainer: SharedNotificationContainer,
32         scenes: Set<Scene>,
33         overlays: Set<Overlay>,
34         layoutInsetController: LayoutInsetsController,
35         sceneDataSourceDelegator: SceneDataSourceDelegator,
36         qsSceneAdapter: Provider<QSSceneAdapter>,
37     ) {
38         setLayoutInsetsController(layoutInsetController)
39         SceneWindowRootViewBinder.bind(
40             view = this@SceneWindowRootView,
41             viewModelFactory = viewModelFactory,
42             motionEventHandlerReceiver = { motionEventHandler ->
43                 this.motionEventHandler = motionEventHandler
44             },
45             windowInsets = windowInsets,
46             containerConfig = containerConfig,
47             sharedNotificationContainer = sharedNotificationContainer,
48             scenes = scenes,
49             overlays = overlays,
50             onVisibilityChangedInternal = { isVisible ->
51                 super.setVisibility(if (isVisible) View.VISIBLE else View.INVISIBLE)
52             },
53             dataSourceDelegator = sceneDataSourceDelegator,
54             qsSceneAdapter = qsSceneAdapter,
55         )
56     }
57 
58     override fun setVisibility(visibility: Int) {
59         // Do nothing. We don't want external callers to invoke this. Instead, we drive our own
60         // visibility from our view-binder.
61     }
62 
63     // TODO(b/298525212): remove once Compose exposes window inset bounds.
64     override fun onApplyWindowInsets(windowInsets: WindowInsets): WindowInsets {
65         this.windowInsets.value = windowInsets
66         return windowInsets
67     }
68 
69     override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
70         motionEventHandler?.onMotionEvent(ev)
71         return super.dispatchTouchEvent(ev).also {
72             TouchLogger.logDispatchTouch(TAG, ev, it)
73             motionEventHandler?.onMotionEventComplete()
74         }
75     }
76 
77     override fun onTouchEvent(event: MotionEvent?): Boolean {
78         event?.let { motionEventHandler?.onEmptySpaceMotionEvent(it) }
79         return super.onTouchEvent(event)
80     }
81 
82     companion object {
83         private const val TAG = "SceneWindowRootView"
84     }
85 }
86