From 9c8473451d89903c08555bde5a6008b0f64b1010 Mon Sep 17 00:00:00 2001 From: "Evgeny @ SimpleX Chat" <259188159+evgeny-simplex@users.noreply.github.com> Date: Wed, 1 Apr 2026 14:34:17 +0000 Subject: [PATCH] better cursor position --- .../chat/simplex/common/views/chat/TextSelection.kt | 10 ++++++++-- .../simplex/common/views/chat/item/FramedItemView.kt | 9 ++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/TextSelection.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/TextSelection.kt index 7a71e05ecf..c5e03a01e3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/TextSelection.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/TextSelection.kt @@ -58,12 +58,18 @@ class SelectionManager { var range by mutableStateOf(null) private set + var anchorWindowY by mutableStateOf(0f) + private set + var anchorWindowX by mutableStateOf(0f) + private set var focusWindowY by mutableStateOf(0f) var focusWindowX by mutableStateOf(0f) - fun startSelection(startIndex: Int) { + fun startSelection(startIndex: Int, anchorY: Float, anchorX: Float) { range = SelectionRange(startIndex, -1, startIndex, -1) selectionState = SelectionState.Selecting + anchorWindowY = anchorY + anchorWindowX = anchorX } fun setAnchorOffset(offset: Int) { @@ -233,7 +239,7 @@ fun BoxScope.SelectionHandler( val idx = resolveIndexAtY(listState.value, localStart.y) Log.e(TAG, "dragStart localStart=$localStart windowStart=$windowStart idx=$idx") if (idx != null) { - manager.startSelection(idx) + manager.startSelection(idx, windowStart.y, windowStart.x) manager.focusWindowY = windowStart.y manager.focusWindowX = windowStart.x } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt index d6e7efd1eb..3c4d421a71 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt @@ -389,9 +389,9 @@ fun CIMarkdownText( val bounds = boundsState.value ?: return@LaunchedEffect val layout = layoutResultState.value ?: return@LaunchedEffect val offset = layout.getOffsetForPosition( - Offset(selectionManager.focusWindowX - bounds.left, selectionManager.focusWindowY - bounds.top) + Offset(selectionManager.anchorWindowX - bounds.left, selectionManager.anchorWindowY - bounds.top) ) - Log.e(TAG, "anchorOffset idx=$selectionIndex offset=$offset bounds=$bounds pointer=(${selectionManager.focusWindowX},${selectionManager.focusWindowY})") + Log.e(TAG, "anchorOffset idx=$selectionIndex offset=$offset bounds=$bounds pointer=(${selectionManager.anchorWindowX},${selectionManager.anchorWindowY})") selectionManager.setAnchorOffset(offset) } @@ -420,7 +420,10 @@ fun CIMarkdownText( Box( Modifier .padding(vertical = 7.dp, horizontal = 12.dp) - .then(if (selectionManager != null) Modifier.onGloballyPositioned { boundsState.value = it.boundsInWindow() } else Modifier) + .then(if (selectionManager != null) Modifier.onGloballyPositioned { + val pos = it.positionInWindow() + boundsState.value = Rect(pos.x, pos.y, pos.x + it.size.width, pos.y + it.size.height) + } else Modifier) ) { MarkdownText( text, if (text.isEmpty()) emptyList() else ci.formattedText, toggleSecrets = true,