Skip to content

Commit 4d4df5f

Browse files
committed
Pass functions, not flows, in PlatformTextInputMethodRequest
1 parent d71d471 commit 4d4df5f

File tree

17 files changed

+134
-219
lines changed

17 files changed

+134
-219
lines changed

compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/text/input/internal/LegacyPlatformTextInputServiceAdapter.skiko.kt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import androidx.compose.runtime.getValue
2121
import androidx.compose.runtime.mutableStateOf
2222
import androidx.compose.runtime.remember
2323
import androidx.compose.runtime.setValue
24-
import androidx.compose.runtime.snapshotFlow
2524
import androidx.compose.ui.ExperimentalComposeUiApi
2625
import androidx.compose.ui.geometry.Rect
2726
import androidx.compose.ui.graphics.Matrix
@@ -39,7 +38,6 @@ import androidx.compose.ui.text.input.TextEditorState
3938
import androidx.compose.ui.text.input.TextFieldValue
4039
import androidx.compose.ui.text.input.TextInputService
4140
import kotlinx.coroutines.Job
42-
import kotlinx.coroutines.flow.filterNotNull
4341

4442
// TODO remove after https://youtrack.jetbrains.com/issue/COMPOSE-740/Implement-BasicTextField2
4543
@OptIn(ExperimentalComposeUiApi::class)
@@ -161,11 +159,10 @@ internal actual fun legacyTextInputServiceAdapterAndService():
161159
imeOptions = imeOptions,
162160
onEditCommand = onEditCommand,
163161
onImeAction = onImeActionPerformed,
164-
outputValue = snapshotFlow { textFieldValue },
165-
textLayoutResult = snapshotFlow { textLayoutResult }.filterNotNull(),
166-
focusedRectInRoot = snapshotFlow { focusedRectInRoot },
167-
textFieldRectInRoot = snapshotFlow { textFieldRectInRoot },
168-
textClippingRectInRoot = snapshotFlow { textClippingRectInRoot },
162+
textLayoutResult = { textLayoutResult },
163+
focusedRectInRoot = { focusedRectInRoot },
164+
textFieldRectInRoot = { textFieldRectInRoot },
165+
textClippingRectInRoot = { textClippingRectInRoot },
169166
editText = editBlock
170167
)
171168
}

compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/text/input/internal/TextInputSession.skiko.kt

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import androidx.compose.foundation.text.input.TextFieldCharSequence
2222
import androidx.compose.foundation.text.input.delete
2323
import androidx.compose.foundation.text.input.setSelectionCoerced
2424
import androidx.compose.foundation.text.offsetByCodePoints
25-
import androidx.compose.runtime.snapshotFlow
2625
import androidx.compose.ui.ExperimentalComposeUiApi
2726
import androidx.compose.ui.geometry.Offset
2827
import androidx.compose.ui.geometry.Rect
@@ -40,10 +39,7 @@ import androidx.compose.ui.text.input.TextEditingScope
4039
import androidx.compose.ui.text.input.TextEditorState
4140
import androidx.compose.ui.text.input.TextFieldValue
4241
import kotlinx.coroutines.coroutineScope
43-
import kotlinx.coroutines.flow.Flow
4442
import kotlinx.coroutines.flow.MutableSharedFlow
45-
import kotlinx.coroutines.flow.callbackFlow
46-
import kotlinx.coroutines.flow.filterNotNull
4743

4844
@OptIn(ExperimentalComposeUiApi::class)
4945
internal actual suspend fun PlatformTextInputSession.platformSpecificTextInputSession(
@@ -91,29 +87,17 @@ internal actual suspend fun PlatformTextInputSession.platformSpecificTextInputSe
9187
}
9288

9389
coroutineScope {
94-
val outputValueFlow = callbackFlow {
95-
state.collectImeNotifications { _, _, _ ->
96-
// SkikoPlatformTextInputMethodRequest should work with an untransformed text on all platforms
97-
// This updates platform text input services after changing the state with latest value in onEditCommand
98-
trySend(state.untransformedText.toTextFieldValue())
99-
}
100-
}
101-
102-
val focusedRectInRootFlow = snapshotFlow {
103-
val layoutResult = layoutState.layoutResult ?: return@snapshotFlow null
104-
val layoutCoords = layoutState.textLayoutNodeCoordinates ?: return@snapshotFlow null
105-
layoutResult
90+
fun focusedRectInRoot(): Rect? {
91+
val layoutResult = layoutState.layoutResult ?: return null
92+
val layoutCoords = layoutState.textLayoutNodeCoordinates ?: return null
93+
return layoutResult
10694
.getCursorRect(state.visualText.selection.max)
10795
.translate(layoutCoords.localToRoot(Offset.Zero))
108-
}.filterNotNull()
96+
}
10997

110-
val textFieldRectInRoot = snapshotFlow {
111-
layoutState.decoratorNodeCoordinates?.boundsInRoot()
112-
}.filterNotNull()
98+
fun textFieldRectInRoot() = layoutState.decoratorNodeCoordinates?.boundsInRoot()
11399

114-
val textClippingRectInRoot = snapshotFlow {
115-
layoutState.coreNodeCoordinates?.boundsInRoot()
116-
}.filterNotNull()
100+
fun textClippingRectInRoot() = layoutState.coreNodeCoordinates?.boundsInRoot()
117101

118102
startInputMethod(
119103
SkikoPlatformTextInputMethodRequest(
@@ -122,11 +106,10 @@ internal actual suspend fun PlatformTextInputSession.platformSpecificTextInputSe
122106
imeOptions = imeOptions,
123107
onEditCommand = ::onEditCommand,
124108
onImeAction = onImeAction,
125-
outputValue = outputValueFlow,
126-
textLayoutResult = snapshotFlow(layoutState::layoutResult).filterNotNull(),
127-
focusedRectInRoot = focusedRectInRootFlow,
128-
textFieldRectInRoot = textFieldRectInRoot,
129-
textClippingRectInRoot = textClippingRectInRoot,
109+
textLayoutResult = layoutState::layoutResult,
110+
focusedRectInRoot = ::focusedRectInRoot,
111+
textFieldRectInRoot = ::textFieldRectInRoot,
112+
textClippingRectInRoot = ::textClippingRectInRoot,
130113
editText = ::editText
131114
)
132115
)
@@ -242,10 +225,9 @@ internal data class SkikoPlatformTextInputMethodRequest(
242225
override val imeOptions: ImeOptions,
243226
override val onEditCommand: (List<EditCommand>) -> Unit,
244227
override val onImeAction: ((ImeAction) -> Unit)?,
245-
override val outputValue: Flow<TextFieldValue>,
246-
override val textLayoutResult: Flow<TextLayoutResult>,
247-
override val focusedRectInRoot: Flow<Rect>,
248-
override val textFieldRectInRoot: Flow<Rect>,
249-
override val textClippingRectInRoot: Flow<Rect>,
228+
override val textLayoutResult: () -> TextLayoutResult?,
229+
override val focusedRectInRoot: () -> Rect?,
230+
override val textFieldRectInRoot: () -> Rect?,
231+
override val textClippingRectInRoot: () -> Rect?,
250232
override val editText: (block: TextEditingScope.() -> Unit) -> Unit
251233
): PlatformTextInputMethodRequest

compose/foundation/foundation/src/skikoTest/kotlin/androidx/compose/foundation/text/LegacyPlatformTextInputServiceAdapterTest.kt

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import androidx.compose.ui.text.input.TextFieldValue
4646
import kotlin.test.Test
4747
import kotlinx.coroutines.awaitCancellation
4848
import kotlinx.coroutines.coroutineScope
49+
import kotlinx.coroutines.flow.filterNotNull
4950
import kotlinx.coroutines.launch
5051

5152
class LegacyPlatformTextInputServiceAdapterTest {
@@ -55,7 +56,6 @@ class LegacyPlatformTextInputServiceAdapterTest {
5556
var value: TextFieldValue? = null
5657
var state: TextEditorState? = null
5758
var imeOptions: ImeOptions? = null
58-
var outputValue: TextFieldValue? = null
5959
var textLayoutResult: TextLayoutResult? = null
6060
var focusedRectInRoot: Rect? = null
6161
var textFieldRectInRoot: Rect? = null
@@ -74,19 +74,24 @@ class LegacyPlatformTextInputServiceAdapterTest {
7474
snapshotFlow { request.imeOptions }.collect { imeOptions = it }
7575
}
7676
launch {
77-
request.outputValue.collect { outputValue = it }
77+
snapshotFlow { request.textLayoutResult() }.filterNotNull().collect {
78+
textLayoutResult = it
79+
}
7880
}
7981
launch {
80-
request.textLayoutResult.collect { textLayoutResult = it }
82+
snapshotFlow { request.focusedRectInRoot() }.filterNotNull().collect {
83+
focusedRectInRoot = it
84+
}
8185
}
8286
launch {
83-
request.focusedRectInRoot.collect { focusedRectInRoot = it }
87+
snapshotFlow { request.textFieldRectInRoot() }.filterNotNull().collect {
88+
textFieldRectInRoot = it
89+
}
8490
}
8591
launch {
86-
request.textFieldRectInRoot.collect { textFieldRectInRoot = it }
87-
}
88-
launch {
89-
request.textClippingRectInRoot.collect { textClippingRectInRoot = it }
92+
snapshotFlow { request.textClippingRectInRoot() }.filterNotNull().collect {
93+
textClippingRectInRoot = it
94+
}
9095
}
9196
}
9297
awaitCancellation()
@@ -107,12 +112,11 @@ class LegacyPlatformTextInputServiceAdapterTest {
107112
waitForIdle()
108113

109114
assertThat(value?.text).isEqualTo("abc")
115+
assertThat(value?.selection).isEqualTo(TextRange(3, 3))
110116
assertThat(state?.length).isEqualTo(3)
111117
assertThat(state?.selection).isEqualTo(TextRange(3, 3))
112118
assertThat(state?.let { it.substring(startIndex = 0, it.length) }).isEqualTo("abc")
113119
assertThat(imeOptions).isNotNull()
114-
assertThat(outputValue?.text).isEqualTo("abc")
115-
assertThat(outputValue?.selection).isEqualTo(TextRange(3, 3))
116120
assertThat(textLayoutResult?.layoutInput?.text?.text).isEqualTo("abc")
117121
assertThat(focusedRectInRoot).isNotNull()
118122
assertThat(textFieldRectInRoot?.isEmpty).isFalse()

compose/ui/ui-text/api/desktop/ui-text.api

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,12 +1396,6 @@ public abstract interface class androidx/compose/ui/text/input/PlatformTextInput
13961396
public fun updateTextLayoutResult (Landroidx/compose/ui/text/input/TextFieldValue;Landroidx/compose/ui/text/input/OffsetMapping;Landroidx/compose/ui/text/TextLayoutResult;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/geometry/Rect;Landroidx/compose/ui/geometry/Rect;)V
13971397
}
13981398

1399-
public abstract interface class androidx/compose/ui/text/input/PlatformTextInputService2 {
1400-
public abstract fun focusedRectChanged (Landroidx/compose/ui/geometry/Rect;)V
1401-
public abstract fun startInput (Landroidx/compose/ui/text/input/TextEditorState;Landroidx/compose/ui/text/input/ImeOptions;Lkotlin/jvm/functions/Function1;)V
1402-
public abstract fun stopInput ()V
1403-
}
1404-
14051399
public final class androidx/compose/ui/text/input/SetComposingRegionCommand : androidx/compose/ui/text/input/EditCommand {
14061400
public static final field $stable I
14071401
public fun <init> (II)V

compose/ui/ui-text/api/ui-text.klib.api

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,6 @@ abstract interface androidx.compose.ui.text.input/PlatformTextInputService { //
130130
open fun updateTextLayoutResult(androidx.compose.ui.text.input/TextFieldValue, androidx.compose.ui.text.input/OffsetMapping, androidx.compose.ui.text/TextLayoutResult, kotlin/Function1<androidx.compose.ui.graphics/Matrix, kotlin/Unit>, androidx.compose.ui.geometry/Rect, androidx.compose.ui.geometry/Rect) // androidx.compose.ui.text.input/PlatformTextInputService.updateTextLayoutResult|updateTextLayoutResult(androidx.compose.ui.text.input.TextFieldValue;androidx.compose.ui.text.input.OffsetMapping;androidx.compose.ui.text.TextLayoutResult;kotlin.Function1<androidx.compose.ui.graphics.Matrix,kotlin.Unit>;androidx.compose.ui.geometry.Rect;androidx.compose.ui.geometry.Rect){}[0]
131131
}
132132

133-
abstract interface androidx.compose.ui.text.input/PlatformTextInputService2 { // androidx.compose.ui.text.input/PlatformTextInputService2|null[0]
134-
abstract fun focusedRectChanged(androidx.compose.ui.geometry/Rect) // androidx.compose.ui.text.input/PlatformTextInputService2.focusedRectChanged|focusedRectChanged(androidx.compose.ui.geometry.Rect){}[0]
135-
abstract fun startInput(androidx.compose.ui.text.input/TextEditorState, androidx.compose.ui.text.input/ImeOptions, kotlin/Function1<kotlin/Function1<androidx.compose.ui.text.input/TextEditingScope, kotlin/Unit>, kotlin/Unit>) // androidx.compose.ui.text.input/PlatformTextInputService2.startInput|startInput(androidx.compose.ui.text.input.TextEditorState;androidx.compose.ui.text.input.ImeOptions;kotlin.Function1<kotlin.Function1<androidx.compose.ui.text.input.TextEditingScope,kotlin.Unit>,kotlin.Unit>){}[0]
136-
abstract fun stopInput() // androidx.compose.ui.text.input/PlatformTextInputService2.stopInput|stopInput(){}[0]
137-
}
138-
139133
abstract interface androidx.compose.ui.text.input/TextEditingScope { // androidx.compose.ui.text.input/TextEditingScope|null[0]
140134
abstract fun commitText(kotlin/CharSequence, kotlin/Int) // androidx.compose.ui.text.input/TextEditingScope.commitText|commitText(kotlin.CharSequence;kotlin.Int){}[0]
141135
abstract fun deleteSurroundingTextInCodePoints(kotlin/Int, kotlin/Int) // androidx.compose.ui.text.input/TextEditingScope.deleteSurroundingTextInCodePoints|deleteSurroundingTextInCodePoints(kotlin.Int;kotlin.Int){}[0]

compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/input/PlatformTextInputService2.kt

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package androidx.compose.ui.text.input
1818

1919
import androidx.compose.ui.ExperimentalComposeUiApi
20-
import androidx.compose.ui.geometry.Rect
2120
import androidx.compose.ui.text.TextRange
2221

2322
/**
@@ -41,58 +40,29 @@ interface TextEditorState : CharSequence {
4140
}
4241

4342
/**
44-
* The scope in which the [PlatformTextInputService2] implementation can make changes to the
43+
* The scope in which the text input service implementations can make changes to the
4544
* [TextEditorState].
4645
*/
4746
@ExperimentalComposeUiApi
4847
interface TextEditingScope {
4948
/**
5049
* Deletes text around the cursor.
5150
*
52-
* This intends to replicate [DeleteSurroundingTextInCodePointsCommand] for
53-
* [PlatformTextInputService2].
51+
* This intends to replicate [DeleteSurroundingTextInCodePointsCommand].
5452
*/
5553
fun deleteSurroundingTextInCodePoints(lengthBeforeCursor: Int, lengthAfterCursor: Int)
5654

5755
/**
5856
* Commits text and repositions the cursor.
5957
*
60-
* This intends to replicate [CommitTextCommand] for [PlatformTextInputService2].
58+
* This intends to replicate [CommitTextCommand].
6159
*/
6260
fun commitText(text: CharSequence, newCursorPosition: Int)
6361

6462
/**
6563
* Sets the composing text and repositions the cursor.
6664
*
67-
* This intends to replicate [SetComposingTextCommand] for [PlatformTextInputService2].
65+
* This intends to replicate [SetComposingTextCommand].
6866
*/
6967
fun setComposingText(text: CharSequence, newCursorPosition: Int)
70-
}
71-
72-
/**
73-
* The interface for classes responsible for platform-specific behaviors of text fields.
74-
*/
75-
@ExperimentalComposeUiApi
76-
interface PlatformTextInputService2 {
77-
/**
78-
* Starts the text input session for given text field.
79-
*/
80-
fun startInput(
81-
state: TextEditorState,
82-
imeOptions: ImeOptions,
83-
editText: (block: TextEditingScope.() -> Unit) -> Unit,
84-
)
85-
86-
/**
87-
* Ends the current text input session.
88-
*/
89-
fun stopInput()
90-
91-
/**
92-
* Notifies the implementation of the rectangle where the actual text editing happens (at the
93-
* caret).
94-
*
95-
* @param rect The rectangle, relative to root.
96-
*/
97-
fun focusedRectChanged(rect: Rect)
9868
}

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3702,15 +3702,14 @@ public abstract interface class androidx/compose/ui/platform/PlatformTextInputIn
37023702

37033703
public abstract interface class androidx/compose/ui/platform/PlatformTextInputMethodRequest {
37043704
public abstract fun getEditText ()Lkotlin/jvm/functions/Function1;
3705-
public abstract fun getFocusedRectInRoot ()Lkotlinx/coroutines/flow/Flow;
3705+
public abstract fun getFocusedRectInRoot ()Lkotlin/jvm/functions/Function0;
37063706
public abstract fun getImeOptions ()Landroidx/compose/ui/text/input/ImeOptions;
37073707
public abstract fun getOnEditCommand ()Lkotlin/jvm/functions/Function1;
37083708
public abstract fun getOnImeAction ()Lkotlin/jvm/functions/Function1;
3709-
public abstract fun getOutputValue ()Lkotlinx/coroutines/flow/Flow;
37103709
public abstract fun getState ()Landroidx/compose/ui/text/input/TextEditorState;
3711-
public abstract fun getTextClippingRectInRoot ()Lkotlinx/coroutines/flow/Flow;
3712-
public abstract fun getTextFieldRectInRoot ()Lkotlinx/coroutines/flow/Flow;
3713-
public abstract fun getTextLayoutResult ()Lkotlinx/coroutines/flow/Flow;
3710+
public abstract fun getTextClippingRectInRoot ()Lkotlin/jvm/functions/Function0;
3711+
public abstract fun getTextFieldRectInRoot ()Lkotlin/jvm/functions/Function0;
3712+
public abstract fun getTextLayoutResult ()Lkotlin/jvm/functions/Function0;
37143713
public abstract fun getValue ()Lkotlin/jvm/functions/Function0;
37153714
}
37163715

0 commit comments

Comments
 (0)