Compare commits

..

6 Commits

8 changed files with 119 additions and 28 deletions

View File

@ -37,7 +37,7 @@ android {
}
dependencies {
implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.9.0")
implementation("androidx.room:room-common:2.5.2")

View File

@ -1,12 +1,12 @@
package net.mezimmah.wkt9
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.inputmethodservice.InputMethodService
import android.media.AudioManager
import android.media.MediaRecorder
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.text.InputType
import android.util.Log
@ -14,6 +14,8 @@ import android.view.KeyEvent
import android.view.View
import android.view.ViewConfiguration
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.ExtractedTextRequest
import android.view.inputmethod.InlineSuggestionsRequest
import android.view.inputmethod.InputMethodManager
import android.view.textservice.SentenceSuggestionsInfo
import android.view.textservice.SpellCheckerSession
@ -23,6 +25,7 @@ import android.view.textservice.TextServicesManager
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import android.widget.inline.InlinePresentationSpec
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@ -50,6 +53,7 @@ import okio.IOException
import java.io.File
import java.util.Locale
class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListener {
private val tag = "WKT9"
@ -135,6 +139,14 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
super.onCreate()
}
override fun onCreateInlineSuggestionsRequest(uiExtras: Bundle): InlineSuggestionsRequest? {
Log.d(tag, "Here we are")
return InlineSuggestionsRequest.Builder(ArrayList<InlinePresentationSpec>())
.setMaxSuggestionCount(InlineSuggestionsRequest.SUGGESTION_COUNT_UNLIMITED)
.build()
}
@SuppressLint("InflateParams")
override fun onCreateInputView(): View? {
inputView = layoutInflater.inflate(R.layout.suggestions, null)
@ -204,28 +216,8 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
}
override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) {
val inputType = attribute?.inputType
val inputClass = inputType?.and(InputType.TYPE_MASK_CLASS) ?: 0
val typeVariation = inputType?.and(InputType.TYPE_MASK_VARIATION) ?: 0
val typeFlags = inputType?.and(InputType.TYPE_MASK_FLAGS) ?: 0
cursorPosition = attribute?.initialSelEnd ?: 0
val forceNumeric = resources.getStringArray(R.array.input_mode_numeric)
if (forceNumeric.contains(attribute?.packageName)) enableInputMode(WKT9InputMode.NUMERIC)
else {
when (inputClass) {
InputType.TYPE_CLASS_DATETIME,
InputType.TYPE_CLASS_NUMBER,
InputType.TYPE_CLASS_PHONE -> enableInputMode(WKT9InputMode.NUMERIC)
InputType.TYPE_CLASS_TEXT -> enableTextInputMode(typeVariation, typeFlags)
else -> enableInputMode(WKT9InputMode.IDLE)
}
}
updateInputStatus()
if (restarting) restartInput()
else startInput(attribute)
super.onStartInput(attribute, restarting)
}
@ -475,6 +467,7 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
if (res.decreaseVolume) onDecreaseVolume()
if (res.increaseBrightness) onIncreaseBrightness()
if (res.decreaseBrightness) onDecreaseBrightness()
if (res.keyEvent != null) onKeyEvent(res.keyEvent)
return res.consumed
}
@ -574,14 +567,32 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
}
private fun onDelete(beforeCursor: Int, afterCursor: Int) {
val newCursorPosition = cursorPosition - beforeCursor
clearCandidates()
deleteText(beforeCursor, afterCursor)
if (newCursorPosition < 1) return
val extractedTextRequest = ExtractedTextRequest()
val request = currentInputConnection?.getExtractedText(extractedTextRequest, 0)
val text = request?.text
text?.let {
Log.d(tag, "Last char before cursor = ${it[newCursorPosition - 1]}")
}
// Log.d(tag, "Text: $sub, ${text?.length}, $cursorPosition")
}
private fun onFocus() {
requestShowSelf(InputMethodManager.SHOW_IMPLICIT)
}
private fun onKeyEvent(keyEvent: KeyEvent) {
currentInputConnection?.sendKeyEvent(keyEvent)
}
private fun onToggleFunctionMode() {
if (inputMode is FNInputMode) enableInputMode(lastInputMode)
else enableInputMode(WKT9InputMode.FN)
@ -749,6 +760,12 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
composeText(candidates[candidateIndex])
}
private fun restartInput() {
inputMode?.restart()
clearCandidates()
}
private fun requestWriteSettings() {
val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
@ -758,6 +775,35 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
startActivity(intent)
}
private fun startInput(attribute: EditorInfo?) {
val inputType = attribute?.inputType
val inputClass = inputType?.and(InputType.TYPE_MASK_CLASS) ?: 0
val typeVariation = inputType?.and(InputType.TYPE_MASK_VARIATION) ?: 0
val typeFlags = inputType?.and(InputType.TYPE_MASK_FLAGS) ?: 0
cursorPosition = attribute?.initialSelEnd ?: 0
val forceNumeric = resources.getStringArray(R.array.input_mode_numeric)
if (forceNumeric.contains(attribute?.packageName)) enableInputMode(WKT9InputMode.NUMERIC)
else {
when (inputClass) {
InputType.TYPE_CLASS_DATETIME,
InputType.TYPE_CLASS_NUMBER,
InputType.TYPE_CLASS_PHONE -> enableInputMode(WKT9InputMode.NUMERIC)
InputType.TYPE_CLASS_TEXT -> enableTextInputMode(typeVariation, typeFlags)
else -> enableInputMode(WKT9InputMode.IDLE)
}
}
attribute?.packageName?.let {
inputMode?.packageName(it)
}
updateInputStatus()
}
private fun updateInputStatus() {
inputStatus = inputMode?.status ?: Status.CAP

View File

@ -1,11 +1,14 @@
package net.mezimmah.wkt9.inputmode
import android.util.Log
import net.mezimmah.wkt9.keypad.Key
import net.mezimmah.wkt9.keypad.KeyCommandResolver
import net.mezimmah.wkt9.keypad.KeyEventResult
import net.mezimmah.wkt9.keypad.KeyLayout
open class BaseInputMode: InputMode {
protected var packageName: String? = null
protected val tag = "WKT9"
protected var newKey = true
@ -42,6 +45,14 @@ open class BaseInputMode: InputMode {
return KeyEventResult()
}
override fun packageName(packageName: String) {
this.packageName = packageName
}
override fun restart() {
Log.d(tag, "Restart should be handled by individual input modes")
}
protected fun commit(text: String, composing: Boolean): KeyEventResult {
return KeyEventResult(
consumed = true,

View File

@ -1,6 +1,7 @@
package net.mezimmah.wkt9.inputmode
import android.util.Log
import android.view.KeyEvent
import net.mezimmah.wkt9.keypad.Command
import net.mezimmah.wkt9.keypad.Key
import net.mezimmah.wkt9.keypad.KeyEventResult
@ -16,6 +17,7 @@ class IdleInputMode : BaseInputMode() {
override fun onKeyDown(key: Key, composing: Boolean): KeyEventResult {
return when(keyCommandResolver.getCommand(key)) {
Command.FN -> KeyEventResult(true)
Command.SELECT -> conditionalSelect()
else -> KeyEventResult(false)
}
}
@ -46,4 +48,17 @@ class IdleInputMode : BaseInputMode() {
else -> KeyEventResult(false)
}
}
private fun conditionalSelect(): KeyEventResult {
return when (packageName) {
"com.android.camera2" -> {
KeyEventResult(
consumed = true,
keyEvent = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_CAMERA)
)
}
else -> KeyEventResult(consumed = false)
}
}
}

View File

@ -16,4 +16,8 @@ interface InputMode {
fun afterKeyDown(key: Key, composing: Boolean): KeyEventResult
fun afterKeyLongDown(key: Key, keyDownMS: Long, composing: Boolean): KeyEventResult
fun packageName(packageName: String)
fun restart()
}

View File

@ -65,6 +65,10 @@ class WordInputMode: BaseInputMode() {
}
}
override fun restart() {
reset()
}
override fun commitNumber(key: Key, composing: Boolean): KeyEventResult {
codeWord.clear()
@ -72,9 +76,17 @@ class WordInputMode: BaseInputMode() {
}
override fun deleteCharacter(composing: Boolean): KeyEventResult {
codeWord.clear()
return if (codeWord.length > 1) {
codeWord.deleteAt(codeWord.length - 1)
return super.deleteCharacter(composing)
KeyEventResult(
codeWord = codeWord
)
} else {
codeWord.clear()
super.deleteCharacter(composing)
}
}
override fun finalizeWordOrSentence(composing: Boolean): KeyEventResult {

View File

@ -1,5 +1,6 @@
package net.mezimmah.wkt9.keypad
import android.view.KeyEvent
import net.mezimmah.wkt9.inputmode.WKT9InputMode
import java.lang.StringBuilder
@ -27,5 +28,6 @@ data class KeyEventResult(
val increaseVolume: Boolean = false,
val decreaseVolume: Boolean = false,
val increaseBrightness: Boolean = false,
val decreaseBrightness: Boolean = false
val decreaseBrightness: Boolean = false,
val keyEvent: KeyEvent? = null
)

View File

@ -1,5 +1,6 @@
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
android:settingsActivity="net.mezimmah.wkt9.preferences.PreferencesActivity">
android:settingsActivity="net.mezimmah.wkt9.preferences.PreferencesActivity"
android:supportsInlineSuggestions="true">
<subtype
android:label="English US"