1 /*
2 * Copyright (C) 2023 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.systemui.common.ui.compose.windowinsets
18
19 import androidx.compose.foundation.layout.WindowInsets
20 import androidx.compose.foundation.layout.asPaddingValues
21 import androidx.compose.foundation.layout.displayCutout
22 import androidx.compose.foundation.layout.systemBars
23 import androidx.compose.runtime.Composable
24 import androidx.compose.runtime.CompositionLocalProvider
25 import androidx.compose.runtime.getValue
26 import androidx.compose.runtime.staticCompositionLocalOf
27 import androidx.compose.ui.platform.LocalConfiguration
28 import androidx.compose.ui.platform.LocalDensity
29 import androidx.compose.ui.unit.dp
30 import androidx.lifecycle.compose.collectAsStateWithLifecycle
31 import kotlinx.coroutines.flow.StateFlow
32
33 /** The bounds and [CutoutLocation] of the current display. */
<lambda>null34 val LocalDisplayCutout = staticCompositionLocalOf { DisplayCutout() }
35
36 /** The corner radius in px of the current display. */
<lambda>null37 val LocalScreenCornerRadius = staticCompositionLocalOf { 0.dp }
38
39 /** The screen height in px without accounting for any screen insets (cutouts, status/nav bars) */
<lambda>null40 val LocalRawScreenHeight = staticCompositionLocalOf { 0f }
41
42 @Composable
ScreenDecorProvidernull43 fun ScreenDecorProvider(
44 displayCutout: StateFlow<DisplayCutout>,
45 screenCornerRadius: Float,
46 content: @Composable () -> Unit,
47 ) {
48 val cutout by displayCutout.collectAsStateWithLifecycle()
49 val screenCornerRadiusDp = with(LocalDensity.current) { screenCornerRadius.toDp() }
50
51 val density = LocalDensity.current
52 val navBarHeight =
53 with(density) { WindowInsets.systemBars.asPaddingValues().calculateBottomPadding().toPx() }
54 val statusBarHeight = WindowInsets.systemBars.asPaddingValues().calculateTopPadding()
55 val displayCutoutHeight = WindowInsets.displayCutout.asPaddingValues().calculateTopPadding()
56 val screenHeight =
57 with(density) {
58 (LocalConfiguration.current.screenHeightDp.dp +
59 maxOf(statusBarHeight, displayCutoutHeight))
60 .toPx()
61 } + navBarHeight
62
63 CompositionLocalProvider(
64 LocalScreenCornerRadius provides screenCornerRadiusDp,
65 LocalDisplayCutout provides cutout,
66 LocalRawScreenHeight provides screenHeight,
67 ) {
68 content()
69 }
70 }
71