Compare commits
6 Commits
cbaa339c37
...
3b5b77c540
Author | SHA1 | Date | |
---|---|---|---|
3b5b77c540 | |||
bf7adcbb3a | |||
add9d0d020 | |||
fcb15459d0 | |||
a29d2d1062 | |||
e86ff3b3b2 |
@ -37,7 +37,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
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("androidx.appcompat:appcompat:1.6.1")
|
||||||
implementation("com.google.android.material:material:1.9.0")
|
implementation("com.google.android.material:material:1.9.0")
|
||||||
implementation("androidx.room:room-common:2.5.2")
|
implementation("androidx.room:room-common:2.5.2")
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package net.mezimmah.wkt9
|
package net.mezimmah.wkt9
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.inputmethodservice.InputMethodService
|
import android.inputmethodservice.InputMethodService
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.media.MediaRecorder
|
import android.media.MediaRecorder
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@ -14,6 +14,8 @@ import android.view.KeyEvent
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewConfiguration
|
import android.view.ViewConfiguration
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import android.view.inputmethod.ExtractedTextRequest
|
||||||
|
import android.view.inputmethod.InlineSuggestionsRequest
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.view.textservice.SentenceSuggestionsInfo
|
import android.view.textservice.SentenceSuggestionsInfo
|
||||||
import android.view.textservice.SpellCheckerSession
|
import android.view.textservice.SpellCheckerSession
|
||||||
@ -23,6 +25,7 @@ import android.view.textservice.TextServicesManager
|
|||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import android.widget.inline.InlinePresentationSpec
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
@ -50,6 +53,7 @@ import okio.IOException
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
|
||||||
class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListener {
|
class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListener {
|
||||||
private val tag = "WKT9"
|
private val tag = "WKT9"
|
||||||
|
|
||||||
@ -135,6 +139,14 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
|
|||||||
super.onCreate()
|
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")
|
@SuppressLint("InflateParams")
|
||||||
override fun onCreateInputView(): View? {
|
override fun onCreateInputView(): View? {
|
||||||
inputView = layoutInflater.inflate(R.layout.suggestions, null)
|
inputView = layoutInflater.inflate(R.layout.suggestions, null)
|
||||||
@ -204,28 +216,8 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) {
|
override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) {
|
||||||
val inputType = attribute?.inputType
|
if (restarting) restartInput()
|
||||||
val inputClass = inputType?.and(InputType.TYPE_MASK_CLASS) ?: 0
|
else startInput(attribute)
|
||||||
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()
|
|
||||||
|
|
||||||
super.onStartInput(attribute, restarting)
|
super.onStartInput(attribute, restarting)
|
||||||
}
|
}
|
||||||
@ -475,6 +467,7 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
|
|||||||
if (res.decreaseVolume) onDecreaseVolume()
|
if (res.decreaseVolume) onDecreaseVolume()
|
||||||
if (res.increaseBrightness) onIncreaseBrightness()
|
if (res.increaseBrightness) onIncreaseBrightness()
|
||||||
if (res.decreaseBrightness) onDecreaseBrightness()
|
if (res.decreaseBrightness) onDecreaseBrightness()
|
||||||
|
if (res.keyEvent != null) onKeyEvent(res.keyEvent)
|
||||||
|
|
||||||
return res.consumed
|
return res.consumed
|
||||||
}
|
}
|
||||||
@ -574,14 +567,32 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun onDelete(beforeCursor: Int, afterCursor: Int) {
|
private fun onDelete(beforeCursor: Int, afterCursor: Int) {
|
||||||
|
val newCursorPosition = cursorPosition - beforeCursor
|
||||||
|
|
||||||
clearCandidates()
|
clearCandidates()
|
||||||
deleteText(beforeCursor, afterCursor)
|
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() {
|
private fun onFocus() {
|
||||||
requestShowSelf(InputMethodManager.SHOW_IMPLICIT)
|
requestShowSelf(InputMethodManager.SHOW_IMPLICIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onKeyEvent(keyEvent: KeyEvent) {
|
||||||
|
currentInputConnection?.sendKeyEvent(keyEvent)
|
||||||
|
}
|
||||||
|
|
||||||
private fun onToggleFunctionMode() {
|
private fun onToggleFunctionMode() {
|
||||||
if (inputMode is FNInputMode) enableInputMode(lastInputMode)
|
if (inputMode is FNInputMode) enableInputMode(lastInputMode)
|
||||||
else enableInputMode(WKT9InputMode.FN)
|
else enableInputMode(WKT9InputMode.FN)
|
||||||
@ -749,6 +760,12 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
|
|||||||
composeText(candidates[candidateIndex])
|
composeText(candidates[candidateIndex])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun restartInput() {
|
||||||
|
inputMode?.restart()
|
||||||
|
|
||||||
|
clearCandidates()
|
||||||
|
}
|
||||||
|
|
||||||
private fun requestWriteSettings() {
|
private fun requestWriteSettings() {
|
||||||
val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
|
val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
|
||||||
|
|
||||||
@ -758,6 +775,35 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
|
|||||||
startActivity(intent)
|
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() {
|
private fun updateInputStatus() {
|
||||||
inputStatus = inputMode?.status ?: Status.CAP
|
inputStatus = inputMode?.status ?: Status.CAP
|
||||||
|
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package net.mezimmah.wkt9.inputmode
|
package net.mezimmah.wkt9.inputmode
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import net.mezimmah.wkt9.keypad.Key
|
import net.mezimmah.wkt9.keypad.Key
|
||||||
import net.mezimmah.wkt9.keypad.KeyCommandResolver
|
import net.mezimmah.wkt9.keypad.KeyCommandResolver
|
||||||
import net.mezimmah.wkt9.keypad.KeyEventResult
|
import net.mezimmah.wkt9.keypad.KeyEventResult
|
||||||
import net.mezimmah.wkt9.keypad.KeyLayout
|
import net.mezimmah.wkt9.keypad.KeyLayout
|
||||||
|
|
||||||
open class BaseInputMode: InputMode {
|
open class BaseInputMode: InputMode {
|
||||||
|
protected var packageName: String? = null
|
||||||
|
|
||||||
protected val tag = "WKT9"
|
protected val tag = "WKT9"
|
||||||
|
|
||||||
protected var newKey = true
|
protected var newKey = true
|
||||||
@ -42,6 +45,14 @@ open class BaseInputMode: InputMode {
|
|||||||
return KeyEventResult()
|
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 {
|
protected fun commit(text: String, composing: Boolean): KeyEventResult {
|
||||||
return KeyEventResult(
|
return KeyEventResult(
|
||||||
consumed = true,
|
consumed = true,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.mezimmah.wkt9.inputmode
|
package net.mezimmah.wkt9.inputmode
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.view.KeyEvent
|
||||||
import net.mezimmah.wkt9.keypad.Command
|
import net.mezimmah.wkt9.keypad.Command
|
||||||
import net.mezimmah.wkt9.keypad.Key
|
import net.mezimmah.wkt9.keypad.Key
|
||||||
import net.mezimmah.wkt9.keypad.KeyEventResult
|
import net.mezimmah.wkt9.keypad.KeyEventResult
|
||||||
@ -16,6 +17,7 @@ class IdleInputMode : BaseInputMode() {
|
|||||||
override fun onKeyDown(key: Key, composing: Boolean): KeyEventResult {
|
override fun onKeyDown(key: Key, composing: Boolean): KeyEventResult {
|
||||||
return when(keyCommandResolver.getCommand(key)) {
|
return when(keyCommandResolver.getCommand(key)) {
|
||||||
Command.FN -> KeyEventResult(true)
|
Command.FN -> KeyEventResult(true)
|
||||||
|
Command.SELECT -> conditionalSelect()
|
||||||
else -> KeyEventResult(false)
|
else -> KeyEventResult(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,4 +48,17 @@ class IdleInputMode : BaseInputMode() {
|
|||||||
else -> KeyEventResult(false)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -16,4 +16,8 @@ interface InputMode {
|
|||||||
fun afterKeyDown(key: Key, composing: Boolean): KeyEventResult
|
fun afterKeyDown(key: Key, composing: Boolean): KeyEventResult
|
||||||
|
|
||||||
fun afterKeyLongDown(key: Key, keyDownMS: Long, composing: Boolean): KeyEventResult
|
fun afterKeyLongDown(key: Key, keyDownMS: Long, composing: Boolean): KeyEventResult
|
||||||
|
|
||||||
|
fun packageName(packageName: String)
|
||||||
|
|
||||||
|
fun restart()
|
||||||
}
|
}
|
@ -65,6 +65,10 @@ class WordInputMode: BaseInputMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun restart() {
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
override fun commitNumber(key: Key, composing: Boolean): KeyEventResult {
|
override fun commitNumber(key: Key, composing: Boolean): KeyEventResult {
|
||||||
codeWord.clear()
|
codeWord.clear()
|
||||||
|
|
||||||
@ -72,9 +76,17 @@ class WordInputMode: BaseInputMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun deleteCharacter(composing: Boolean): KeyEventResult {
|
override fun deleteCharacter(composing: Boolean): KeyEventResult {
|
||||||
|
return if (codeWord.length > 1) {
|
||||||
|
codeWord.deleteAt(codeWord.length - 1)
|
||||||
|
|
||||||
|
KeyEventResult(
|
||||||
|
codeWord = codeWord
|
||||||
|
)
|
||||||
|
} else {
|
||||||
codeWord.clear()
|
codeWord.clear()
|
||||||
|
|
||||||
return super.deleteCharacter(composing)
|
super.deleteCharacter(composing)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun finalizeWordOrSentence(composing: Boolean): KeyEventResult {
|
override fun finalizeWordOrSentence(composing: Boolean): KeyEventResult {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.mezimmah.wkt9.keypad
|
package net.mezimmah.wkt9.keypad
|
||||||
|
|
||||||
|
import android.view.KeyEvent
|
||||||
import net.mezimmah.wkt9.inputmode.WKT9InputMode
|
import net.mezimmah.wkt9.inputmode.WKT9InputMode
|
||||||
import java.lang.StringBuilder
|
import java.lang.StringBuilder
|
||||||
|
|
||||||
@ -27,5 +28,6 @@ data class KeyEventResult(
|
|||||||
val increaseVolume: Boolean = false,
|
val increaseVolume: Boolean = false,
|
||||||
val decreaseVolume: Boolean = false,
|
val decreaseVolume: Boolean = false,
|
||||||
val increaseBrightness: Boolean = false,
|
val increaseBrightness: Boolean = false,
|
||||||
val decreaseBrightness: Boolean = false
|
val decreaseBrightness: Boolean = false,
|
||||||
|
val keyEvent: KeyEvent? = null
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
|
<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
|
<subtype
|
||||||
android:label="English US"
|
android:label="English US"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user