From 67d2f8e680dd58a2a93b0cf3a6913d62bad46b37 Mon Sep 17 00:00:00 2001 From: Naveen Singh Date: Thu, 14 Aug 2025 14:56:13 +0530 Subject: [PATCH 1/2] fix: perform haptic feedback on cursor control This uses `HapticFeedbackConstants.TEXT_HANDLE_MOVE`, which may not work on all devices. See: https://github.com/FossifyOrg/Keyboard/issues/222 --- .../keyboard/services/SimpleKeyboardIME.kt | 19 ++++++++++++------- .../fossify/keyboard/views/MyKeyboardView.kt | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/app/src/main/kotlin/org/fossify/keyboard/services/SimpleKeyboardIME.kt b/app/src/main/kotlin/org/fossify/keyboard/services/SimpleKeyboardIME.kt index 5c42b814..fa7d607d 100644 --- a/app/src/main/kotlin/org/fossify/keyboard/services/SimpleKeyboardIME.kt +++ b/app/src/main/kotlin/org/fossify/keyboard/services/SimpleKeyboardIME.kt @@ -417,15 +417,20 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared } private fun moveCursor(moveRight: Boolean) { - val extractedText = currentInputConnection?.getExtractedText(ExtractedTextRequest(), 0) ?: return - var newCursorPosition = extractedText.selectionStart - newCursorPosition = if (moveRight) { - newCursorPosition + 1 + val inputConnection = currentInputConnection + val extractedText = inputConnection.getExtractedText(ExtractedTextRequest(), 0) ?: return + val text = extractedText.text ?: return + val oldPos = extractedText.selectionStart + val newPos = if (moveRight) { + oldPos + 1 } else { - newCursorPosition - 1 - } + oldPos - 1 + }.coerceIn(0, text.length) - currentInputConnection?.setSelection(newCursorPosition, newCursorPosition) + if (newPos != oldPos) { + inputConnection?.setSelection(newPos, newPos) + keyboardView?.performHapticHandleMove() + } } private fun getImeOptionsActionId(): Int { diff --git a/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt b/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt index 9e682d3f..ace7ddc2 100644 --- a/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt +++ b/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt @@ -14,6 +14,7 @@ import android.os.Build import android.os.Handler import android.os.Looper import android.os.Message +import android.os.SystemClock import android.util.AttributeSet import android.util.TypedValue import android.view.* @@ -33,6 +34,7 @@ import androidx.emoji2.text.EmojiCompat.EMOJI_SUPPORTED import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup import org.fossify.commons.extensions.* import org.fossify.commons.helpers.ensureBackgroundThread +import org.fossify.commons.helpers.isOreoMr1Plus import org.fossify.commons.helpers.isPiePlus import org.fossify.keyboard.R import org.fossify.keyboard.activities.ManageClipboardItemsActivity @@ -143,6 +145,7 @@ class MyKeyboardView @JvmOverloads constructor( private var mTopSmallNumberMarginHeight = 0f private val mSpaceMoveThreshold: Int private var ignoreTouches = false + private var lastHandleMoveAt = 0L private var mKeyBackground: Drawable? = null private var mShowKeyBorders: Boolean = false @@ -185,6 +188,7 @@ class MyKeyboardView @JvmOverloads constructor( private const val REPEAT_INTERVAL = 50 // ~20 keys per second private const val REPEAT_START_DELAY = 400 private val LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout() + private const val HANDLE_MOVE_MIN_MS = 30L } init { @@ -491,6 +495,20 @@ class MyKeyboardView @JvmOverloads constructor( } } + fun performHapticHandleMove() { + if (!context.config.vibrateOnKeypress) return + val now = SystemClock.uptimeMillis() + if (now - lastHandleMoveAt < HANDLE_MOVE_MIN_MS) return + lastHandleMoveAt = now + if (isOreoMr1Plus()) { + @Suppress("DEPRECATION") + performHapticFeedback( + HapticFeedbackConstants.TEXT_HANDLE_MOVE, + HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING + ) + } + } + /** * Sets the state of the shift key of the keyboard, if any. * @param shifted whether or not to enable the state of the shift key From 855a833e8d339217117d5d1070823d04d03a1f13 Mon Sep 17 00:00:00 2001 From: Naveen Singh Date: Thu, 14 Aug 2025 15:50:24 +0530 Subject: [PATCH 2/2] fix: bump `HANDLE_MOVE_MIN_MS` to 35ms Less buzzing when swiping quickly on some devices. --- .../main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt b/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt index ace7ddc2..3152f89b 100644 --- a/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt +++ b/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt @@ -188,7 +188,7 @@ class MyKeyboardView @JvmOverloads constructor( private const val REPEAT_INTERVAL = 50 // ~20 keys per second private const val REPEAT_START_DELAY = 400 private val LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout() - private const val HANDLE_MOVE_MIN_MS = 30L + private const val HANDLE_MOVE_MIN_MS = 35L } init {