diff --git a/java/res/values/strings-uix.xml b/java/res/values/strings-uix.xml
index aa146b7b89..38f8d3170d 100644
--- a/java/res/values/strings-uix.xml
+++ b/java/res/values/strings-uix.xml
@@ -501,6 +501,10 @@
Always use Western numerals
Hide when USB keyboard is detected
+ Show toolbar when hardware keyboard is detected
+ When the keyboard is hidden because a physical keyboard is connected, keep the action/suggestions bar visible and add a button to show the touch keyboard.
+ Show touch keyboard
+ Hide touch keyboard
Keyboard & Typing
@@ -696,4 +700,4 @@ Default is %1$s
Delete extra dictionary file?
%1$s will be deleted
-
\ No newline at end of file
+
diff --git a/java/src/org/futo/inputmethod/latin/LatinIME.kt b/java/src/org/futo/inputmethod/latin/LatinIME.kt
index 0632f74087..f6410d1a53 100644
--- a/java/src/org/futo/inputmethod/latin/LatinIME.kt
+++ b/java/src/org/futo/inputmethod/latin/LatinIME.kt
@@ -119,6 +119,11 @@ val HideKeyboardWhenHardKeyboardConnected = SettingsKey(
false
)
+val ShowToolbarWhenHardKeyboardConnected = SettingsKey(
+ booleanPreferencesKey("showToolbarWhenHardKeyboardConnected"),
+ false
+)
+
private class UnlockedBroadcastReceiver(val onDeviceUnlocked: () -> Unit) : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == Intent.ACTION_USER_UNLOCKED) {
@@ -423,6 +428,19 @@ class LatinIME : InputMethodServiceCompose(), LatinIMELegacy.SuggestionStripCont
}
}
+ launchJob {
+ combine(
+ getSettingFlow(HideKeyboardWhenHardKeyboardConnected),
+ getSettingFlow(ShowToolbarWhenHardKeyboardConnected)
+ ) { _, _ -> Unit }.collect {
+ withContext(Dispatchers.Main) {
+ uixManager.refreshHardwareToolbarMode()
+ updateInputViewShown()
+ onSizeMaybeUpdated()
+ }
+ }
+ }
+
launchJob {
combine(
getSettingFlow(HiddenKeysSetting),
@@ -516,6 +534,7 @@ class LatinIME : InputMethodServiceCompose(), LatinIMELegacy.SuggestionStripCont
updateNavigationBarVisibility()
latinIMELegacy.onConfigurationChanged(newConfig)
super.onConfigurationChanged(newConfig)
+ uixManager.refreshHardwareToolbarMode()
uixManager.updateLocaleOnCfgChanged()
}
@@ -609,6 +628,7 @@ class LatinIME : InputMethodServiceCompose(), LatinIMELegacy.SuggestionStripCont
override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) {
super.onStartInput(attribute, restarting)
latinIMELegacy.onStartInput(attribute, restarting)
+ uixManager.refreshHardwareToolbarMode()
uixManager.inputStarted(attribute)
//imeManager.onStartInput() // TODO: Is this call needed or not?
}
@@ -618,6 +638,7 @@ class LatinIME : InputMethodServiceCompose(), LatinIMELegacy.SuggestionStripCont
onSizeMaybeUpdated()
imeManager.onStartInput()
latinIMELegacy.onStartInputView(info, restarting)
+ uixManager.refreshHardwareToolbarMode()
lifecycleScope.launch { uixManager.showUpdateNoticeIfNeeded() }
updateColorsIfDynamicChanged()
uixManager.updateEmojiTranslationsIfNeeded()
@@ -766,8 +787,17 @@ class LatinIME : InputMethodServiceCompose(), LatinIMELegacy.SuggestionStripCont
return latinIMELegacy.onEvaluateInputViewShown()
|| super.onEvaluateInputViewShown()
|| !getSetting(HideKeyboardWhenHardKeyboardConnected)
+ || shouldUseHardwareKeyboardToolbarMode()
}
+ fun hasHardwareKeyboardConnected(): Boolean =
+ Settings.readHasHardwareKeyboard(resources.configuration)
+
+ fun shouldUseHardwareKeyboardToolbarMode(): Boolean =
+ hasHardwareKeyboardConnected()
+ && getSetting(HideKeyboardWhenHardKeyboardConnected)
+ && getSetting(ShowToolbarWhenHardKeyboardConnected)
+
override fun onEvaluateFullscreenMode(): Boolean {
// TODO: Revisit fullscreen mode
return false //latinIMELegacy.onEvaluateFullscreenMode(super.onEvaluateFullscreenMode())
@@ -941,4 +971,4 @@ class LatinIME : InputMethodServiceCompose(), LatinIMELegacy.SuggestionStripCont
else ->
KeyboardSizeSettingKind.Portrait
}
-}
\ No newline at end of file
+}
diff --git a/java/src/org/futo/inputmethod/latin/uix/ActionBar.kt b/java/src/org/futo/inputmethod/latin/uix/ActionBar.kt
index 8ae519b348..f58fd2521e 100644
--- a/java/src/org/futo/inputmethod/latin/uix/ActionBar.kt
+++ b/java/src/org/futo/inputmethod/latin/uix/ActionBar.kt
@@ -825,6 +825,9 @@ fun ActionBar(
onQuickClipDismiss: () -> Unit = {},
needToUseExpandableSuggestionUi: Boolean = false,
loading: Boolean = false,
+ showTouchKeyboardToggle: Boolean = false,
+ touchKeyboardShown: Boolean = false,
+ onTouchKeyboardToggle: () -> Unit = {},
) {
val view = LocalView.current
val context = LocalContext.current
@@ -884,6 +887,12 @@ fun ActionBar(
.fillMaxHeight()) {
ActionItems(onActionActivated, onActionAltActivated)
}
+ if(showTouchKeyboardToggle) {
+ TouchKeyboardToggleButton(
+ touchKeyboardShown = touchKeyboardShown,
+ onToggle = onTouchKeyboardToggle
+ )
+ }
} else {
if (importantNotice != null) {
ImportantNoticeView(importantNotice)
@@ -922,6 +931,13 @@ fun ActionBar(
Spacer(modifier = Modifier.weight(1.0f))
}
+ if(showTouchKeyboardToggle) {
+ TouchKeyboardToggleButton(
+ touchKeyboardShown = touchKeyboardShown,
+ onToggle = onTouchKeyboardToggle
+ )
+ }
+
if(inlineSuggestions.isEmpty()) {
PinnedActionItems(onActionActivated, onActionAltActivated)
}
@@ -934,6 +950,33 @@ fun ActionBar(
}
}
+@Composable
+private fun TouchKeyboardToggleButton(
+ touchKeyboardShown: Boolean,
+ onToggle: () -> Unit
+) {
+ IconButton(
+ onClick = onToggle,
+ modifier = Modifier
+ .width(42.dp)
+ .fillMaxHeight(),
+ colors = IconButtonDefaults.iconButtonColors(contentColor = LocalKeyboardScheme.current.onBackground)
+ ) {
+ Icon(
+ painter = painterResource(
+ id = if (touchKeyboardShown) R.drawable.arrow_down else R.drawable.keyboard_regular
+ ),
+ contentDescription = stringResource(
+ if (touchKeyboardShown) {
+ R.string.keyboard_actionbar_hide_touch_keyboard
+ } else {
+ R.string.keyboard_actionbar_show_touch_keyboard
+ }
+ )
+ )
+ }
+}
+
@Composable
fun ActionWindowBar(
windowTitleBar: @Composable RowScope.() -> Unit,
@@ -1818,4 +1861,4 @@ fun PreviewActionBarLoadingDynamicDark() {
@Preview
fun PreviewExpandedActionBarDynamicDark() {
PreviewExpandedActionBar(DynamicDarkTheme)
-}
\ No newline at end of file
+}
diff --git a/java/src/org/futo/inputmethod/latin/uix/UixManager.kt b/java/src/org/futo/inputmethod/latin/uix/UixManager.kt
index 6191a1e09c..87c6c185b6 100644
--- a/java/src/org/futo/inputmethod/latin/uix/UixManager.kt
+++ b/java/src/org/futo/inputmethod/latin/uix/UixManager.kt
@@ -603,6 +603,14 @@ class UixManager(private val latinIME: LatinIME) {
private val keyboardManagerForAction = UixActionKeyboardManager(this, latinIME)
private var mainKeyboardHidden = mutableStateOf(false)
+ private val hardwareToolbarMode = mutableStateOf(false)
+ private val forceTouchKeyboardForCurrentInput = mutableStateOf(false)
+
+ val isHardwareToolbarModeEffective: Boolean
+ get() = hardwareToolbarMode.value && !forceTouchKeyboardForCurrentInput.value
+
+ private val effectiveMainKeyboardHidden: Boolean
+ get() = mainKeyboardHidden.value || isHardwareToolbarModeEffective
fun getCurrentLayoutName(): String =
getPrimaryLayoutOverride(latinIME.currentInputEditorInfo)
@@ -646,7 +654,35 @@ class UixManager(private val latinIME: LatinIME) {
val touchableHeight: Int
get() = measuredTouchableHeight
- val isMainKeyboardHidden get() = mainKeyboardHidden.value
+ val isMainKeyboardHidden get() = effectiveMainKeyboardHidden
+
+ fun refreshHardwareToolbarMode() {
+ val newValue = latinIME.shouldUseHardwareKeyboardToolbarMode()
+ if (!newValue) {
+ forceTouchKeyboardForCurrentInput.value = false
+ }
+ hardwareToolbarMode.value = newValue
+ }
+
+ fun toggleTouchKeyboardForHardwareToolbarMode() {
+ if (!hardwareToolbarMode.value) return
+ forceTouchKeyboardForCurrentInput.value = !forceTouchKeyboardForCurrentInput.value
+ if (!effectiveMainKeyboardHidden) {
+ latinIME.onKeyboardShown()
+ }
+ }
+
+ private fun expandActionWindowKeyboard() {
+ if (isHardwareToolbarModeEffective) {
+ forceTouchKeyboardForCurrentInput.value = true
+ }
+
+ if (mainKeyboardHidden.value) {
+ toggleExpandAction(false)
+ } else if (!effectiveMainKeyboardHidden) {
+ latinIME.onKeyboardShown()
+ }
+ }
private fun onActionActivatedInternal(rawAction: Action) {
resizers.hideResizer()
@@ -688,7 +724,11 @@ class UixManager(private val latinIME: LatinIME) {
@Composable
private fun MainKeyboardViewWithActionBar(
- needToUseExpandableSuggestionUi: Boolean
+ needToUseExpandableSuggestionUi: Boolean,
+ forceActionBarShown: Boolean = false,
+ showTouchKeyboardToggle: Boolean = false,
+ touchKeyboardShown: Boolean = false,
+ onTouchKeyboardToggle: () -> Unit = {}
) {
val view = LocalView.current
@@ -706,7 +746,7 @@ class UixManager(private val latinIME: LatinIME) {
if(!inlineStuffHiddenByTyping.value) inlineSuggestions.value else emptyList()
}
- if(actionBarShown.value || inlineSuggestions.isNotEmpty()) {
+ if(forceActionBarShown || actionBarShown.value || inlineSuggestions.isNotEmpty()) {
ActionBar(
suggestedWordsOrNull,
suggestionStripListener,
@@ -737,7 +777,10 @@ class UixManager(private val latinIME: LatinIME) {
},
onQuickClipDismiss = { quickClipState.value = null },
needToUseExpandableSuggestionUi = needToUseExpandableSuggestionUi,
- loading = latinIME.imeManager.isImeLoading()
+ loading = latinIME.imeManager.isImeLoading(),
+ showTouchKeyboardToggle = showTouchKeyboardToggle,
+ touchKeyboardShown = touchKeyboardShown,
+ onTouchKeyboardToggle = onTouchKeyboardToggle
)
}
}
@@ -801,13 +844,14 @@ class UixManager(private val latinIME: LatinIME) {
@Composable
private fun ActionViewWithHeader(windowImpl: ActionWindow,
needToUseExpandableSuggestionUi: Boolean) {
- val heightDiv = if(mainKeyboardHidden.value) {
+ val touchKeyboardHidden = effectiveMainKeyboardHidden
+ val heightDiv = if(touchKeyboardHidden) {
1
} else {
1.5
}
- val showingAboveKeyboard = !mainKeyboardHidden.value
+ val showingAboveKeyboard = !touchKeyboardHidden
Column {
Column(
Modifier.background(
@@ -818,11 +862,11 @@ class UixManager(private val latinIME: LatinIME) {
}
)
) {
- if (mainKeyboardHidden.value || isInputOverridden.value) {
+ if (touchKeyboardHidden || isInputOverridden.value) {
ActionWindowBar(
onBack = { closeActionWindow(true) },
canExpand = currWindowAction.value!!.canShowKeyboard,
- onExpand = { toggleExpandAction() },
+ onExpand = { expandActionWindowKeyboard() },
windowTitleBar = { windowImpl.WindowTitleBar(this) }
)
}
@@ -838,11 +882,11 @@ class UixManager(private val latinIME: LatinIME) {
})
.safeKeyboardPadding()
) {
- windowImpl.WindowContents(keyboardShown = !mainKeyboardHidden.value)
+ windowImpl.WindowContents(keyboardShown = !touchKeyboardHidden)
}
}
- if((!mainKeyboardHidden.value && !latinIME.isInputConnectionOverridden)
+ if((!touchKeyboardHidden && !latinIME.isInputConnectionOverridden)
|| (latinIME.inputConnectionOverridenWithSuggestions)) {
val suggestedWordsOrNull = if (shouldShowSuggestionStrip.value) {
suggestedWords.value
@@ -1281,7 +1325,7 @@ class UixManager(private val latinIME: LatinIME) {
// TODO: Refactor how we handle expandable suggestions here to not be a mess
val needToUseExpandableSuggestionUi =
expandableSuggestionCfg.value.useExpandableUi && suggestedWords.value?.size()?.equals(0) != true
- && mainKeyboardHidden.value == false
+ && !effectiveMainKeyboardHidden
&& (quickClipState.value == null || inlineStuffHiddenByTyping.value)
&& currentNotice.value == null
&& (inlineSuggestions.value.isEmpty() || inlineStuffHiddenByTyping.value)
@@ -1292,7 +1336,11 @@ class UixManager(private val latinIME: LatinIME) {
)
else -> MainKeyboardViewWithActionBar(
- needToUseExpandableSuggestionUi
+ needToUseExpandableSuggestionUi,
+ forceActionBarShown = hardwareToolbarMode.value,
+ showTouchKeyboardToggle = hardwareToolbarMode.value,
+ touchKeyboardShown = !isHardwareToolbarModeEffective,
+ onTouchKeyboardToggle = { toggleTouchKeyboardForHardwareToolbarMode() }
)
}
@@ -1303,7 +1351,9 @@ class UixManager(private val latinIME: LatinIME) {
val kbHeight = remember { mutableIntStateOf(latinIME.size.value!!.height) }
val keyboardViewOffset = remember(needToUseExpandableSuggestionUi) { mutableIntStateOf(0) }
Box(Modifier.let {
- if(needToUseExpandableSuggestionUi) {
+ if(isHardwareToolbarModeEffective) {
+ it.height(0.dp)
+ } else if(needToUseExpandableSuggestionUi) {
it.height(
with(LocalDensity.current) { kbHeight.intValue.toDp() }
+ latinIME.sizingCalculator.calculateSuggestionBarHeightDp().dp
@@ -1338,7 +1388,7 @@ class UixManager(private val latinIME: LatinIME) {
}
}
.absoluteOffset { IntOffset(0, keyboardViewOffset.intValue) },
- hidden = mainKeyboardHidden.value)
+ hidden = effectiveMainKeyboardHidden)
}
if(latinIME.size.value !is FloatingKeyboardSize) {
@@ -1608,6 +1658,8 @@ class UixManager(private val latinIME: LatinIME) {
private val quickClipState: MutableState = mutableStateOf(null)
fun dismissQuickClips() { quickClipState.value = null }
fun inputStarted(editorInfo: EditorInfo?) {
+ forceTouchKeyboardForCurrentInput.value = false
+ refreshHardwareToolbarMode()
try {
checkIfDictInstalled()
} catch(e: Exception) {
@@ -1632,6 +1684,8 @@ class UixManager(private val latinIME: LatinIME) {
}
fun onInputFinishing() {
+ forceTouchKeyboardForCurrentInput.value = false
+ refreshHardwareToolbarMode()
closeActionWindow()
languageSwitcherDialog?.dismiss()
isShowingActionEditor.value = false
@@ -1715,5 +1769,3 @@ class UixManager(private val latinIME: LatinIME) {
val extraTopTouchHeight: Int
get() = if(floatingPreeditShown) floatingPreeditHeight.value else 0
}
-
-
diff --git a/java/src/org/futo/inputmethod/latin/uix/settings/pages/Typing.kt b/java/src/org/futo/inputmethod/latin/uix/settings/pages/Typing.kt
index 0218653c24..7b399b7008 100644
--- a/java/src/org/futo/inputmethod/latin/uix/settings/pages/Typing.kt
+++ b/java/src/org/futo/inputmethod/latin/uix/settings/pages/Typing.kt
@@ -86,6 +86,7 @@ import org.futo.inputmethod.accessibility.AccessibilityUtils
import org.futo.inputmethod.engine.IMESettingsMenu
import org.futo.inputmethod.latin.HideKeyboardWhenHardKeyboardConnected
import org.futo.inputmethod.latin.R
+import org.futo.inputmethod.latin.ShowToolbarWhenHardKeyboardConnected
import org.futo.inputmethod.latin.settings.LongPressKey
import org.futo.inputmethod.latin.settings.LongPressKeyLayoutSetting
import org.futo.inputmethod.latin.settings.Settings
@@ -848,6 +849,12 @@ val KeyboardSettingsMenu = UserSettingsMenu(
userSettingToggleDataStore(
title = R.string.keyboard_settings_hide_when_hardware_keyboard_is_connected,
setting = HideKeyboardWhenHardKeyboardConnected
+ ),
+ userSettingToggleDataStore(
+ title = R.string.keyboard_settings_show_toolbar_when_hardware_keyboard_is_connected,
+ subtitle = R.string.keyboard_settings_show_toolbar_when_hardware_keyboard_is_connected_subtitle,
+ setting = ShowToolbarWhenHardKeyboardConnected,
+ disabled = { !useDataStore(HideKeyboardWhenHardKeyboardConnected).value }
)
)
)
@@ -1047,4 +1054,4 @@ fun KeyboardAndTypingScreen(navController: NavHostController = rememberNavContro
BottomSpacer()
}
-}
\ No newline at end of file
+}