Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix WindowInfo.containerSize without platformLayers flag #1028

Merged
merged 10 commits into from
Jan 30, 2024
33 changes: 33 additions & 0 deletions compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/Helpers.kt
MatkovIvan marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.compose.ui

import androidx.compose.ui.unit.Density
import androidx.compose.ui.window.uiContentSizeCategoryToFontScaleMap
import platform.UIKit.UIContentSizeCategoryUnspecified
import platform.UIKit.UIScreen
import platform.UIKit.UITraitEnvironmentProtocol

internal val UITraitEnvironmentProtocol.systemDensity: Density
get() {
val contentSizeCategory =
traitCollection.preferredContentSizeCategory ?: UIContentSizeCategoryUnspecified
return Density(
density = UIScreen.mainScreen.scale.toFloat(),
fontScale = uiContentSizeCategoryToFontScaleMap[contentSizeCategory] ?: 1.0f
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.compose.ui.platform

import androidx.compose.ui.input.pointer.PointerKeyboardModifiers
import androidx.compose.ui.systemDensity
import androidx.compose.ui.toDpRect
import androidx.compose.ui.unit.IntRect
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.roundToIntRect
import kotlinx.cinterop.useContents
import platform.UIKit.UIView

/**
* This class copied from Desktop sourceSet.
* Tracking a state of window.
*
* TODO: Extract information about window from [PlatformContext] in skiko source set.
*
*/
internal class PlatformWindowContext {
private val _windowInfo = WindowInfoImpl()
val windowInfo: WindowInfo get() = _windowInfo

private var _windowContainer: UIView? = null

fun setKeyboardModifiers(modifiers: PointerKeyboardModifiers) {
_windowInfo.keyboardModifiers = modifiers
}

fun setWindowFocused(focused: Boolean) {
_windowInfo.isWindowFocused = focused
}

fun setWindowContainer(windowContainer: UIView) {
_windowContainer = windowContainer
}

fun setContainerSize(size: IntSize) {
if (_windowInfo.containerSize != size) {
_windowInfo.containerSize = size
}
}

/**
* Calculates the bounds of the given [container] within the window.
* It uses [_windowContainer] as a reference for window coordinate space.
*
* @param container The container component whose bounds need to be calculated.
* @return The bounds of the container within the window as an [IntRect] object.
*/
fun boundsInWindow(container: UIView): IntRect {
val density = container.systemDensity
return if (_windowContainer != null && _windowContainer != container) {
container.convertRect(
rect = container.bounds,
toView = _windowContainer,
)
} else {
container.bounds
}.useContents {
with(density) {
toDpRect().toRect().roundToIntRect()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ import androidx.compose.ui.platform.LocalLayoutMargins
import androidx.compose.ui.platform.LocalSafeArea
import androidx.compose.ui.platform.PlatformContext
import androidx.compose.ui.platform.PlatformInsets
import androidx.compose.ui.platform.PlatformWindowContext
import androidx.compose.ui.platform.UIKitTextInputService
import androidx.compose.ui.platform.WindowInfo
import androidx.compose.ui.semantics.SemanticsOwner
import androidx.compose.ui.systemDensity
import androidx.compose.ui.toDpOffset
import androidx.compose.ui.toDpRect
import androidx.compose.ui.uikit.ComposeUIViewControllerConfiguration
import androidx.compose.ui.uikit.LocalKeyboardOverlapHeight
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.DpRect
import androidx.compose.ui.unit.IntRect
Expand All @@ -59,7 +59,6 @@ import androidx.compose.ui.window.KeyboardEventHandler
import androidx.compose.ui.window.KeyboardVisibilityListenerImpl
import androidx.compose.ui.window.RenderingUIView
import androidx.compose.ui.window.UITouchesEventPhase
import androidx.compose.ui.window.uiContentSizeCategoryToFontScaleMap
import kotlin.coroutines.CoroutineContext
import kotlin.math.floor
import kotlin.math.roundToLong
Expand All @@ -81,11 +80,9 @@ import platform.Foundation.NSSelectorFromString
import platform.Foundation.NSTimeInterval
import platform.QuartzCore.CATransaction
import platform.UIKit.NSLayoutConstraint
import platform.UIKit.UIContentSizeCategoryUnspecified
import platform.UIKit.UIEvent
import platform.UIKit.UIKeyboardWillHideNotification
import platform.UIKit.UIKeyboardWillShowNotification
import platform.UIKit.UIScreen
import platform.UIKit.UITouch
import platform.UIKit.UITouchPhase
import platform.UIKit.UIView
Expand All @@ -108,7 +105,7 @@ internal class ComposeSceneMediator(
private val container: UIView,
configuration: ComposeUIViewControllerConfiguration,
private val focusStack: FocusStack<UIView>?,
private val windowInfo: WindowInfo,
private val windowContext: PlatformWindowContext,
val coroutineContext: CoroutineContext,
private val renderingUIViewFactory: (RenderingUIView.Delegate) -> RenderingUIView,
composeSceneFactory: (
Expand Down Expand Up @@ -161,21 +158,12 @@ internal class ComposeSceneMediator(
renderingView.redrawer.needsProactiveDisplayLink = needHighFrequencyPolling
},
checkBounds = { dpPoint: DpOffset ->
val point = dpPoint.toOffset(getSystemDensity())
val point = dpPoint.toOffset(container.systemDensity)
getBoundsInPx().contains(point.round())
}
)
}

private fun getSystemDensity(): Density {
val contentSizeCategory = container.traitCollection.preferredContentSizeCategory
?: UIContentSizeCategoryUnspecified
return Density(
density = UIScreen.mainScreen.scale.toFloat(),
fontScale = uiContentSizeCategoryToFontScaleMap[contentSizeCategory] ?: 1.0f
)
}

private val interopContext: UIKitInteropContext by lazy {
UIKitInteropContext(
requestRedraw = { onComposeSceneInvalidate() }
Expand Down Expand Up @@ -227,8 +215,8 @@ internal class ComposeSceneMediator(
IOSPlatformContextImpl(
inputServices = uiKitTextInputService,
textToolbar = uiKitTextInputService,
windowInfo = windowInfo,
density = getSystemDensity(),
windowInfo = windowContext.windowInfo,
density = container.systemDensity,
semanticsOwnerListener = semanticsOwnerListener
)
}
Expand All @@ -238,7 +226,7 @@ internal class ComposeSceneMediator(
configuration = configuration,
keyboardOverlapHeightState = keyboardOverlapHeightState,
viewProvider = { container },
densityProvider = ::getSystemDensity,
densityProvider = { container.systemDensity },
composeSceneMediatorProvider = { this },
focusManager = focusManager,
)
Expand All @@ -262,7 +250,7 @@ internal class ComposeSceneMediator(
CATransaction.flush() // clear all animations
},
rootViewProvider = { container },
densityProvider = ::getSystemDensity,
densityProvider = { container.systemDensity },
focusStack = focusStack,
keyboardEventHandler = keyboardEventHandler
)
Expand Down Expand Up @@ -424,7 +412,7 @@ internal class ComposeSceneMediator(
}

is SceneLayout.Bounds -> {
val density = getSystemDensity().density
val density = container.systemDensity.density
renderingView.translatesAutoresizingMaskIntoConstraints = true
renderingView.setFrame(
with(value.rect) {
Expand All @@ -444,18 +432,11 @@ internal class ComposeSceneMediator(
}

fun viewWillLayoutSubviews() {
val density = getSystemDensity()
val density = container.systemDensity
//TODO: Current code updates layout based on rootViewController size.
// Maybe we need to rewrite it for SingleLayerComposeScene.

val boundsInWindow = container.convertRect(
rect = container.bounds,
toView = null
).useContents {
with(density) {
toDpRect().toRect().roundToIntRect()
}
}
val boundsInWindow = windowContext.boundsInWindow(container)
scene.density = density // TODO: Maybe it is wrong to set density to scene here?
scene.boundsInWindow = boundsInWindow
onComposeSceneInvalidate()
Expand Down Expand Up @@ -483,7 +464,7 @@ internal class ComposeSceneMediator(

fun getBoundsInDp(): DpRect = renderingView.frame.useContents { this.toDpRect() }

fun getBoundsInPx(): IntRect = with(getSystemDensity()) {
fun getBoundsInPx(): IntRect = with(container.systemDensity) {
getBoundsInDp().toRect().roundToIntRect()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import androidx.compose.runtime.CompositionLocalContext
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.platform.PlatformContext
import androidx.compose.ui.platform.WindowInfo
import androidx.compose.ui.platform.PlatformWindowContext
import androidx.compose.ui.uikit.ComposeUIViewControllerConfiguration
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntOffset
Expand Down Expand Up @@ -50,7 +50,7 @@ internal class UIViewComposeSceneLayer(
private val initLayoutDirection: LayoutDirection,
configuration: ComposeUIViewControllerConfiguration,
focusStack: FocusStack<UIView>?,
windowInfo: WindowInfo,
windowContext: PlatformWindowContext,
compositionContext: CompositionContext,
compositionLocalContext: CompositionLocalContext?,
) : ComposeSceneLayer {
Expand Down Expand Up @@ -83,7 +83,7 @@ internal class UIViewComposeSceneLayer(
container = rootView,
configuration = configuration,
focusStack = focusStack,
windowInfo = windowInfo,
windowContext = windowContext,
coroutineContext = compositionContext.effectCoroutineContext,
renderingUIViewFactory = ::createSkikoUIView,
composeSceneFactory = ::createComposeScene,
Expand Down