diff --git a/app/src/main/kotlin/dev/patrickgold/florisboard/FlorisImeService.kt b/app/src/main/kotlin/dev/patrickgold/florisboard/FlorisImeService.kt index d3c1754f..d51dd3f7 100644 --- a/app/src/main/kotlin/dev/patrickgold/florisboard/FlorisImeService.kt +++ b/app/src/main/kotlin/dev/patrickgold/florisboard/FlorisImeService.kt @@ -32,6 +32,7 @@ import android.view.inputmethod.EditorInfo import android.view.inputmethod.InlineSuggestionsRequest import android.view.inputmethod.InlineSuggestionsResponse import android.view.inputmethod.InputConnection +import android.view.inputmethod.InputMethodInfo import android.view.inputmethod.InputMethodManager import android.widget.FrameLayout import android.widget.LinearLayout @@ -95,6 +96,7 @@ import dev.patrickgold.florisboard.lib.android.isOrientationLandscape import dev.patrickgold.florisboard.lib.android.isOrientationPortrait import dev.patrickgold.florisboard.lib.android.launchActivity import dev.patrickgold.florisboard.lib.android.setLocale +import dev.patrickgold.florisboard.lib.android.showShortToast import dev.patrickgold.florisboard.lib.android.systemServiceOrNull import dev.patrickgold.florisboard.lib.compose.FlorisButton import dev.patrickgold.florisboard.lib.compose.ProvideLocalizedResources @@ -215,6 +217,29 @@ class FlorisImeService : LifecycleInputMethodService() { } return false } + + fun switchToVoiceInputMethod(): Boolean { + val ims = FlorisImeServiceReference.get() ?: return false + val imm = ims.systemServiceOrNull(InputMethodManager::class) ?: return false + val list: List = imm.enabledInputMethodList + for (el in list) { + for (i in 0 until el.subtypeCount){ + if (el.getSubtypeAt(i).mode != "voice") continue + if (AndroidVersion.ATLEAST_API28_P) { + ims.switchInputMethod(el.id) + return true + } else { + ims.window.window?.let { window -> + @Suppress("DEPRECATION") + imm.setInputMethod(window.attributes.token, el.id) + return true + } + } + } + } + ims.showShortToast("Failed to find voice IME, do you have one installed?") + return false + } } private val prefs by florisPreferenceModel() diff --git a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/keyboard/ComputingEvaluator.kt b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/keyboard/ComputingEvaluator.kt index 5282cd99..9d72b8e3 100644 --- a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/keyboard/ComputingEvaluator.kt +++ b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/keyboard/ComputingEvaluator.kt @@ -157,6 +157,9 @@ fun ComputingEvaluator.computeIconResId(data: KeyData): Int? { // TODO: find a better icon for compact mode R.drawable.ic_smartphone } + KeyCode.VOICE_INPUT -> { + R.drawable.ic_keyboard_voice + } KeyCode.DELETE -> { R.drawable.ic_backspace } diff --git a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/keyboard/KeyboardManager.kt b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/keyboard/KeyboardManager.kt index 67283d58..7e48ee08 100644 --- a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/keyboard/KeyboardManager.kt +++ b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/keyboard/KeyboardManager.kt @@ -664,6 +664,7 @@ class KeyboardManager(context: Context) : InputKeyEventReceiver { KeyCode.IME_UI_MODE_TEXT -> activeState.imeUiMode = ImeUiMode.TEXT KeyCode.IME_UI_MODE_MEDIA -> activeState.imeUiMode = ImeUiMode.MEDIA KeyCode.IME_UI_MODE_CLIPBOARD -> activeState.imeUiMode = ImeUiMode.CLIPBOARD + KeyCode.VOICE_INPUT -> FlorisImeService.switchToVoiceInputMethod() KeyCode.KANA_SWITCHER -> handleKanaSwitch() KeyCode.KANA_HIRA -> handleKanaHira() KeyCode.KANA_KATA -> handleKanaKata() diff --git a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/keyboard/TextKeyData.kt b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/keyboard/TextKeyData.kt index 01150266..2f3f60c4 100644 --- a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/keyboard/TextKeyData.kt +++ b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/keyboard/TextKeyData.kt @@ -476,6 +476,13 @@ class TextKeyData( code = KeyCode.SETTINGS, label = "settings", ) + + /** Predefined key data for [KeyCode.VOICE_INPUT] */ + val VOICE_INPUT = TextKeyData( + type = KeyType.UNSPECIFIED, + code = KeyCode.VOICE_INPUT, + label = "voice_input", + ) } } diff --git a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/smartbar/QuickAction.kt b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/smartbar/QuickAction.kt index 70024aca..5d9f124b 100644 --- a/app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/smartbar/QuickAction.kt +++ b/app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/smartbar/QuickAction.kt @@ -37,6 +37,7 @@ private val QuickActionSet = setOf( QuickAction.Key(TextKeyData.REDO), QuickAction.Key(TextKeyData.SETTINGS), QuickAction.Key(TextKeyData.IME_UI_MODE_MEDIA), + QuickAction.Key(TextKeyData.VOICE_INPUT), QuickAction.Key(TextKeyData.COMPACT_LAYOUT_TO_RIGHT), QuickAction.Key(TextKeyData.IME_UI_MODE_CLIPBOARD), ) diff --git a/app/src/main/res/drawable/ic_keyboard_voice.xml b/app/src/main/res/drawable/ic_keyboard_voice.xml new file mode 100644 index 00000000..d28d4165 --- /dev/null +++ b/app/src/main/res/drawable/ic_keyboard_voice.xml @@ -0,0 +1,9 @@ + + +