Skip to content

Commit 25efbda

Browse files
committed
Move TextInputSession calls to TextInputSession.
1 parent 80a9499 commit 25efbda

File tree

10 files changed

+156
-170
lines changed

10 files changed

+156
-170
lines changed

compose/mpp/demo/src/uikitMain/kotlin/androidx/compose/mpp/demo/main.uikit.kt

+43-2
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
11
// Use `xcodegen` first, then `open ./SkikoSample.xcodeproj` and then Run button in XCode.
22
package androidx.compose.mpp.demo
33

4+
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.fillMaxSize
6+
import androidx.compose.foundation.layout.safeDrawingPadding
7+
import androidx.compose.foundation.text.input.rememberTextFieldState
8+
import androidx.compose.material.Button
9+
import androidx.compose.material.MaterialTheme
10+
import androidx.compose.material.Text
11+
import androidx.compose.material.TextField
412
import androidx.compose.mpp.demo.bugs.IosBugs
513
import androidx.compose.mpp.demo.bugs.StartRecompositionCheck
614
import androidx.compose.runtime.Composable
7-
import androidx.compose.runtime.ExperimentalComposeApi
15+
import androidx.compose.runtime.mutableStateOf
816
import androidx.compose.runtime.remember
917
import androidx.compose.ui.ExperimentalComposeUiApi
18+
import androidx.compose.ui.Modifier
19+
import androidx.compose.ui.platform.InterceptPlatformTextInput
1020
import androidx.compose.ui.window.ComposeUIViewController
1121
import kotlinx.cinterop.BetaInteropApi
1222
import kotlinx.cinterop.autoreleasepool
1323
import kotlinx.cinterop.cstr
1424
import kotlinx.cinterop.memScoped
1525
import kotlinx.cinterop.toCValues
26+
import kotlinx.coroutines.awaitCancellation
1627
import platform.Foundation.NSStringFromClass
1728
import platform.UIKit.UIApplication
1829
import platform.UIKit.UIApplicationDelegateProtocol
@@ -43,7 +54,37 @@ fun main(vararg args: String) {
4354
parallelRendering = true
4455
}
4556
) {
46-
IosDemo(arg)
57+
MaterialTheme {
58+
// IosDemo(arg)
59+
Column(modifier = Modifier.fillMaxSize().safeDrawingPadding()) {
60+
Text("Hello World!")
61+
Button({}) {
62+
Text("Hello Button!")
63+
}
64+
65+
val text = rememberTextFieldState("test")
66+
InterceptPlatformTextInput(
67+
interceptor = { _, _ -> awaitCancellation() }
68+
) {
69+
TextField(text)
70+
}
71+
72+
val text1 = remember { mutableStateOf("test") }
73+
InterceptPlatformTextInput(
74+
interceptor = { _, _ -> awaitCancellation() }
75+
) {
76+
TextField(text1.value, onValueChange = { text1.value = it})
77+
}
78+
79+
80+
val text2 = rememberTextFieldState("test")
81+
TextField(text2)
82+
83+
val text133 = remember { mutableStateOf("test") }
84+
TextField(text133.value, onValueChange = { text133.value = it})
85+
86+
}
87+
}
4788
}
4889
}
4990
}

compose/ui/ui-test/src/skikoMain/kotlin/androidx/compose/ui/test/ComposeUiTest.skiko.kt

+3-16
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import androidx.compose.runtime.Composable
2020
import androidx.compose.runtime.snapshots.Snapshot
2121
import androidx.compose.ui.ExperimentalComposeUiApi
2222
import androidx.compose.ui.InternalComposeUiApi
23-
import androidx.compose.ui.SessionMutex
2423
import androidx.compose.ui.draganddrop.DragAndDropTransferData
2524
import androidx.compose.ui.geometry.Offset
2625
import androidx.compose.ui.geometry.Size
@@ -34,7 +33,6 @@ import androidx.compose.ui.platform.PlatformContext
3433
import androidx.compose.ui.platform.PlatformDragAndDropManager
3534
import androidx.compose.ui.platform.PlatformDragAndDropSource
3635
import androidx.compose.ui.platform.PlatformTextInputMethodRequest
37-
import androidx.compose.ui.platform.PlatformTextInputSessionScope
3836
import androidx.compose.ui.platform.WindowInfo
3937
import androidx.compose.ui.scene.CanvasLayersComposeScene
4038
import androidx.compose.ui.scene.ComposeScene
@@ -398,13 +396,6 @@ open class SkikoComposeUiTest @InternalTestApi constructor(
398396
get() = size
399397
}
400398

401-
private inner class TestTextInputSession(
402-
coroutineScope: CoroutineScope
403-
) : PlatformTextInputSessionScope, CoroutineScope by coroutineScope {
404-
override suspend fun startInputMethod(request: PlatformTextInputMethodRequest): Nothing =
405-
awaitCancellation()
406-
}
407-
408399
private inner class TestDragAndDropManager : PlatformDragAndDropManager {
409400
override val isRequestDragAndDropTransferRequired: Boolean
410401
get() = true
@@ -443,13 +434,9 @@ open class SkikoComposeUiTest @InternalTestApi constructor(
443434

444435
override val dragAndDropManager: PlatformDragAndDropManager = TestDragAndDropManager()
445436

446-
private val textInputSessionMutex = SessionMutex<TestTextInputSession>()
447-
448-
override suspend fun textInputSession(
449-
session: suspend PlatformTextInputSessionScope.() -> Nothing
450-
): Nothing = textInputSessionMutex.withSessionCancellingPrevious(
451-
sessionInitializer = { TestTextInputSession(it) }, session = session
452-
)
437+
override suspend fun startInputMethod(request: PlatformTextInputMethodRequest): Nothing {
438+
awaitCancellation()
439+
}
453440
}
454441
}
455442

compose/ui/ui/api/desktop/ui.api

+1-1
Original file line numberDiff line numberDiff line change
@@ -3506,7 +3506,7 @@ public abstract interface class androidx/compose/ui/platform/PlatformContext {
35063506
public fun isWindowTransparent ()Z
35073507
public fun requestFocus ()Z
35083508
public fun setPointerIcon (Landroidx/compose/ui/input/pointer/PointerIcon;)V
3509-
public fun textInputSession (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
3509+
public fun startInputMethod (Landroidx/compose/ui/platform/PlatformTextInputMethodRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
35103510
}
35113511

35123512
public final class androidx/compose/ui/platform/PlatformContext$Companion {

compose/ui/ui/api/ui.klib.api

+1-1
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ abstract interface androidx.compose.ui.platform/PlatformContext { // androidx.co
971971
open fun convertWindowToLocalPosition(androidx.compose.ui.geometry/Offset): androidx.compose.ui.geometry/Offset // androidx.compose.ui.platform/PlatformContext.convertWindowToLocalPosition|convertWindowToLocalPosition(androidx.compose.ui.geometry.Offset){}[0]
972972
open fun requestFocus(): kotlin/Boolean // androidx.compose.ui.platform/PlatformContext.requestFocus|requestFocus(){}[0]
973973
open fun setPointerIcon(androidx.compose.ui.input.pointer/PointerIcon) // androidx.compose.ui.platform/PlatformContext.setPointerIcon|setPointerIcon(androidx.compose.ui.input.pointer.PointerIcon){}[0]
974-
open suspend fun textInputSession(kotlin.coroutines/SuspendFunction1<androidx.compose.ui.platform/PlatformTextInputSessionScope, kotlin/Nothing>): kotlin/Nothing // androidx.compose.ui.platform/PlatformContext.textInputSession|textInputSession(kotlin.coroutines.SuspendFunction1<androidx.compose.ui.platform.PlatformTextInputSessionScope,kotlin.Nothing>){}[0]
974+
open suspend fun startInputMethod(androidx.compose.ui.platform/PlatformTextInputMethodRequest): kotlin/Nothing // androidx.compose.ui.platform/PlatformContext.startInputMethod|startInputMethod(androidx.compose.ui.platform.PlatformTextInputMethodRequest){}[0]
975975

976976
abstract interface RootForTestListener { // androidx.compose.ui.platform/PlatformContext.RootForTestListener|null[0]
977977
abstract fun onRootForTestCreated(androidx.compose.ui.platform/PlatformRootForTest) // androidx.compose.ui.platform/PlatformContext.RootForTestListener.onRootForTestCreated|onRootForTestCreated(androidx.compose.ui.platform.PlatformRootForTest){}[0]

compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/scene/ComposeSceneMediator.desktop.kt

+21-45
Original file line numberDiff line numberDiff line change
@@ -715,16 +715,27 @@ internal class ComposeSceneMediator(
715715
override val viewConfiguration: ViewConfiguration = DesktopViewConfiguration()
716716
override val textInputService = this@ComposeSceneMediator.textInputService
717717

718-
private val textInputSessionMutex = SessionMutex<DesktopTextInputSession>()
719-
720-
override suspend fun textInputSession(
721-
session: suspend PlatformTextInputSessionScope.() -> Nothing
722-
): Nothing = textInputSessionMutex.withSessionCancellingPrevious(
723-
sessionInitializer = {
724-
DesktopTextInputSession(coroutineScope = it)
725-
},
726-
session = session
727-
)
718+
override suspend fun startInputMethod(request: PlatformTextInputMethodRequest): Nothing {
719+
coroutineScope {
720+
launch {
721+
request.focusedRectInRoot.collect {
722+
textInputService2.focusedRectChanged(it)
723+
}
724+
}
725+
726+
suspendCancellableCoroutine<Nothing> { continuation ->
727+
textInputService2.startInput(
728+
state = request.state,
729+
imeOptions = request.imeOptions,
730+
editText = request.editText,
731+
)
732+
733+
continuation.invokeOnCancellation {
734+
textInputService2.stopInput()
735+
}
736+
}
737+
}
738+
}
728739

729740
override fun setPointerIcon(pointerIcon: PointerIcon) {
730741
contentComponent.cursor =
@@ -776,41 +787,6 @@ internal class ComposeSceneMediator(
776787
get() = contentComponent.density
777788
}
778789

779-
@OptIn(InternalComposeUiApi::class)
780-
private inner class DesktopTextInputSession(
781-
coroutineScope: CoroutineScope,
782-
) : PlatformTextInputSessionScope, CoroutineScope by coroutineScope {
783-
784-
private val innerSessionMutex = SessionMutex<Nothing?>()
785-
786-
override suspend fun startInputMethod(
787-
request: PlatformTextInputMethodRequest
788-
): Nothing = innerSessionMutex.withSessionCancellingPrevious(
789-
// This session has no data, just init/dispose tasks.
790-
sessionInitializer = { null }
791-
) {
792-
coroutineScope {
793-
launch {
794-
request.focusedRectInRoot.collect {
795-
textInputService2.focusedRectChanged(it)
796-
}
797-
}
798-
799-
suspendCancellableCoroutine<Nothing> { continuation ->
800-
textInputService2.startInput(
801-
state = request.state,
802-
imeOptions = request.imeOptions,
803-
editText = request.editText,
804-
)
805-
806-
continuation.invokeOnCancellation {
807-
textInputService2.stopInput()
808-
}
809-
}
810-
}
811-
}
812-
}
813-
814790
private class InvisibleComponent : Component() {
815791
fun requestFocusTemporary(): Boolean {
816792
return super.requestFocus(true)

compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/node/RootNodeOwner.skiko.kt

+33-15
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import androidx.compose.runtime.snapshotFlow
2626
import androidx.compose.ui.ExperimentalComposeUiApi
2727
import androidx.compose.ui.InternalComposeUiApi
2828
import androidx.compose.ui.Modifier
29+
import androidx.compose.ui.SessionMutex
2930
import androidx.compose.ui.autofill.Autofill
3031
import androidx.compose.ui.autofill.AutofillManager
3132
import androidx.compose.ui.autofill.AutofillTree
@@ -67,6 +68,7 @@ import androidx.compose.ui.platform.OwnedLayerManager
6768
import androidx.compose.ui.platform.PlatformClipboardManager
6869
import androidx.compose.ui.platform.PlatformContext
6970
import androidx.compose.ui.platform.PlatformRootForTest
71+
import androidx.compose.ui.platform.PlatformTextInputMethodRequest
7072
import androidx.compose.ui.platform.PlatformTextInputSessionScope
7173
import androidx.compose.ui.platform.createPlatformClipboard
7274
import androidx.compose.ui.platform.setLightingInfo
@@ -366,27 +368,43 @@ internal class RootNodeOwner(
366368
override val softwareKeyboardController =
367369
DelegatingSoftwareKeyboardController(textInputService)
368370

369-
@OptIn(InternalTextApi::class)
370-
override suspend fun textInputSession(
371-
session: suspend PlatformTextInputSessionScope.() -> Nothing
372-
) : Nothing {
373-
coroutineScope {
374-
// Currently TextInputService is used for keyboard show/hide actions and for
375-
// backward compatibility by the LocalTextInputService.
376-
// startInput and stopInput calls are required to properly configure the service
377-
// and allow it to pass keyboard show/hide calls to the PlatformTextInputService.
378-
textInputService.startInput()
379-
launch {
380-
suspendCancellableCoroutine<Nothing> {
381-
it.invokeOnCancellation {
382-
textInputService.stopInput()
371+
private val textInputSessionMutex = SessionMutex<TextInputSession>()
372+
private inner class TextInputSession(
373+
coroutineScope: CoroutineScope,
374+
) : PlatformTextInputSessionScope, CoroutineScope by coroutineScope {
375+
private val innerSessionMutex = SessionMutex<Nothing?>()
376+
377+
@OptIn(InternalTextApi::class)
378+
override suspend fun startInputMethod(request: PlatformTextInputMethodRequest): Nothing {
379+
innerSessionMutex.withSessionCancellingPrevious(
380+
sessionInitializer = { null }
381+
) {
382+
// Currently TextInputService is used for keyboard show/hide actions and for
383+
// backward compatibility by the LocalTextInputService.
384+
// startInput and stopInput calls are required to properly configure the service
385+
// and allow it to pass keyboard show/hide calls to the PlatformTextInputService.
386+
textInputService.startInput()
387+
launch {
388+
suspendCancellableCoroutine<Nothing> {
389+
it.invokeOnCancellation {
390+
textInputService.stopInput()
391+
}
383392
}
384393
}
394+
platformContext.startInputMethod(request)
385395
}
386-
platformContext.textInputSession(session)
387396
}
388397
}
389398

399+
override suspend fun textInputSession(
400+
session: suspend PlatformTextInputSessionScope.() -> Nothing
401+
) : Nothing {
402+
textInputSessionMutex.withSessionCancellingPrevious(
403+
sessionInitializer = ::TextInputSession,
404+
session = session
405+
)
406+
}
407+
390408
override val dragAndDropManager = this@RootNodeOwner.dragAndDropOwner
391409
override val pointerIconService = PointerIconServiceImpl()
392410
override val semanticsOwner = SemanticsOwner(root, rootSemanticsNode, layoutNodes)

compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/PlatformContext.skiko.kt

+1-3
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,7 @@ interface PlatformContext {
111111
val inputModeManager: InputModeManager
112112
val textInputService: PlatformTextInputService get() = EmptyPlatformTextInputService
113113

114-
suspend fun textInputSession(
115-
session: suspend PlatformTextInputSessionScope.() -> Nothing
116-
): Nothing {
114+
suspend fun startInputMethod(request: PlatformTextInputMethodRequest): Nothing {
117115
awaitCancellation()
118116
}
119117

0 commit comments

Comments
 (0)