Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request and handle cursor changes #613

Merged
merged 8 commits into from
Jan 19, 2024
Merged
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
14 changes: 7 additions & 7 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ android {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.7"
kotlinCompilerExtensionVersion = "1.5.8"
}
namespace 'com.dessalines.thumbkey'
}
Expand Down Expand Up @@ -92,16 +92,16 @@ dependencies {
implementation 'androidx.room:room-paging:2.6.1'

// LiveData
implementation 'androidx.compose.runtime:runtime-livedata:1.5.4'
implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.2"
implementation 'androidx.compose.runtime:runtime-livedata:1.6.0-rc01'
implementation "androidx.lifecycle:lifecycle-runtime-compose:2.7.0"

implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.9.21'
implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.9.22'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.compose.ui:ui:1.5.4'
implementation 'androidx.compose.ui:ui:1.6.0-rc01'
implementation 'androidx.compose.material3:material3:1.1.2'
implementation 'androidx.compose.material:material-icons-extended:1.5.4'
implementation 'androidx.compose.material:material-icons-extended-desktop:1.6.0-rc01'
implementation 'androidx.compose.material3:material3-window-size-class:1.1.2'
implementation 'androidx.compose.ui:ui-tooling:1.5.4'
implementation 'androidx.compose.ui:ui-tooling:1.6.0-rc01'
implementation 'androidx.activity:activity-compose:1.8.2'
implementation "com.louiscad.splitties:splitties-systemservices:3.0.0"
implementation "com.louiscad.splitties:splitties-views:3.0.0"
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/java/com/dessalines/thumbkey/IMEService.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.dessalines.thumbkey

import android.inputmethodservice.InputMethodService
import android.util.Log
import android.view.View
import android.view.inputmethod.CursorAnchorInfo
import android.view.inputmethod.EditorInfo
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
Expand All @@ -14,6 +16,8 @@ import androidx.savedstate.SavedStateRegistry
import androidx.savedstate.SavedStateRegistryController
import androidx.savedstate.SavedStateRegistryOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
import com.dessalines.thumbkey.utils.TAG
import kotlin.math.abs

class IMEService :
InputMethodService(),
Expand Down Expand Up @@ -68,6 +72,34 @@ class IMEService :
handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
}

// Cursor update Methods
override fun onUpdateCursorAnchorInfo(cursorAnchorInfo: CursorAnchorInfo) {
super.onUpdateCursorAnchorInfo(cursorAnchorInfo)

// If the cursor has moved at all vertically, or more than a small amount horizontally, the cursor has changed and multitap should be blocked.
// The horizontal buffer is because the cursor moves slightly based on the size of some of the characters (i.e '?') moving the cursor a little bit.
// It would be better to not use a magic number of 15, but I don't know what the ideal buffer is and it seems to work well, even when moving the cursor right before the multitap character
if (insertionMarkerBaseline != cursorAnchorInfo.insertionMarkerBaseline ||
abs(cursorAnchorInfo.insertionMarkerHorizontal - insertionMarkerHorizontal) > 15f
) {
cursorMoved = true
insertionMarkerBaseline = cursorAnchorInfo.insertionMarkerBaseline
Log.d(TAG, "cursor moved")
} else {
cursorMoved = false
}
// Always update the horizontal position. This prevents the movement of the cursor by the first space tap blocking consecutive tap actions.
insertionMarkerHorizontal = cursorAnchorInfo.insertionMarkerHorizontal
}

fun didCursorMove(): Boolean {
jm355 marked this conversation as resolved.
Show resolved Hide resolved
return cursorMoved
}

private var cursorMoved: Boolean = false
private var insertionMarkerBaseline: Float = 0f
private var insertionMarkerHorizontal: Float = 0f

// ViewModelStore Methods
override val viewModelStore = ViewModelStore()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ fun KeyboardKey(
// Set the last key info, and the tap count
val cAction = key.center.action
lastAction.value?.let { lastAction ->
if (lastAction == cAction) {
if (lastAction == cAction && !ime.didCursorMove()) {
tapCount += 1
} else {
tapCount = 0
Expand Down Expand Up @@ -226,7 +226,7 @@ fun KeyboardKey(
// Spacebar:
// Swipe up/down/left/right
// Slide gesture
// Wtih slide gesture deadzone to allow normal swipes
// With slide gesture deadzone to allow normal swipes
// Without deadzone
// Slide up to enter selection mode.
// Backspace key:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package com.dessalines.thumbkey.ui.components.keyboard

import android.content.Context
import android.media.AudioManager
import android.util.Log
import android.view.inputmethod.InputConnection.CURSOR_UPDATE_FILTER_INSERTION_MARKER
import android.view.inputmethod.InputConnection.CURSOR_UPDATE_MONITOR
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
Expand Down Expand Up @@ -60,6 +63,7 @@ import com.dessalines.thumbkey.utils.KeyAction
import com.dessalines.thumbkey.utils.KeyboardLayout
import com.dessalines.thumbkey.utils.KeyboardMode
import com.dessalines.thumbkey.utils.KeyboardPosition
import com.dessalines.thumbkey.utils.TAG
import com.dessalines.thumbkey.utils.getKeyboardMode
import com.dessalines.thumbkey.utils.keyboardPositionToAlignment
import com.dessalines.thumbkey.utils.toBool
Expand Down Expand Up @@ -139,6 +143,8 @@ fun KeyboardScreen(
val controllerKeys = listOf(EMOJI_BACK_KEY_ITEM, NUMERIC_KEY_ITEM, BACKSPACE_KEY_ITEM, RETURN_KEY_ITEM)
val keyboardHeight = Dp((keySize * controllerKeys.size) - (keyPadding * 2))

ctx.currentInputConnection.requestCursorUpdates(0)

Box(
modifier =
Modifier
Expand Down Expand Up @@ -296,6 +302,12 @@ fun KeyboardScreen(
}
}
} else {
if (ctx.currentInputConnection.requestCursorUpdates(CURSOR_UPDATE_MONITOR or CURSOR_UPDATE_FILTER_INSERTION_MARKER)) {
dessalines marked this conversation as resolved.
Show resolved Hide resolved
Log.d(TAG, "request for cursor updates succeeded, cursor updates will be provided")
} else {
Log.d(TAG, "request for cursor updates failed, cursor updates will not be provided")
}

Box(
contentAlignment = alignment,
modifier =
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ buildscript {
plugins {
id 'com.android.application' version '8.2.1' apply false
id 'com.android.library' version '8.2.1' apply false
id 'org.jetbrains.kotlin.android' version '1.9.21' apply false
id 'org.jetbrains.kotlin.android' version '1.9.22' apply false
id 'org.jmailen.kotlinter' version "4.1.0" apply false
id 'com.google.devtools.ksp' version "1.9.21-1.0.15" apply false
id 'com.google.devtools.ksp' version "1.9.22-1.0.16" apply false
}

subprojects {
Expand Down