Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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 @@ -24,6 +24,7 @@ import androidx.compose.foundation.text.selection.TextFieldSelectionManager
import androidx.compose.foundation.text.selection.awaitSelectionGestures
import androidx.compose.foundation.text.selection.getTextFieldSelectionLayout
import androidx.compose.foundation.text.selection.isSelectionHandleInVisibleBound
import androidx.compose.foundation.text.selection.updateSelectionTouchMode
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
Expand All @@ -50,31 +51,28 @@ internal fun Modifier.cupertinoTextFieldPointer(
readOnly: Boolean,
offsetMapping: OffsetMapping
): Modifier = if (enabled) {
// TODO switch to ".updateSelectionTouchMode { state.isInTouchMode = it }" as in defaultTextFieldPointer
if (isInTouchMode) {
val longPressHandlerModifier = getLongPressHandlerModifier(state, offsetMapping, manager)
val tapHandlerModifier = getTapHandlerModifier(
interactionSource,
state,
focusRequester,
readOnly,
offsetMapping,
manager
this
.updateSelectionTouchMode {
state.isInTouchMode = it
}
.then(
getTapHandlerModifier(
interactionSource,
state,
focusRequester,
readOnly,
offsetMapping,
manager
)
)
this
.then(tapHandlerModifier)
.then(longPressHandlerModifier)
.pointerHoverIcon(PointerIcon.Text)
} else {
this
.pointerInput(manager.mouseSelectionObserver, manager.touchSelectionObserver) {
awaitSelectionGestures(
manager.mouseSelectionObserver,
manager.touchSelectionObserver,
)
}
.pointerHoverIcon(PointerIcon.Text)
}
.then(getLongPressHandlerModifier(state, offsetMapping, manager))
.pointerInput(manager.mouseSelectionObserver, manager.touchSelectionObserver) {
awaitSelectionGestures(
manager.mouseSelectionObserver,
manager.touchSelectionObserver,
)
}
.pointerHoverIcon(PointerIcon.Text)
} else {
this
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,10 @@ internal actual fun createLegacyPlatformTextInputServiceAdapter():
focusedRectInRoot = { focusedRectInRoot },
textFieldRectInRoot = { textFieldRectInRoot },
textClippingRectInRoot = { textClippingRectInRoot },
editText = editBlock
editText = editBlock,
updateTouchMode = {
textInputModifierNode?.legacyTextFieldState?.isInTouchMode = it
}
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ internal actual suspend fun PlatformTextInputSession.platformSpecificTextInputSe
focusedRectInRoot = ::focusedRectInRoot,
textFieldRectInRoot = ::textFieldRectInRoot,
textClippingRectInRoot = ::textClippingRectInRoot,
editText = ::editText
editText = ::editText,
updateTouchMode = { updateTouchMode(it) }
)
)
}
Expand Down Expand Up @@ -235,5 +236,6 @@ internal data class SkikoPlatformTextInputMethodRequest(
override val focusedRectInRoot: () -> Rect?,
override val textFieldRectInRoot: () -> Rect?,
override val textClippingRectInRoot: () -> Rect?,
override val editText: (block: TextEditingScope.() -> Unit) -> Unit
override val editText: (block: TextEditingScope.() -> Unit) -> Unit,
override val updateTouchMode: (Boolean) -> Unit,
): PlatformTextInputMethodRequest
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,7 @@ actual interface PlatformTextInputMethodRequest {
*/
@ExperimentalComposeUiApi
val editText: (block: TextEditingScope.() -> Unit) -> Unit

@ExperimentalComposeUiApi
val updateTouchMode: (Boolean) -> Unit
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ internal class UIKitTextInputService(
private var _tempCursorPos: Int? = null
private val mainScope = MainScope()

fun setUpdateTouchMode(updateTouchMode: ((Boolean) -> Unit)?) {
textUIView?.updateTouchMode = updateTouchMode
}

override fun startInput(
value: TextFieldValue,
imeOptions: ImeOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,8 @@ internal class ComposeSceneMediator(
onImeActionPerformed = request.onImeAction ?: {}
)

textInputService.setUpdateTouchMode(request.updateTouchMode)

continuation.invokeOnCancellation {
textInputService.stopInput()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ import platform.UIKit.NSWritingDirectionNatural
import platform.UIKit.UIEvent
import platform.UIKit.UIKeyInputProtocol
import platform.UIKit.UIKeyboardAppearance
import platform.UIKit.UIKeyboardHIDUsageKeyboardLeftAlt
import platform.UIKit.UIKeyboardHIDUsageKeyboardLeftControl
import platform.UIKit.UIKeyboardHIDUsageKeyboardLeftGUI
import platform.UIKit.UIKeyboardHIDUsageKeyboardLeftShift
import platform.UIKit.UIKeyboardHIDUsageKeyboardRightAlt
import platform.UIKit.UIKeyboardHIDUsageKeyboardRightControl
import platform.UIKit.UIKeyboardHIDUsageKeyboardRightGUI
import platform.UIKit.UIKeyboardHIDUsageKeyboardRightShift
import platform.UIKit.UIKeyboardType
import platform.UIKit.UIPress
import platform.UIKit.UIPressesEvent
Expand Down Expand Up @@ -95,11 +103,13 @@ internal class IntermediateTextInputUIView(
private val mainScope = MainScope()

/**
* Callback to handle keyboard presses. The parameter is a [Set] of [UIPress] objects.
* Callback to handle physical keyboard presses. The parameter is a [Set] of [UIPress] objects.
* Erasure happens due to K/N not supporting Obj-C lightweight generics.
*/
var onKeyboardPresses: (Set<*>) -> Unit = NoOpOnKeyboardPresses

var updateTouchMode: ((Boolean) -> Unit)? = null

var inputTraits: SkikoUITextInputTraits = EmptyInputTraits

override fun inputView(): UIView? = inputTraits.inputView()
Expand All @@ -126,8 +136,13 @@ internal class IntermediateTextInputUIView(
}

override fun pressesBegan(presses: Set<*>, withEvent: UIPressesEvent?) {
onKeyboardPresses(presses)
@Suppress("UNCHECKED_CAST")
if (!onlyModifiersPressed(presses as Set<UIPress>)) {
// Touch mode update, this shouldn't be triggered if only modifiers keys are pressed
updateTouchMode?.invoke(false)
}

onKeyboardPresses(presses)
super.pressesBegan(presses, withEvent)
}

Expand All @@ -136,6 +151,10 @@ internal class IntermediateTextInputUIView(
super.pressesEnded(presses, withEvent)
}

private fun onlyModifiersPressed(presses: Set<UIPress>): Boolean {
return presses.all { it.key?.keyCode in modifierKeys }
}

override fun hitTest(point: CValue<CGPoint>, withEvent: UIEvent?): UIView? {
return if (input == null) {
null
Expand Down Expand Up @@ -580,3 +599,17 @@ private fun UITextRange.toTextRange(): TextRange {

private fun TextRange.toUITextRange(): UITextRange =
IntermediateTextRange(start = start, end = end)

/**
* A set of keyboard modifier keys used for handling input events.
*/
private val modifierKeys = setOf(
UIKeyboardHIDUsageKeyboardLeftShift,
UIKeyboardHIDUsageKeyboardRightShift,
UIKeyboardHIDUsageKeyboardLeftControl,
UIKeyboardHIDUsageKeyboardRightControl,
UIKeyboardHIDUsageKeyboardLeftAlt,
UIKeyboardHIDUsageKeyboardRightAlt,
UIKeyboardHIDUsageKeyboardLeftGUI, // Left Command / Super / Win
UIKeyboardHIDUsageKeyboardRightGUI, // Right Command / Super / Win
)
Loading