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 IME window insets and view offset when keyboard appears #1199

Merged
merged 16 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,12 @@ internal class MagnifierNode(
),
fromCoordinateSpace = window.coordinateSpace()
).useContents {
Offset(x.toFloat() * density.density, y.toFloat() * density.density)
// HACK: Applying additional offset to adjust magnifier location
// when platform layers are disabled.
val additionalViewOffsetInWindow = view!!.layer.affineTransform().useContents {
Offset(tx.toFloat(), ty.toFloat()) * density.density
}
Offset(x.toFloat(), y.toFloat()) * density.density + additionalViewOffsetInWindow
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import androidx.compose.ui.window.ComposeSceneKeyboardOffsetManager
import androidx.compose.ui.window.FocusStack
import androidx.compose.ui.window.InteractionUIView
import androidx.compose.ui.window.KeyboardEventHandler
import androidx.compose.ui.window.KeyboardVisibilityListener
import androidx.compose.ui.window.RenderingUIView
import androidx.compose.ui.window.UITouchesEventPhase
import kotlin.coroutines.CoroutineContext
Expand Down Expand Up @@ -332,10 +333,10 @@ internal class ComposeSceneMediator(
ComposeSceneKeyboardOffsetManager(
configuration = configuration,
keyboardOverlapHeightState = keyboardOverlapHeightState,
viewProvider = { rootView },
viewProvider = { viewForKeyboardOffsetTransform },
composeSceneMediatorProvider = { this },
onComposeSceneOffsetChanged = { offset ->
rootView.layer.setAffineTransform(CGAffineTransformMakeTranslation(0.0, -offset))
viewForKeyboardOffsetTransform.layer.setAffineTransform(CGAffineTransformMakeTranslation(0.0, -offset))
scene.invalidatePositionInWindow()
}
)
Expand All @@ -360,7 +361,9 @@ internal class ComposeSceneMediator(
viewConfiguration = viewConfiguration,
focusStack = focusStack,
keyboardEventHandler = keyboardEventHandler
)
).also {
KeyboardVisibilityListener.initialize()
}
}

private val touchesDelegate: InteractionUIView.Delegate by lazy {
Expand Down Expand Up @@ -662,14 +665,18 @@ internal class ComposeSceneMediator(
|| scene.sendKeyEvent(keyEvent)
|| _onKeyEvent(keyEvent)

@OptIn(ExperimentalComposeApi::class)
private var viewForKeyboardOffsetTransform = if (configuration.platformLayers)
rootView else container
MatkovIvan marked this conversation as resolved.
Show resolved Hide resolved

private inner class IOSPlatformContext : PlatformContext by PlatformContext.Empty {
override val windowInfo: WindowInfo get() = windowContext.windowInfo

override fun calculatePositionInWindow(localPosition: Offset): Offset =
windowContext.calculatePositionInWindow(rootView, localPosition)
windowContext.calculatePositionInWindow(viewForKeyboardOffsetTransform, localPosition)

override fun calculateLocalPosition(positionInWindow: Offset): Offset =
windowContext.calculateLocalPosition(rootView, positionInWindow)
windowContext.calculateLocalPosition(viewForKeyboardOffsetTransform, positionInWindow)

override val measureDrawLayerBounds get() = this@ComposeSceneMediator.measureDrawLayerBounds
override val viewConfiguration get() = this@ComposeSceneMediator.viewConfiguration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ internal interface KeyboardVisibilityObserver {

internal object KeyboardVisibilityListener {
private val listener = NativeKeyboardVisibilityListener()
private var initOnce = false
fun initialize() {
if (initOnce) { return }
initOnce = true
listener.startKeyboardChangesObserving()
}

fun addObserver(observer: KeyboardVisibilityObserver) = listener.observers.add(observer)

Expand All @@ -70,7 +76,7 @@ internal object KeyboardVisibilityListener {
private class NativeKeyboardVisibilityListener : NSObject() {
val observers = mutableSetOf<KeyboardVisibilityObserver>()

init {
fun startKeyboardChangesObserving() {
NSNotificationCenter.defaultCenter.addObserver(
observer = this,
selector = NSSelectorFromString(::keyboardWillShow.name + ":"),
Expand Down