mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Update keyboard sizing and add floating mode
This commit is contained in:
parent
32b27b84c0
commit
3d8233be92
@ -16,6 +16,11 @@
|
|||||||
<string name="more_actions_action_title">All Actions</string>
|
<string name="more_actions_action_title">All Actions</string>
|
||||||
<string name="bug_viewer_action_title">Bug Viewer</string>
|
<string name="bug_viewer_action_title">Bug Viewer</string>
|
||||||
|
|
||||||
|
<string name="left_handed_keyboard_action_title">Left-Handed Keyboard</string>
|
||||||
|
<string name="right_handed_keyboard_action_title">Right-Handed Keyboard</string>
|
||||||
|
<string name="split_keyboard_action_title">Split Keyboard</string>
|
||||||
|
<string name="floating_keyboard_action_title">Floating Keyboard</string>
|
||||||
|
|
||||||
<string name="action_kind_action_key">Action Key</string>
|
<string name="action_kind_action_key">Action Key</string>
|
||||||
<string name="action_kind_pinned_key">Pinned Action(s)</string>
|
<string name="action_kind_pinned_key">Pinned Action(s)</string>
|
||||||
<string name="action_kind_favorites">Favorite Actions</string>
|
<string name="action_kind_favorites">Favorite Actions</string>
|
||||||
|
@ -140,40 +140,16 @@ public final class KeyboardSwitcher implements SwitchActions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final KeyboardSizingCalculator sizingCalculator = new KeyboardSizingCalculator(mLatinIMELegacy.getInputMethodService());
|
final KeyboardSizingCalculator sizingCalculator = ((LatinIME)mLatinIMELegacy.getInputMethodService()).getSizingCalculator();
|
||||||
final ComputedKeyboardSize computedSize = sizingCalculator.calculate(layoutSetName, settingsValues.mIsNumberRowEnabled);
|
final ComputedKeyboardSize computedSize = sizingCalculator.calculate(layoutSetName, settingsValues.mIsNumberRowEnabled);
|
||||||
|
|
||||||
int keyboardWidth = 0;
|
|
||||||
int keyboardHeight = 0;
|
|
||||||
|
|
||||||
int splitLayoutWidth = 0;
|
|
||||||
|
|
||||||
Rect padding = new Rect();
|
|
||||||
|
|
||||||
Window window = mLatinIMELegacy.getInputMethodService().getWindow().getWindow();
|
|
||||||
|
|
||||||
if(computedSize instanceof SplitKeyboardSize) {
|
|
||||||
keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(window, res);
|
|
||||||
keyboardHeight = ((SplitKeyboardSize) computedSize).getHeight();
|
|
||||||
splitLayoutWidth = ((SplitKeyboardSize) computedSize).getSplitLayoutWidth();
|
|
||||||
padding = ((SplitKeyboardSize) computedSize).getPadding();
|
|
||||||
}else if(computedSize instanceof RegularKeyboardSize) {
|
|
||||||
keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(window, res);
|
|
||||||
keyboardHeight = ((RegularKeyboardSize) computedSize).getHeight();
|
|
||||||
padding = ((RegularKeyboardSize) computedSize).getPadding();
|
|
||||||
}
|
|
||||||
|
|
||||||
final KeyboardLayoutSetV2Params params = new KeyboardLayoutSetV2Params(
|
final KeyboardLayoutSetV2Params params = new KeyboardLayoutSetV2Params(
|
||||||
keyboardWidth,
|
computedSize,
|
||||||
keyboardHeight,
|
|
||||||
padding,
|
|
||||||
layoutSetName,
|
layoutSetName,
|
||||||
subtype.getLocale(),
|
subtype.getLocale(),
|
||||||
editorInfo == null ? new EditorInfo() : editorInfo,
|
editorInfo == null ? new EditorInfo() : editorInfo,
|
||||||
settingsValues.mIsNumberRowEnabled,
|
settingsValues.mIsNumberRowEnabled,
|
||||||
sizingCalculator.calculateGap(),
|
sizingCalculator.calculateGap(),
|
||||||
splitLayoutWidth != 0,
|
|
||||||
splitLayoutWidth,
|
|
||||||
settingsValues.mShowsActionKey ? settingsValues.mActionKeyId : null,
|
settingsValues.mShowsActionKey ? settingsValues.mActionKeyId : null,
|
||||||
LongPressKeySettings.load(mThemeContext)
|
LongPressKeySettings.load(mThemeContext)
|
||||||
);
|
);
|
||||||
|
@ -132,16 +132,8 @@ public final class KeyPreviewChoreographer {
|
|||||||
final int keyPreviewPosition;
|
final int keyPreviewPosition;
|
||||||
int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2
|
int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2
|
||||||
+ CoordinateUtils.x(originCoords);
|
+ CoordinateUtils.x(originCoords);
|
||||||
if (previewX < 0) {
|
keyPreviewPosition = KeyPreviewView.POSITION_MIDDLE;
|
||||||
previewX = 0;
|
final boolean hasMoreKeys = !key.getMoreKeys().isEmpty();
|
||||||
keyPreviewPosition = KeyPreviewView.POSITION_LEFT;
|
|
||||||
} else if (previewX > keyboardViewWidth - previewWidth) {
|
|
||||||
previewX = keyboardViewWidth - previewWidth;
|
|
||||||
keyPreviewPosition = KeyPreviewView.POSITION_RIGHT;
|
|
||||||
} else {
|
|
||||||
keyPreviewPosition = KeyPreviewView.POSITION_MIDDLE;
|
|
||||||
}
|
|
||||||
final boolean hasMoreKeys = (key.getMoreKeys() != null);
|
|
||||||
keyPreviewView.setPreviewBackground(hasMoreKeys, keyPreviewPosition);
|
keyPreviewView.setPreviewBackground(hasMoreKeys, keyPreviewPosition);
|
||||||
// The key preview is placed vertically above the top edge of the parent key with an
|
// The key preview is placed vertically above the top edge of the parent key with an
|
||||||
// arbitrary offset.
|
// arbitrary offset.
|
||||||
|
@ -21,10 +21,14 @@ import android.view.inputmethod.InputMethodSubtype
|
|||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.key
|
import androidx.compose.runtime.key
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clipToBounds
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
import androidx.compose.ui.layout.onSizeChanged
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.viewinterop.AndroidView
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
@ -75,28 +79,27 @@ import org.futo.inputmethod.latin.uix.theme.applyWindowColors
|
|||||||
import org.futo.inputmethod.latin.uix.theme.presets.VoiceInputTheme
|
import org.futo.inputmethod.latin.uix.theme.presets.VoiceInputTheme
|
||||||
import org.futo.inputmethod.latin.xlm.LanguageModelFacilitator
|
import org.futo.inputmethod.latin.xlm.LanguageModelFacilitator
|
||||||
import org.futo.inputmethod.updates.scheduleUpdateCheckingJob
|
import org.futo.inputmethod.updates.scheduleUpdateCheckingJob
|
||||||
|
import org.futo.inputmethod.v2keyboard.ComputedKeyboardSize
|
||||||
|
import org.futo.inputmethod.v2keyboard.FloatingKeyboardSize
|
||||||
|
import org.futo.inputmethod.v2keyboard.KeyboardSettings
|
||||||
import org.futo.inputmethod.v2keyboard.KeyboardSizeSettingKind
|
import org.futo.inputmethod.v2keyboard.KeyboardSizeSettingKind
|
||||||
import org.futo.inputmethod.v2keyboard.KeyboardSizeStateProvider
|
import org.futo.inputmethod.v2keyboard.KeyboardSizeStateProvider
|
||||||
|
import org.futo.inputmethod.v2keyboard.KeyboardSizingCalculator
|
||||||
|
import org.futo.inputmethod.v2keyboard.getHeight
|
||||||
|
|
||||||
private class UnlockedBroadcastReceiver(val onDeviceUnlocked: () -> Unit) : BroadcastReceiver() {
|
private class UnlockedBroadcastReceiver(val onDeviceUnlocked: () -> Unit) : BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
println("Unlocked Broadcast Receiver: ${intent?.action}")
|
|
||||||
if (intent?.action == Intent.ACTION_USER_UNLOCKED) {
|
if (intent?.action == Intent.ACTION_USER_UNLOCKED) {
|
||||||
onDeviceUnlocked()
|
onDeviceUnlocked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner,
|
open class InputMethodServiceCompose : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner {
|
||||||
LatinIMELegacy.SuggestionStripController, DynamicThemeProviderOwner, FoldStateProvider,
|
|
||||||
KeyboardSizeStateProvider {
|
|
||||||
|
|
||||||
private lateinit var mLifecycleRegistry: LifecycleRegistry
|
private lateinit var mLifecycleRegistry: LifecycleRegistry
|
||||||
private lateinit var mViewModelStore: ViewModelStore
|
private lateinit var mViewModelStore: ViewModelStore
|
||||||
private lateinit var mSavedStateRegistryController: SavedStateRegistryController
|
private lateinit var mSavedStateRegistryController: SavedStateRegistryController
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun setOwners() {
|
fun setOwners() {
|
||||||
val decorView = window.window?.decorView
|
val decorView = window.window?.decorView
|
||||||
if (decorView?.findViewTreeLifecycleOwner() == null) {
|
if (decorView?.findViewTreeLifecycleOwner() == null) {
|
||||||
@ -110,11 +113,59 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
|
||||||
|
mLifecycleRegistry = LifecycleRegistry(this)
|
||||||
|
mLifecycleRegistry.currentState = Lifecycle.State.INITIALIZED
|
||||||
|
|
||||||
|
mViewModelStore = ViewModelStore()
|
||||||
|
|
||||||
|
mSavedStateRegistryController = SavedStateRegistryController.create(this)
|
||||||
|
mSavedStateRegistryController.performRestore(null)
|
||||||
|
|
||||||
|
mLifecycleRegistry.currentState = Lifecycle.State.CREATED
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartInputView(editorInfo: EditorInfo?, restarting: Boolean) {
|
||||||
|
super.onStartInputView(editorInfo, restarting)
|
||||||
|
|
||||||
|
mLifecycleRegistry.currentState = Lifecycle.State.STARTED
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
mLifecycleRegistry.currentState = Lifecycle.State.DESTROYED
|
||||||
|
}
|
||||||
|
|
||||||
|
override val lifecycle: Lifecycle
|
||||||
|
get() = mLifecycleRegistry
|
||||||
|
override val savedStateRegistry: SavedStateRegistry
|
||||||
|
get() = mSavedStateRegistryController.savedStateRegistry
|
||||||
|
override val viewModelStore: ViewModelStore
|
||||||
|
get() = mViewModelStore
|
||||||
|
|
||||||
|
internal var composeView: ComposeView? = null
|
||||||
|
|
||||||
|
override fun onCreateInputView(): View =
|
||||||
|
ComposeView(this).apply {
|
||||||
|
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||||
|
setParentCompositionContext(null)
|
||||||
|
|
||||||
|
setOwners()
|
||||||
|
|
||||||
|
composeView = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LatinIME : InputMethodServiceCompose(), LatinIMELegacy.SuggestionStripController,
|
||||||
|
DynamicThemeProviderOwner, FoldStateProvider, KeyboardSizeStateProvider {
|
||||||
val latinIMELegacy = LatinIMELegacy(
|
val latinIMELegacy = LatinIMELegacy(
|
||||||
this as InputMethodService,
|
this as InputMethodService,
|
||||||
this as LatinIMELegacy.SuggestionStripController
|
this as LatinIMELegacy.SuggestionStripController
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
val inputLogic get() = latinIMELegacy.mInputLogic
|
val inputLogic get() = latinIMELegacy.mInputLogic
|
||||||
|
|
||||||
lateinit var languageModelFacilitator: LanguageModelFacilitator
|
lateinit var languageModelFacilitator: LanguageModelFacilitator
|
||||||
@ -122,6 +173,8 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
val uixManager = UixManager(this)
|
val uixManager = UixManager(this)
|
||||||
lateinit var suggestionBlacklist: SuggestionBlacklist
|
lateinit var suggestionBlacklist: SuggestionBlacklist
|
||||||
|
|
||||||
|
val sizingCalculator = KeyboardSizingCalculator(this, uixManager)
|
||||||
|
|
||||||
private var activeThemeOption: ThemeOption? = null
|
private var activeThemeOption: ThemeOption? = null
|
||||||
private var activeColorScheme = VoiceInputTheme.obtainColors(this)
|
private var activeColorScheme = VoiceInputTheme.obtainColors(this)
|
||||||
private var pendingRecreateKeyboard: Boolean = false
|
private var pendingRecreateKeyboard: Boolean = false
|
||||||
@ -130,6 +183,13 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
val colorScheme get() = activeColorScheme
|
val colorScheme get() = activeColorScheme
|
||||||
val keyboardColor get() = drawableProvider?.primaryKeyboardColor?.let { androidx.compose.ui.graphics.Color(it) } ?: colorScheme.surface
|
val keyboardColor get() = drawableProvider?.primaryKeyboardColor?.let { androidx.compose.ui.graphics.Color(it) } ?: colorScheme.surface
|
||||||
|
|
||||||
|
val size: MutableState<ComputedKeyboardSize?> = mutableStateOf(null)
|
||||||
|
private fun calculateSize(): ComputedKeyboardSize
|
||||||
|
= sizingCalculator.calculate(
|
||||||
|
latinIMELegacy.mKeyboardSwitcher.keyboard?.mId?.mKeyboardLayoutSetName ?: "qwerty",
|
||||||
|
latinIMELegacy.mKeyboardSwitcher.keyboard?.mId?.mNumberRow ?: false
|
||||||
|
)
|
||||||
|
|
||||||
private var drawableProvider: DynamicThemeProvider? = null
|
private var drawableProvider: DynamicThemeProvider? = null
|
||||||
|
|
||||||
private var lastEditorInfo: EditorInfo? = null
|
private var lastEditorInfo: EditorInfo? = null
|
||||||
@ -204,7 +264,26 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onSizeUpdated() {
|
||||||
|
val newSize = calculateSize()
|
||||||
|
val shouldInvalidateKeyboard = size.value?.let { oldSize ->
|
||||||
|
when {
|
||||||
|
oldSize is FloatingKeyboardSize && newSize is FloatingKeyboardSize -> {
|
||||||
|
oldSize.width != newSize.width || oldSize.height != newSize.height
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
} ?: true
|
||||||
|
|
||||||
|
size.value = newSize
|
||||||
|
|
||||||
|
if(shouldInvalidateKeyboard) {
|
||||||
|
invalidateKeyboard(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun invalidateKeyboard(refreshSettings: Boolean = false) {
|
fun invalidateKeyboard(refreshSettings: Boolean = false) {
|
||||||
|
size.value = calculateSize()
|
||||||
settingsRefreshRequired = settingsRefreshRequired || refreshSettings
|
settingsRefreshRequired = settingsRefreshRequired || refreshSettings
|
||||||
|
|
||||||
if(!uixManager.isMainKeyboardHidden) {
|
if(!uixManager.isMainKeyboardHidden) {
|
||||||
@ -256,16 +335,6 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
val filter = IntentFilter(Intent.ACTION_USER_UNLOCKED)
|
val filter = IntentFilter(Intent.ACTION_USER_UNLOCKED)
|
||||||
registerReceiver(unlockReceiver, filter)
|
registerReceiver(unlockReceiver, filter)
|
||||||
|
|
||||||
mLifecycleRegistry = LifecycleRegistry(this)
|
|
||||||
mLifecycleRegistry.currentState = Lifecycle.State.INITIALIZED
|
|
||||||
|
|
||||||
mViewModelStore = ViewModelStore()
|
|
||||||
|
|
||||||
mSavedStateRegistryController = SavedStateRegistryController.create(this)
|
|
||||||
mSavedStateRegistryController.performRestore(null)
|
|
||||||
|
|
||||||
mLifecycleRegistry.currentState = Lifecycle.State.CREATED
|
|
||||||
|
|
||||||
suggestionBlacklist = SuggestionBlacklist(latinIMELegacy.mSettings, this, lifecycleScope)
|
suggestionBlacklist = SuggestionBlacklist(latinIMELegacy.mSettings, this, lifecycleScope)
|
||||||
|
|
||||||
Subtypes.addDefaultSubtypesIfNecessary(this)
|
Subtypes.addDefaultSubtypesIfNecessary(this)
|
||||||
@ -348,6 +417,21 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Listen to size changes
|
||||||
|
launchJob {
|
||||||
|
val prev: MutableMap<KeyboardSizeSettingKind, String?> =
|
||||||
|
KeyboardSizeSettingKind.entries.associateWith { null }.toMutableMap()
|
||||||
|
|
||||||
|
dataStore.data.collect { data ->
|
||||||
|
prev.keys.toList().forEach {
|
||||||
|
if(data[KeyboardSettings[it]!!.key] != prev[it]) {
|
||||||
|
prev[it] = data[KeyboardSettings[it]!!.key]
|
||||||
|
onSizeUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uixManager.onCreate()
|
uixManager.onCreate()
|
||||||
|
|
||||||
Settings.getInstance().settingsChangedListeners.add { oldSettings, newSettings ->
|
Settings.getInstance().settingsChangedListeners.add { oldSettings, newSettings ->
|
||||||
@ -364,7 +448,6 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
unregisterReceiver(unlockReceiver)
|
unregisterReceiver(unlockReceiver)
|
||||||
|
|
||||||
stopJobs()
|
stopJobs()
|
||||||
mLifecycleRegistry.currentState = Lifecycle.State.DESTROYED
|
|
||||||
viewModelStore.clear()
|
viewModelStore.clear()
|
||||||
|
|
||||||
languageModelFacilitator.saveHistoryLog()
|
languageModelFacilitator.saveHistoryLog()
|
||||||
@ -381,6 +464,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
Log.w("LatinIME", "Configuration changed")
|
Log.w("LatinIME", "Configuration changed")
|
||||||
|
size.value = calculateSize()
|
||||||
latinIMELegacy.onConfigurationChanged(newConfig)
|
latinIMELegacy.onConfigurationChanged(newConfig)
|
||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
}
|
}
|
||||||
@ -390,22 +474,21 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var legacyInputView: View? = null
|
private var legacyInputView: View? = null
|
||||||
private var touchableHeight: Int = 0
|
|
||||||
override fun onCreateInputView(): View {
|
override fun onCreateInputView(): View {
|
||||||
Log.w("LatinIME", "Create input view")
|
val composeView = super.onCreateInputView()
|
||||||
legacyInputView = latinIMELegacy.onCreateInputView()
|
|
||||||
|
|
||||||
val composeView = uixManager.createComposeView()
|
legacyInputView = latinIMELegacy.onCreateInputView()
|
||||||
latinIMELegacy.setComposeInputView(composeView)
|
latinIMELegacy.setComposeInputView(composeView)
|
||||||
|
|
||||||
|
uixManager.setContent()
|
||||||
|
|
||||||
return composeView
|
return composeView
|
||||||
}
|
}
|
||||||
|
|
||||||
private var inputViewHeight: Int = -1
|
private var inputViewHeight: Int = -1
|
||||||
|
|
||||||
// Both called by UixManager
|
|
||||||
fun updateTouchableHeight(to: Int) { touchableHeight = to }
|
|
||||||
fun getInputViewHeight(): Int = inputViewHeight
|
fun getInputViewHeight(): Int = inputViewHeight
|
||||||
|
fun getViewHeight(): Int = composeView?.height ?: resources.displayMetrics.heightPixels
|
||||||
|
|
||||||
private var isInputModal = false
|
private var isInputModal = false
|
||||||
fun setInputModal(to: Boolean) {
|
fun setInputModal(to: Boolean) {
|
||||||
@ -426,8 +509,6 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
key(legacyInputView) {
|
key(legacyInputView) {
|
||||||
AndroidView(factory = {
|
AndroidView(factory = {
|
||||||
legacyInputView!!
|
legacyInputView!!
|
||||||
@ -445,7 +526,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
legacyInputView = newView
|
legacyInputView = newView
|
||||||
|
|
||||||
uixManager.setContent()
|
uixManager.setContent()
|
||||||
uixManager.getComposeView()?.let {
|
composeView?.let {
|
||||||
latinIMELegacy.setComposeInputView(it)
|
latinIMELegacy.setComposeInputView(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,7 +536,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
override fun setInputView(view: View?) {
|
override fun setInputView(view: View?) {
|
||||||
super.setInputView(view)
|
super.setInputView(view)
|
||||||
|
|
||||||
uixManager.getComposeView()?.let {
|
composeView?.let {
|
||||||
latinIMELegacy.setComposeInputView(it)
|
latinIMELegacy.setComposeInputView(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,8 +554,6 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartInputView(info: EditorInfo?, restarting: Boolean) {
|
override fun onStartInputView(info: EditorInfo?, restarting: Boolean) {
|
||||||
mLifecycleRegistry.currentState = Lifecycle.State.STARTED
|
|
||||||
|
|
||||||
lastEditorInfo = info
|
lastEditorInfo = info
|
||||||
|
|
||||||
super.onStartInputView(info, restarting)
|
super.onStartInputView(info, restarting)
|
||||||
@ -561,36 +640,55 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onComputeInsets(outInsets: Insets?) {
|
override fun onComputeInsets(outInsets: Insets?) {
|
||||||
val composeView = uixManager.getComposeView()
|
|
||||||
|
|
||||||
// This method may be called before {@link #setInputView(View)}.
|
// This method may be called before {@link #setInputView(View)}.
|
||||||
if (legacyInputView == null || composeView == null) {
|
if (legacyInputView == null || composeView == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val inputHeight: Int = composeView.height
|
val viewHeight = composeView!!.height
|
||||||
if (latinIMELegacy.isImeSuppressedByHardwareKeyboard && !legacyInputView!!.isShown) {
|
val size = size.value ?: return
|
||||||
// If there is a hardware keyboard and a visible software keyboard view has been hidden,
|
|
||||||
// no visual element will be shown on the screen.
|
|
||||||
latinIMELegacy.setInsets(outInsets!!.apply {
|
|
||||||
contentTopInsets = inputHeight
|
|
||||||
visibleTopInsets = inputHeight
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val visibleTopY = inputHeight - touchableHeight
|
|
||||||
|
|
||||||
val touchLeft = 0
|
|
||||||
val touchTop = if(isInputModal) { 0 } else { visibleTopY }
|
|
||||||
val touchRight = composeView.width
|
|
||||||
val touchBottom = inputHeight
|
|
||||||
|
|
||||||
latinIMELegacy.setInsets(outInsets!!.apply {
|
latinIMELegacy.setInsets(outInsets!!.apply {
|
||||||
touchableInsets = Insets.TOUCHABLE_INSETS_REGION;
|
when(size) {
|
||||||
touchableRegion.set(touchLeft, touchTop, touchRight, touchBottom);
|
is FloatingKeyboardSize -> {
|
||||||
contentTopInsets = visibleTopY
|
val height = uixManager.touchableHeight
|
||||||
visibleTopInsets = visibleTopY
|
|
||||||
|
val left = size.bottomOrigin.first
|
||||||
|
val bottomYFromBottom = size.bottomOrigin.second
|
||||||
|
var bottom = viewHeight - bottomYFromBottom
|
||||||
|
var top = bottom - height
|
||||||
|
val right = left + size.width
|
||||||
|
|
||||||
|
if(top < 0) {
|
||||||
|
bottom -= top
|
||||||
|
top -= top
|
||||||
|
}
|
||||||
|
|
||||||
|
touchableInsets = Insets.TOUCHABLE_INSETS_REGION
|
||||||
|
touchableRegion.set(left, top, right, bottom)
|
||||||
|
contentTopInsets = viewHeight
|
||||||
|
visibleTopInsets = viewHeight
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
touchableInsets = Insets.TOUCHABLE_INSETS_CONTENT
|
||||||
|
|
||||||
|
val touchableHeight = uixManager.touchableHeight
|
||||||
|
val topInset = if(touchableHeight < 1 || touchableHeight >= viewHeight - 1) {
|
||||||
|
val actionBarHeight = sizingCalculator.calculateTotalActionBarHeightPx()
|
||||||
|
|
||||||
|
viewHeight - size.getHeight() - actionBarHeight
|
||||||
|
} else {
|
||||||
|
viewHeight - touchableHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
contentTopInsets = topInset
|
||||||
|
visibleTopInsets = topInset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isInputModal) {
|
||||||
|
touchableInsets = Insets.TOUCHABLE_INSETS_REGION
|
||||||
|
touchableRegion.set(0, 0, composeView!!.width, composeView!!.height)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,14 +835,6 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
return super.getCurrentInputConnection()
|
return super.getCurrentInputConnection()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val lifecycle: Lifecycle
|
|
||||||
get() = mLifecycleRegistry
|
|
||||||
override val savedStateRegistry: SavedStateRegistry
|
|
||||||
get() = mSavedStateRegistryController.savedStateRegistry
|
|
||||||
override val viewModelStore: ViewModelStore
|
|
||||||
get() = mViewModelStore
|
|
||||||
|
|
||||||
|
|
||||||
private fun onDeviceUnlocked() {
|
private fun onDeviceUnlocked() {
|
||||||
Log.i("LatinIME", "DEVICE has UNLOCKED!!! Reloading settings...")
|
Log.i("LatinIME", "DEVICE has UNLOCKED!!! Reloading settings...")
|
||||||
// Every place that called getDefaultSharedPreferences now needs to be refreshed or call it again
|
// Every place that called getDefaultSharedPreferences now needs to be refreshed or call it again
|
||||||
|
@ -16,6 +16,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.lifecycle.LifecycleCoroutineScope
|
import androidx.lifecycle.LifecycleCoroutineScope
|
||||||
import org.futo.inputmethod.latin.LatinIME
|
import org.futo.inputmethod.latin.LatinIME
|
||||||
import org.futo.inputmethod.latin.uix.theme.ThemeOption
|
import org.futo.inputmethod.latin.uix.theme.ThemeOption
|
||||||
|
import org.futo.inputmethod.v2keyboard.KeyboardSizingCalculator
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
interface ActionInputTransaction {
|
interface ActionInputTransaction {
|
||||||
@ -68,6 +69,8 @@ interface KeyboardManagerForAction {
|
|||||||
|
|
||||||
fun getLatinIMEForDebug(): LatinIME
|
fun getLatinIMEForDebug(): LatinIME
|
||||||
fun isDeviceLocked(): Boolean
|
fun isDeviceLocked(): Boolean
|
||||||
|
|
||||||
|
fun getSizingCalculator(): KeyboardSizingCalculator
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActionWindow {
|
interface ActionWindow {
|
||||||
|
@ -13,7 +13,6 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.scale
|
import androidx.compose.ui.draw.scale
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
@ -30,6 +29,7 @@ import org.futo.inputmethod.latin.R
|
|||||||
import org.futo.inputmethod.v2keyboard.KeyboardLayoutSetV2
|
import org.futo.inputmethod.v2keyboard.KeyboardLayoutSetV2
|
||||||
import org.futo.inputmethod.v2keyboard.KeyboardLayoutSetV2Params
|
import org.futo.inputmethod.v2keyboard.KeyboardLayoutSetV2Params
|
||||||
import org.futo.inputmethod.v2keyboard.LayoutManager
|
import org.futo.inputmethod.v2keyboard.LayoutManager
|
||||||
|
import org.futo.inputmethod.v2keyboard.RegularKeyboardSize
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@ -76,23 +76,8 @@ fun KeyboardLayoutPreview(id: String, width: Dp = 172.dp, locale: Locale? = null
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val configuration = LocalConfiguration.current
|
val widthPx: Int = (320.0 * context.resources.displayMetrics.density).roundToInt()
|
||||||
val isLandscape = false//configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
val heightPx: Int = (200.0 * context.resources.displayMetrics.density).roundToInt()
|
||||||
|
|
||||||
val widthPx: Int
|
|
||||||
val heightPx: Int
|
|
||||||
|
|
||||||
when {
|
|
||||||
isLandscape -> {
|
|
||||||
widthPx = (500.0 * context.resources.displayMetrics.density).roundToInt()
|
|
||||||
heightPx = (180.0 * context.resources.displayMetrics.density).roundToInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
widthPx = (320.0 * context.resources.displayMetrics.density).roundToInt()
|
|
||||||
heightPx = (200.0 * context.resources.displayMetrics.density).roundToInt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val keyboard = remember { mutableStateOf<Keyboard?>(null) }
|
val keyboard = remember { mutableStateOf<Keyboard?>(null) }
|
||||||
|
|
||||||
@ -107,16 +92,12 @@ fun KeyboardLayoutPreview(id: String, width: Dp = 172.dp, locale: Locale? = null
|
|||||||
val layoutSet = KeyboardLayoutSetV2(
|
val layoutSet = KeyboardLayoutSetV2(
|
||||||
context,
|
context,
|
||||||
KeyboardLayoutSetV2Params(
|
KeyboardLayoutSetV2Params(
|
||||||
width = widthPx,
|
computedSize = RegularKeyboardSize(width = widthPx, height = heightPx, padding = Rect()),
|
||||||
height = heightPx,
|
|
||||||
padding = Rect(),
|
|
||||||
gap = 4.0f,
|
gap = 4.0f,
|
||||||
keyboardLayoutSet = id,
|
keyboardLayoutSet = id,
|
||||||
locale = loc ?: Locale.ENGLISH,
|
locale = loc ?: Locale.ENGLISH,
|
||||||
editorInfo = editorInfo,
|
editorInfo = editorInfo,
|
||||||
numberRow = numberRow,
|
numberRow = numberRow,
|
||||||
useSplitLayout = isLandscape,
|
|
||||||
splitLayoutWidth = widthPx * 2 / 3,
|
|
||||||
bottomActionKey = null
|
bottomActionKey = null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -23,22 +23,29 @@ import androidx.compose.animation.fadeOut
|
|||||||
import androidx.compose.animation.slideInVertically
|
import androidx.compose.animation.slideInVertically
|
||||||
import androidx.compose.animation.slideOutVertically
|
import androidx.compose.animation.slideOutVertically
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.gestures.detectDragGestures
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
import androidx.compose.foundation.layout.BoxScope
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.absoluteOffset
|
||||||
|
import androidx.compose.foundation.layout.absolutePadding
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.requiredWidth
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.LocalContentColor
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.material3.contentColorFor
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@ -46,17 +53,21 @@ import androidx.compose.runtime.MutableState
|
|||||||
import androidx.compose.runtime.compositionLocalOf
|
import androidx.compose.runtime.compositionLocalOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.staticCompositionLocalOf
|
import androidx.compose.runtime.staticCompositionLocalOf
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.layout.onSizeChanged
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
import androidx.compose.ui.platform.ComposeView
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.unit.IntOffset
|
||||||
import androidx.compose.ui.unit.LayoutDirection
|
import androidx.compose.ui.unit.LayoutDirection
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.LifecycleCoroutineScope
|
import androidx.lifecycle.LifecycleCoroutineScope
|
||||||
@ -96,6 +107,14 @@ import org.futo.inputmethod.updates.deferManualUpdate
|
|||||||
import org.futo.inputmethod.updates.isManualUpdateTimeExpired
|
import org.futo.inputmethod.updates.isManualUpdateTimeExpired
|
||||||
import org.futo.inputmethod.updates.openManualUpdateCheck
|
import org.futo.inputmethod.updates.openManualUpdateCheck
|
||||||
import org.futo.inputmethod.updates.retrieveSavedLastUpdateCheckResult
|
import org.futo.inputmethod.updates.retrieveSavedLastUpdateCheckResult
|
||||||
|
import org.futo.inputmethod.v2keyboard.FloatingKeyboardSize
|
||||||
|
import org.futo.inputmethod.v2keyboard.KeyboardSizingCalculator
|
||||||
|
import org.futo.inputmethod.v2keyboard.OneHandedDirection
|
||||||
|
import org.futo.inputmethod.v2keyboard.OneHandedKeyboardSize
|
||||||
|
import org.futo.inputmethod.v2keyboard.RegularKeyboardSize
|
||||||
|
import org.futo.inputmethod.v2keyboard.SplitKeyboardSize
|
||||||
|
import org.futo.inputmethod.v2keyboard.getPadding
|
||||||
|
import org.futo.inputmethod.v2keyboard.getWidth
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
val LocalManager = staticCompositionLocalOf<KeyboardManagerForAction> {
|
val LocalManager = staticCompositionLocalOf<KeyboardManagerForAction> {
|
||||||
@ -279,7 +298,7 @@ class UixActionKeyboardManager(val uixManager: UixManager, val latinIME: LatinIM
|
|||||||
override fun announce(s: String) {
|
override fun announce(s: String) {
|
||||||
AccessibilityUtils.init(getContext())
|
AccessibilityUtils.init(getContext())
|
||||||
if(AccessibilityUtils.getInstance().isAccessibilityEnabled) {
|
if(AccessibilityUtils.getInstance().isAccessibilityEnabled) {
|
||||||
AccessibilityUtils.getInstance().announceForAccessibility(uixManager.getComposeView(), s)
|
AccessibilityUtils.getInstance().announceForAccessibility(uixManager.composeView, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,6 +314,9 @@ class UixActionKeyboardManager(val uixManager: UixManager, val latinIME: LatinIM
|
|||||||
return getContext().isDeviceLocked
|
return getContext().isDeviceLocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSizingCalculator(): KeyboardSizingCalculator =
|
||||||
|
latinIME.sizingCalculator
|
||||||
|
|
||||||
override fun getLatinIMEForDebug(): LatinIME = latinIME
|
override fun getLatinIMEForDebug(): LatinIME = latinIME
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,11 +327,12 @@ data class ActiveDialogRequest(
|
|||||||
)
|
)
|
||||||
|
|
||||||
class UixManager(private val latinIME: LatinIME) {
|
class UixManager(private val latinIME: LatinIME) {
|
||||||
|
internal val composeView: ComposeView?
|
||||||
|
get() = latinIME.composeView
|
||||||
|
|
||||||
private var shouldShowSuggestionStrip: Boolean = true
|
private var shouldShowSuggestionStrip: Boolean = true
|
||||||
private var suggestedWords: SuggestedWords? = null
|
private var suggestedWords: SuggestedWords? = null
|
||||||
|
|
||||||
private var composeView: ComposeView? = null
|
|
||||||
|
|
||||||
private var currWindowAction: Action? = null
|
private var currWindowAction: Action? = null
|
||||||
private var persistentStates: HashMap<Action, PersistentActionState?> = hashMapOf()
|
private var persistentStates: HashMap<Action, PersistentActionState?> = hashMapOf()
|
||||||
|
|
||||||
@ -327,6 +350,9 @@ class UixManager(private val latinIME: LatinIME) {
|
|||||||
latinIME.deferSetSetting(ActionBarExpanded, isActionsExpanded.value)
|
latinIME.deferSetSetting(ActionBarExpanded, isActionsExpanded.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val actionsExpanded: Boolean
|
||||||
|
get() = isActionsExpanded.value
|
||||||
|
|
||||||
private var isShowingActionEditor = mutableStateOf(false)
|
private var isShowingActionEditor = mutableStateOf(false)
|
||||||
fun showActionEditor() {
|
fun showActionEditor() {
|
||||||
isShowingActionEditor.value = true
|
isShowingActionEditor.value = true
|
||||||
@ -337,6 +363,12 @@ class UixManager(private val latinIME: LatinIME) {
|
|||||||
var isInputOverridden = mutableStateOf(false)
|
var isInputOverridden = mutableStateOf(false)
|
||||||
|
|
||||||
var currWindowActionWindow: ActionWindow? = null
|
var currWindowActionWindow: ActionWindow? = null
|
||||||
|
val isActionWindowDocked: Boolean
|
||||||
|
get() = currWindowActionWindow != null
|
||||||
|
|
||||||
|
private var measuredTouchableHeight = 0
|
||||||
|
val touchableHeight: Int
|
||||||
|
get() = measuredTouchableHeight
|
||||||
|
|
||||||
val isMainKeyboardHidden get() = mainKeyboardHidden
|
val isMainKeyboardHidden get() = mainKeyboardHidden
|
||||||
|
|
||||||
@ -626,6 +658,129 @@ class UixManager(private val latinIME: LatinIME) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SizePositionerSurface(content: @Composable BoxScope.(actionBarGap: Dp) -> Unit) {
|
||||||
|
val size = latinIME.size.value
|
||||||
|
when(size) {
|
||||||
|
is FloatingKeyboardSize -> {
|
||||||
|
val offset = remember(size) { mutableStateOf(Offset(size.bottomOrigin.first.toFloat(), size.bottomOrigin.second.toFloat())) }
|
||||||
|
val configuration = LocalConfiguration.current
|
||||||
|
with(LocalDensity.current) {
|
||||||
|
Column(modifier = Modifier.fillMaxHeight().absoluteOffset { IntOffset(offset.value.x.toInt(), 0) }) {
|
||||||
|
Spacer(Modifier.weight(1.0f))
|
||||||
|
Column(Modifier
|
||||||
|
.background(latinIME.keyboardColor, RoundedCornerShape(8.dp))
|
||||||
|
.requiredWidth(size.width.toDp())
|
||||||
|
.onSizeChanged {
|
||||||
|
measuredTouchableHeight = it.height
|
||||||
|
}
|
||||||
|
.absolutePadding(
|
||||||
|
left = size.decorationPadding.left.toDp(),
|
||||||
|
top = 0.dp,
|
||||||
|
right = size.decorationPadding.right.toDp(),
|
||||||
|
bottom = 0.dp,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Box(Modifier.fillMaxWidth()) {
|
||||||
|
CompositionLocalProvider(
|
||||||
|
LocalContentColor provides contentColorFor(
|
||||||
|
latinIME.keyboardColor
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
content(4.dp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(20.dp)
|
||||||
|
.pointerInput(size) {
|
||||||
|
detectDragGestures(onDrag = { change, dragAmount ->
|
||||||
|
var newOffset = offset.value.copy(
|
||||||
|
x = offset.value.x + dragAmount.x,
|
||||||
|
y = offset.value.y - dragAmount.y
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ensure we are not out of bounds
|
||||||
|
newOffset = newOffset.copy(
|
||||||
|
newOffset.x.coerceAtLeast(0.0f),
|
||||||
|
newOffset.y.coerceAtLeast(0.0f)
|
||||||
|
)
|
||||||
|
newOffset = newOffset.copy(
|
||||||
|
newOffset.x.coerceAtMost(configuration.screenWidthDp.dp.toPx() - size.width),
|
||||||
|
newOffset.y.coerceAtMost(latinIME.getViewHeight().toFloat() - measuredTouchableHeight)
|
||||||
|
)
|
||||||
|
|
||||||
|
offset.value = newOffset
|
||||||
|
}, onDragEnd = {
|
||||||
|
latinIME.sizingCalculator.editSavedSettings { settings ->
|
||||||
|
settings.copy(
|
||||||
|
floatingBottomCenterOriginDp = Pair(
|
||||||
|
offset.value.x.toDp().value,
|
||||||
|
offset.value.y.toDp().value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}) {
|
||||||
|
Box(modifier = Modifier.fillMaxWidth(0.6f).height(4.dp).align(Alignment.TopCenter).background(
|
||||||
|
MaterialTheme.colorScheme.onBackground.copy(alpha = 0.6f), RoundedCornerShape(100)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(Modifier.height(offset.value.y.toDp()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is OneHandedKeyboardSize,
|
||||||
|
is RegularKeyboardSize,
|
||||||
|
is SplitKeyboardSize -> {
|
||||||
|
Column {
|
||||||
|
Spacer(modifier = Modifier.weight(1.0f))
|
||||||
|
Surface(modifier = Modifier.onSizeChanged {
|
||||||
|
measuredTouchableHeight = it.height
|
||||||
|
}, color = latinIME.keyboardColor) {
|
||||||
|
with(LocalDensity.current) {
|
||||||
|
val actionBarGap = (size.getPadding().top / 2).toDp()
|
||||||
|
Box(Modifier.absolutePadding(
|
||||||
|
left = size.getPadding().left.toDp(),
|
||||||
|
top = actionBarGap,
|
||||||
|
right = size.getPadding().right.toDp(),
|
||||||
|
bottom = size.getPadding().bottom.toDp(),
|
||||||
|
).width(
|
||||||
|
(size.getWidth() - size.getPadding().left - size.getPadding().right).toDp()
|
||||||
|
)) {
|
||||||
|
when(size) {
|
||||||
|
is OneHandedKeyboardSize -> {
|
||||||
|
Box(modifier = Modifier.width(size.layoutWidth.toDp()).align(
|
||||||
|
when(size.direction) {
|
||||||
|
OneHandedDirection.Left -> Alignment.CenterStart
|
||||||
|
OneHandedDirection.Right -> Alignment.CenterEnd
|
||||||
|
}
|
||||||
|
)) {
|
||||||
|
content(actionBarGap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is RegularKeyboardSize -> {
|
||||||
|
content(actionBarGap)
|
||||||
|
}
|
||||||
|
is SplitKeyboardSize -> {
|
||||||
|
content(actionBarGap)
|
||||||
|
}
|
||||||
|
else -> throw IllegalStateException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
null -> return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun setContent() {
|
fun setContent() {
|
||||||
composeView?.setContent {
|
composeView?.setContent {
|
||||||
UixThemeWrapper(latinIME.colorScheme) {
|
UixThemeWrapper(latinIME.colorScheme) {
|
||||||
@ -639,29 +794,22 @@ class UixManager(private val latinIME: LatinIME) {
|
|||||||
isShowingActionEditor.value = false
|
isShowingActionEditor.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
SizePositionerSurface { gap ->
|
||||||
Spacer(modifier = Modifier.weight(1.0f))
|
Column {
|
||||||
Surface(modifier = Modifier.onSizeChanged {
|
when {
|
||||||
latinIME.updateTouchableHeight(it.height)
|
currWindowActionWindow != null -> ActionViewWithHeader(
|
||||||
}, color = latinIME.keyboardColor) {
|
currWindowActionWindow!!
|
||||||
Box {
|
)
|
||||||
Column {
|
|
||||||
when {
|
|
||||||
currWindowActionWindow != null -> ActionViewWithHeader(
|
|
||||||
currWindowActionWindow!!
|
|
||||||
)
|
|
||||||
|
|
||||||
else -> MainKeyboardViewWithActionBar()
|
else -> MainKeyboardViewWithActionBar()
|
||||||
}
|
|
||||||
|
|
||||||
latinIME.LegacyKeyboardView(hidden = isMainKeyboardHidden)
|
|
||||||
}
|
|
||||||
|
|
||||||
ForgetWordDialog()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(gap))
|
||||||
|
|
||||||
|
latinIME.LegacyKeyboardView(hidden = isMainKeyboardHidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ForgetWordDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionEditorHost()
|
ActionEditorHost()
|
||||||
@ -734,28 +882,6 @@ class UixManager(private val latinIME: LatinIME) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createComposeView(): View {
|
|
||||||
if(composeView != null) {
|
|
||||||
composeView = null
|
|
||||||
//throw IllegalStateException("Attempted to create compose view, when one is already created!")
|
|
||||||
}
|
|
||||||
|
|
||||||
composeView = ComposeView(latinIME).apply {
|
|
||||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
|
||||||
setParentCompositionContext(null)
|
|
||||||
|
|
||||||
latinIME.setOwners()
|
|
||||||
}
|
|
||||||
|
|
||||||
setContent()
|
|
||||||
|
|
||||||
return composeView!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getComposeView(): View? {
|
|
||||||
return composeView
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onColorSchemeChanged() {
|
fun onColorSchemeChanged() {
|
||||||
setContent()
|
setContent()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
package org.futo.inputmethod.latin.uix.actions
|
||||||
|
|
||||||
|
import org.futo.inputmethod.latin.R
|
||||||
|
import org.futo.inputmethod.latin.uix.Action
|
||||||
|
import org.futo.inputmethod.v2keyboard.KeyboardMode
|
||||||
|
import org.futo.inputmethod.v2keyboard.OneHandedDirection
|
||||||
|
|
||||||
|
val LeftHandedKeyboardAction = Action(
|
||||||
|
icon = R.drawable.arrow_left,
|
||||||
|
name = R.string.left_handed_keyboard_action_title,
|
||||||
|
simplePressImpl = { manager, _ ->
|
||||||
|
manager.getSizingCalculator().editSavedSettings {
|
||||||
|
if(it.currentMode == KeyboardMode.OneHanded
|
||||||
|
&& it.oneHandedDirection == OneHandedDirection.Left) {
|
||||||
|
it.copy(
|
||||||
|
currentMode = KeyboardMode.Regular
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
it.copy(
|
||||||
|
oneHandedDirection = OneHandedDirection.Left,
|
||||||
|
currentMode = KeyboardMode.OneHanded
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
windowImpl = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
val RightHandedKeyboardAction = Action(
|
||||||
|
icon = R.drawable.arrow_right,
|
||||||
|
name = R.string.right_handed_keyboard_action_title,
|
||||||
|
simplePressImpl = { manager, _ ->
|
||||||
|
manager.getSizingCalculator().editSavedSettings {
|
||||||
|
if(it.currentMode == KeyboardMode.OneHanded
|
||||||
|
&& it.oneHandedDirection == OneHandedDirection.Right) {
|
||||||
|
it.copy(
|
||||||
|
currentMode = KeyboardMode.Regular
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
it.copy(
|
||||||
|
oneHandedDirection = OneHandedDirection.Right,
|
||||||
|
currentMode = KeyboardMode.OneHanded
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
windowImpl = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
val SplitKeyboardAction = Action(
|
||||||
|
icon = R.drawable.arrow_down,
|
||||||
|
name = R.string.split_keyboard_action_title,
|
||||||
|
simplePressImpl = { manager, _ ->
|
||||||
|
manager.getSizingCalculator().editSavedSettings {
|
||||||
|
if(it.currentMode == KeyboardMode.Split) {
|
||||||
|
it.copy(
|
||||||
|
currentMode = KeyboardMode.Regular
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
it.copy(
|
||||||
|
currentMode = KeyboardMode.Split
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
windowImpl = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
val FloatingKeyboardAction = Action(
|
||||||
|
icon = R.drawable.arrow_up,
|
||||||
|
name = R.string.floating_keyboard_action_title,
|
||||||
|
simplePressImpl = { manager, _ ->
|
||||||
|
manager.getSizingCalculator().editSavedSettings {
|
||||||
|
if(it.currentMode == KeyboardMode.Floating) {
|
||||||
|
it.copy(
|
||||||
|
currentMode = KeyboardMode.Regular
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
it.copy(
|
||||||
|
currentMode = KeyboardMode.Floating
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
windowImpl = null,
|
||||||
|
)
|
@ -31,7 +31,11 @@ val AllActionsMap = mapOf(
|
|||||||
"copy" to CopyAction,
|
"copy" to CopyAction,
|
||||||
"select_all" to SelectAllAction,
|
"select_all" to SelectAllAction,
|
||||||
"more" to MoreActionsAction,
|
"more" to MoreActionsAction,
|
||||||
"bugs" to BugViewerAction
|
"bugs" to BugViewerAction,
|
||||||
|
"onehanded_left" to LeftHandedKeyboardAction,
|
||||||
|
"onehanded_right" to RightHandedKeyboardAction,
|
||||||
|
"split_keyboard" to SplitKeyboardAction,
|
||||||
|
"floating_keyboard" to FloatingKeyboardAction
|
||||||
)
|
)
|
||||||
|
|
||||||
val ActionToId = AllActionsMap.entries.associate { it.value to it.key }
|
val ActionToId = AllActionsMap.entries.associate { it.value to it.key }
|
||||||
|
@ -76,16 +76,12 @@ fun getPrimaryLayoutOverride(editorInfo: EditorInfo?): String? {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class KeyboardLayoutSetV2Params(
|
data class KeyboardLayoutSetV2Params(
|
||||||
val width: Int,
|
val computedSize: ComputedKeyboardSize,
|
||||||
val height: Int,
|
|
||||||
val padding: Rect,
|
|
||||||
val keyboardLayoutSet: String,
|
val keyboardLayoutSet: String,
|
||||||
val locale: Locale,
|
val locale: Locale,
|
||||||
val editorInfo: EditorInfo?,
|
val editorInfo: EditorInfo?,
|
||||||
val numberRow: Boolean,
|
val numberRow: Boolean,
|
||||||
val gap: Float = 4.0f,
|
val gap: Float = 4.0f,
|
||||||
val useSplitLayout: Boolean,
|
|
||||||
val splitLayoutWidth: Int,
|
|
||||||
val bottomActionKey: Int?,
|
val bottomActionKey: Int?,
|
||||||
val longPressKeySettings: LongPressKeySettings? = null
|
val longPressKeySettings: LongPressKeySettings? = null
|
||||||
)
|
)
|
||||||
@ -184,14 +180,15 @@ class KeyboardLayoutSetV2 internal constructor(
|
|||||||
NumberRowMode.AlwaysDisabled -> false
|
NumberRowMode.AlwaysDisabled -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
private val widthMinusPadding = params.width - params.padding.left - params.padding.right
|
private val height = params.computedSize.getHeight()
|
||||||
private val heightMinusPadding = params.height - params.padding.top - params.padding.bottom
|
|
||||||
|
private val padding = params.computedSize.getPadding()
|
||||||
|
|
||||||
|
private val widthMinusPadding = params.computedSize.getTotalKeyboardWidth()
|
||||||
|
private val heightMinusPadding = height - padding.top - padding.bottom
|
||||||
|
|
||||||
private val singularRowHeight: Double
|
private val singularRowHeight: Double
|
||||||
get() = heightMinusPadding?.let { it / 4.0 } ?: run {
|
get() = heightMinusPadding / 4.0
|
||||||
(ResourceUtils.getDefaultKeyboardHeight(context.resources) / 4.0) *
|
|
||||||
keyboardHeightMultiplier
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getKeyboard(element: KeyboardLayoutElement): Keyboard {
|
fun getKeyboard(element: KeyboardLayoutElement): Keyboard {
|
||||||
|
|
||||||
@ -221,10 +218,8 @@ class KeyboardLayoutSetV2 internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val layoutParams = LayoutParams(
|
val layoutParams = LayoutParams(
|
||||||
|
size = params.computedSize,
|
||||||
gap = params.gap.dp,
|
gap = params.gap.dp,
|
||||||
useSplitLayout = params.useSplitLayout,
|
|
||||||
splitLayoutWidth = params.splitLayoutWidth,
|
|
||||||
padding = params.padding,
|
|
||||||
standardRowHeight = singularRowHeight,
|
standardRowHeight = singularRowHeight,
|
||||||
element = element
|
element = element
|
||||||
)
|
)
|
||||||
|
@ -2,12 +2,27 @@ package org.futo.inputmethod.v2keyboard
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||||
import androidx.datastore.preferences.core.floatPreferencesKey
|
|
||||||
import androidx.window.layout.FoldingFeature
|
import androidx.window.layout.FoldingFeature
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Serializer
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||||
|
import kotlinx.serialization.descriptors.element
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
import kotlinx.serialization.encoding.CompositeDecoder
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
import kotlinx.serialization.encoding.decodeStructure
|
||||||
|
import kotlinx.serialization.encoding.encodeStructure
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
import org.futo.inputmethod.latin.FoldStateProvider
|
import org.futo.inputmethod.latin.FoldStateProvider
|
||||||
|
import org.futo.inputmethod.latin.LatinIME
|
||||||
import org.futo.inputmethod.latin.uix.SettingsKey
|
import org.futo.inputmethod.latin.uix.SettingsKey
|
||||||
|
import org.futo.inputmethod.latin.uix.UixManager
|
||||||
import org.futo.inputmethod.latin.uix.getSettingBlocking
|
import org.futo.inputmethod.latin.uix.getSettingBlocking
|
||||||
|
import org.futo.inputmethod.latin.uix.setSettingBlocking
|
||||||
import org.futo.inputmethod.latin.utils.ResourceUtils
|
import org.futo.inputmethod.latin.utils.ResourceUtils
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@ -17,13 +32,139 @@ interface KeyboardSizeStateProvider {
|
|||||||
|
|
||||||
sealed class ComputedKeyboardSize()
|
sealed class ComputedKeyboardSize()
|
||||||
|
|
||||||
class RegularKeyboardSize(val height: Int, val padding: Rect) : ComputedKeyboardSize()
|
class RegularKeyboardSize(val height: Int, val width: Int, val padding: Rect) : ComputedKeyboardSize()
|
||||||
|
|
||||||
class SplitKeyboardSize(val height: Int, val padding: Rect, val splitLayoutWidth: Int) : ComputedKeyboardSize()
|
class SplitKeyboardSize(val height: Int, val width: Int, val padding: Rect, val splitLayoutWidth: Int) : ComputedKeyboardSize()
|
||||||
|
|
||||||
//class OneHandedKeyboardSize(val height: Int, val offset: Int, val sideInset: Int, val isLeft: Boolean, val width: Int): ComputedKeyboardSize()
|
enum class OneHandedDirection {
|
||||||
//class FloatingKeyboardSize(val x: Int, val y: Int, val width: Int, val height: Int): ComputedKeyboardSize()
|
Left,
|
||||||
|
Right
|
||||||
|
}
|
||||||
|
|
||||||
|
class OneHandedKeyboardSize(val height: Int, val width: Int, val padding: Rect, val layoutWidth: Int, val direction: OneHandedDirection): ComputedKeyboardSize()
|
||||||
|
|
||||||
|
class FloatingKeyboardSize(
|
||||||
|
val bottomOrigin: Pair<Int, Int>,
|
||||||
|
val width: Int,
|
||||||
|
val height: Int,
|
||||||
|
val decorationPadding: Rect
|
||||||
|
): ComputedKeyboardSize()
|
||||||
|
|
||||||
|
fun ComputedKeyboardSize.getHeight(): Int = when(this) {
|
||||||
|
is FloatingKeyboardSize -> height
|
||||||
|
is OneHandedKeyboardSize -> height
|
||||||
|
is RegularKeyboardSize -> height
|
||||||
|
is SplitKeyboardSize -> height
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ComputedKeyboardSize.getWidth(): Int = when(this) {
|
||||||
|
is FloatingKeyboardSize -> width
|
||||||
|
is OneHandedKeyboardSize -> width
|
||||||
|
is RegularKeyboardSize -> width
|
||||||
|
is SplitKeyboardSize -> width
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ComputedKeyboardSize.getPadding(): Rect = when(this) {
|
||||||
|
is FloatingKeyboardSize -> decorationPadding
|
||||||
|
is OneHandedKeyboardSize -> padding
|
||||||
|
is RegularKeyboardSize -> padding
|
||||||
|
is SplitKeyboardSize -> padding
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ComputedKeyboardSize.getTotalKeyboardWidth(): Int = when(this) {
|
||||||
|
is FloatingKeyboardSize -> width - decorationPadding.left - decorationPadding.right
|
||||||
|
is OneHandedKeyboardSize -> layoutWidth
|
||||||
|
is RegularKeyboardSize -> width - padding.left - padding.right
|
||||||
|
is SplitKeyboardSize -> width - padding.left - padding.right
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class KeyboardMode {
|
||||||
|
Regular,
|
||||||
|
Split,
|
||||||
|
OneHanded,
|
||||||
|
Floating
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Serializer(forClass = Rect::class)
|
||||||
|
object RectSerializer : KSerializer<Rect> {
|
||||||
|
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Rect") {
|
||||||
|
element<Int>("left")
|
||||||
|
element<Int>("top")
|
||||||
|
element<Int>("right")
|
||||||
|
element<Int>("bottom")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, value: Rect) {
|
||||||
|
encoder.encodeStructure(descriptor) {
|
||||||
|
encodeIntElement(descriptor, 0, value.left)
|
||||||
|
encodeIntElement(descriptor, 1, value.top)
|
||||||
|
encodeIntElement(descriptor, 2, value.right)
|
||||||
|
encodeIntElement(descriptor, 3, value.bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): Rect {
|
||||||
|
return decoder.decodeStructure(descriptor) {
|
||||||
|
var left = 0
|
||||||
|
var top = 0
|
||||||
|
var right = 0
|
||||||
|
var bottom = 0
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
when (val index = decodeElementIndex(descriptor)) {
|
||||||
|
0 -> left = decodeIntElement(descriptor, 0)
|
||||||
|
1 -> top = decodeIntElement(descriptor, 1)
|
||||||
|
2 -> right = decodeIntElement(descriptor, 2)
|
||||||
|
3 -> bottom = decodeIntElement(descriptor, 3)
|
||||||
|
CompositeDecoder.DECODE_DONE -> break
|
||||||
|
else -> error("Unexpected index: $index")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect(left, top, right, bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class SavedKeyboardSizingSettings(
|
||||||
|
val currentMode: KeyboardMode,
|
||||||
|
val heightMultiplier: Float,
|
||||||
|
val paddingDp: @Serializable(RectSerializer::class) Rect,
|
||||||
|
|
||||||
|
// Split
|
||||||
|
val splitWidthFraction: Float,
|
||||||
|
|
||||||
|
// One handed, values with respect to left handed mode
|
||||||
|
// left = padding
|
||||||
|
// right = width + padding
|
||||||
|
// bottom = padding for bottom
|
||||||
|
val oneHandedRectDp: @Serializable(RectSerializer::class) Rect,
|
||||||
|
val oneHandedDirection: OneHandedDirection,
|
||||||
|
|
||||||
|
// Floating
|
||||||
|
val floatingBottomCenterOriginDp: Pair<Float, Float>, // relative to bottom left of screen, .second is Y up
|
||||||
|
val floatingWidthDp: Float,
|
||||||
|
val floatingHeightDp: Float
|
||||||
|
) {
|
||||||
|
fun toJsonString(): String =
|
||||||
|
Json.encodeToString(this)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun fromJsonString(s: String): SavedKeyboardSizingSettings? =
|
||||||
|
try {
|
||||||
|
Json.decodeFromString(s)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
//e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum class KeyboardSizeSettingKind {
|
enum class KeyboardSizeSettingKind {
|
||||||
Portrait,
|
Portrait,
|
||||||
@ -31,117 +172,231 @@ enum class KeyboardSizeSettingKind {
|
|||||||
FoldableInnerDisplay
|
FoldableInnerDisplay
|
||||||
}
|
}
|
||||||
|
|
||||||
val SplitKeyboardSettings = mapOf(
|
val DefaultKeyboardSettings = mapOf(
|
||||||
KeyboardSizeSettingKind.Portrait to SettingsKey(
|
KeyboardSizeSettingKind.Portrait to SavedKeyboardSizingSettings(
|
||||||
booleanPreferencesKey("split_keyboard_portrait"), false),
|
currentMode = KeyboardMode.Regular,
|
||||||
KeyboardSizeSettingKind.Landscape to SettingsKey(
|
heightMultiplier = 1.0f,
|
||||||
booleanPreferencesKey("split_keyboard_landscape"), true),
|
paddingDp = Rect(2, 4, 2, 10),
|
||||||
KeyboardSizeSettingKind.FoldableInnerDisplay to SettingsKey(
|
splitWidthFraction = 4.0f / 5.0f,
|
||||||
booleanPreferencesKey("split_keyboard_fold"), true),
|
oneHandedDirection = OneHandedDirection.Right,
|
||||||
|
oneHandedRectDp = Rect(4, 4, 364, 30),
|
||||||
|
floatingBottomCenterOriginDp = Pair(0.0f, 0.0f),
|
||||||
|
floatingHeightDp = 240.0f,
|
||||||
|
floatingWidthDp = 360.0f
|
||||||
|
),
|
||||||
|
|
||||||
|
KeyboardSizeSettingKind.Landscape to SavedKeyboardSizingSettings(
|
||||||
|
currentMode = KeyboardMode.Split,
|
||||||
|
heightMultiplier = 0.9f,
|
||||||
|
paddingDp = Rect(8, 2, 8, 2),
|
||||||
|
splitWidthFraction = 3.0f / 5.0f,
|
||||||
|
oneHandedDirection = OneHandedDirection.Right,
|
||||||
|
oneHandedRectDp = Rect(4, 4, 364, 30),
|
||||||
|
floatingBottomCenterOriginDp = Pair(0.0f, 0.0f),
|
||||||
|
floatingHeightDp = 240.0f,
|
||||||
|
floatingWidthDp = 360.0f
|
||||||
|
),
|
||||||
|
|
||||||
|
KeyboardSizeSettingKind.FoldableInnerDisplay to SavedKeyboardSizingSettings(
|
||||||
|
currentMode = KeyboardMode.Split,
|
||||||
|
heightMultiplier = 0.67f,
|
||||||
|
paddingDp = Rect(44, 4, 44, 8),
|
||||||
|
splitWidthFraction = 3.0f / 5.0f,
|
||||||
|
oneHandedDirection = OneHandedDirection.Right,
|
||||||
|
oneHandedRectDp = Rect(4, 4, 364, 30),
|
||||||
|
floatingBottomCenterOriginDp = Pair(0.0f, 0.0f),
|
||||||
|
floatingHeightDp = 240.0f,
|
||||||
|
floatingWidthDp = 360.0f
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
val KeyboardHeightSettings = mapOf(
|
val KeyboardSettings = mapOf(
|
||||||
KeyboardSizeSettingKind.Portrait to SettingsKey(
|
KeyboardSizeSettingKind.Portrait to SettingsKey(
|
||||||
floatPreferencesKey("keyboardHeightMultiplier"), 1.0f),
|
stringPreferencesKey("keyboard_settings_portrait"), ""),
|
||||||
KeyboardSizeSettingKind.Landscape to SettingsKey(
|
KeyboardSizeSettingKind.Landscape to SettingsKey(
|
||||||
floatPreferencesKey("keyboard_height_landscape"), 0.9f),
|
stringPreferencesKey("keyboard_settings_landscape"), ""),
|
||||||
KeyboardSizeSettingKind.FoldableInnerDisplay to SettingsKey(
|
KeyboardSizeSettingKind.FoldableInnerDisplay to SettingsKey(
|
||||||
floatPreferencesKey("keyboard_height_fold"), 0.67f),
|
stringPreferencesKey("keyboard_settings_fold"), ""),
|
||||||
)
|
)
|
||||||
|
|
||||||
val KeyboardOffsetSettings = mapOf(
|
class KeyboardSizingCalculator(val context: Context, val uixManager: UixManager) {
|
||||||
KeyboardSizeSettingKind.Portrait to SettingsKey(
|
val sizeStateProvider = context as KeyboardSizeStateProvider
|
||||||
floatPreferencesKey("keyboard_offset_portrait"), 8.0f),
|
val foldStateProvider = context as FoldStateProvider
|
||||||
KeyboardSizeSettingKind.Landscape to SettingsKey(
|
|
||||||
floatPreferencesKey("keyboard_offset_landscape"), 0.0f),
|
|
||||||
KeyboardSizeSettingKind.FoldableInnerDisplay to SettingsKey(
|
|
||||||
floatPreferencesKey("keyboard_offset_fold"), 8.0f),
|
|
||||||
)
|
|
||||||
|
|
||||||
val KeyboardSideInsetSettings = mapOf(
|
private fun dp(v: Number): Int =
|
||||||
KeyboardSizeSettingKind.Portrait to SettingsKey(
|
(v.toFloat() * context.resources.displayMetrics.density).toInt()
|
||||||
floatPreferencesKey("keyboard_inset_portrait"), 2.0f),
|
|
||||||
KeyboardSizeSettingKind.Landscape to SettingsKey(
|
private fun dp(v: Rect): Rect =
|
||||||
floatPreferencesKey("keyboard_inset_landscape"), 8.0f),
|
Rect(dp(v.left), dp(v.top), dp(v.right), dp(v.bottom))
|
||||||
KeyboardSizeSettingKind.FoldableInnerDisplay to SettingsKey(
|
|
||||||
floatPreferencesKey("keyboard_inset_fold"), 44.0f),
|
private fun limitFloating(rectPx: Rect): Rect {
|
||||||
)
|
val width = rectPx.width()
|
||||||
|
val height = rectPx.height()
|
||||||
|
|
||||||
|
val minWidth = dp(160)
|
||||||
|
val minHeight = dp(160)
|
||||||
|
|
||||||
|
if(width < minWidth) {
|
||||||
|
val delta = minWidth - width
|
||||||
|
rectPx.left -= delta / 2
|
||||||
|
rectPx.right += delta / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if(height < minHeight) {
|
||||||
|
val delta = minHeight - height
|
||||||
|
rectPx.top -= delta
|
||||||
|
rectPx.bottom += delta
|
||||||
|
}
|
||||||
|
|
||||||
|
val maxWidth = context.resources.displayMetrics.widthPixels * 2 / 3
|
||||||
|
val maxHeight = context.resources.displayMetrics.heightPixels * 2 / 3
|
||||||
|
|
||||||
|
if(width > maxWidth) {
|
||||||
|
val delta = width - maxWidth
|
||||||
|
rectPx.left += delta / 2
|
||||||
|
rectPx.right -= delta / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if(height > maxHeight) {
|
||||||
|
val delta = height - maxHeight
|
||||||
|
rectPx.top += delta / 2
|
||||||
|
rectPx.bottom -= delta / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class KeyboardSizingCalculator(val context: Context) {
|
val originX = rectPx.left
|
||||||
private val sizeStateProvider = context as KeyboardSizeStateProvider
|
val originY = rectPx.top
|
||||||
private val foldStateProvider = context as FoldStateProvider
|
|
||||||
|
|
||||||
private fun isSplitKeyboard(mode: KeyboardSizeSettingKind): Boolean =
|
if(originX < 0){
|
||||||
context.getSettingBlocking(SplitKeyboardSettings[mode]!!)
|
rectPx.left -= originX
|
||||||
|
rectPx.right -= originX
|
||||||
|
}
|
||||||
|
|
||||||
private fun heightMultiplier(mode: KeyboardSizeSettingKind): Float =
|
if(originY < 0) {
|
||||||
context.getSettingBlocking(KeyboardHeightSettings[mode]!!)
|
rectPx.top -= originY
|
||||||
|
rectPx.bottom -= originY
|
||||||
|
}
|
||||||
|
|
||||||
private fun bottomOffsetPx(mode: KeyboardSizeSettingKind): Int =
|
if(rectPx.right > context.resources.displayMetrics.widthPixels) {
|
||||||
(context.getSettingBlocking(KeyboardOffsetSettings[mode]!!) * context.resources.displayMetrics.density).toInt()
|
val delta = rectPx.right - context.resources.displayMetrics.widthPixels
|
||||||
|
rectPx.right -= delta
|
||||||
|
rectPx.left -= delta
|
||||||
|
}
|
||||||
|
if(rectPx.bottom < 0) {
|
||||||
|
val delta = rectPx.bottom
|
||||||
|
rectPx.top -= delta
|
||||||
|
rectPx.bottom -= delta
|
||||||
|
}
|
||||||
|
|
||||||
private fun sideInsetPx(mode: KeyboardSizeSettingKind): Int =
|
return rectPx
|
||||||
(context.getSettingBlocking(KeyboardSideInsetSettings[mode]!!) * context.resources.displayMetrics.density).toInt()
|
}
|
||||||
|
|
||||||
private fun topPaddingPx(mode: KeyboardSizeSettingKind): Int =
|
fun getSavedSettings(): SavedKeyboardSizingSettings =
|
||||||
(when(mode) {
|
SavedKeyboardSizingSettings.fromJsonString(context.getSettingBlocking(
|
||||||
KeyboardSizeSettingKind.Portrait -> 4.0f
|
KeyboardSettings[sizeStateProvider.currentSizeState]!!
|
||||||
KeyboardSizeSettingKind.Landscape -> 0.0f
|
)) ?: DefaultKeyboardSettings[sizeStateProvider.currentSizeState]!!
|
||||||
KeyboardSizeSettingKind.FoldableInnerDisplay -> 8.0f
|
|
||||||
} * context.resources.displayMetrics.density).toInt()
|
fun editSavedSettings(transform: (SavedKeyboardSizingSettings) -> SavedKeyboardSizingSettings) {
|
||||||
|
val sizeState = sizeStateProvider.currentSizeState
|
||||||
|
|
||||||
|
val savedSettings = SavedKeyboardSizingSettings.fromJsonString(context.getSettingBlocking(
|
||||||
|
KeyboardSettings[sizeState]!!
|
||||||
|
)) ?: DefaultKeyboardSettings[sizeState]!!
|
||||||
|
|
||||||
|
val transformed = transform(savedSettings)
|
||||||
|
|
||||||
|
if(transformed != savedSettings) {
|
||||||
|
context.setSettingBlocking(KeyboardSettings[sizeState]!!.key, transformed.toJsonString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun calculate(layoutName: String, isNumberRowActive: Boolean): ComputedKeyboardSize {
|
fun calculate(layoutName: String, isNumberRowActive: Boolean): ComputedKeyboardSize {
|
||||||
|
val savedSettings = getSavedSettings()
|
||||||
|
|
||||||
val layout = LayoutManager.getLayout(context, layoutName)
|
val layout = LayoutManager.getLayout(context, layoutName)
|
||||||
val effectiveRowCount = layout.effectiveRows.size
|
val effectiveRowCount = layout.effectiveRows.size
|
||||||
|
|
||||||
val configuration = context.resources.configuration
|
|
||||||
val displayMetrics = context.resources.displayMetrics
|
val displayMetrics = context.resources.displayMetrics
|
||||||
|
println("Display metrics ${displayMetrics.widthPixels / displayMetrics.density}")
|
||||||
|
|
||||||
val mode = sizeStateProvider.currentSizeState
|
val singularRowHeight = (ResourceUtils.getDefaultKeyboardHeight(context.resources) / 4.0) *
|
||||||
|
savedSettings.heightMultiplier
|
||||||
val isSplit = isSplitKeyboard(mode)
|
|
||||||
val heightMultiplier = heightMultiplier(mode)
|
|
||||||
val bottomOffset = bottomOffsetPx(mode)
|
|
||||||
val sideInset = sideInsetPx(mode)
|
|
||||||
val topPadding = topPaddingPx(mode)
|
|
||||||
|
|
||||||
val singularRowHeight = (ResourceUtils.getDefaultKeyboardHeight(context.resources) / 4.0) * heightMultiplier
|
|
||||||
|
|
||||||
val numRows = 4.0 +
|
val numRows = 4.0 +
|
||||||
((effectiveRowCount - 5) / 2.0).coerceAtLeast(0.0) +
|
((effectiveRowCount - 5) / 2.0).coerceAtLeast(0.0) +
|
||||||
if(isNumberRowActive) { 0.5 } else { 0.0 }
|
if(isNumberRowActive) { 0.5 } else { 0.0 }
|
||||||
|
|
||||||
println("Num rows; $numRows, $effectiveRowCount ($layoutName) ($layout)")
|
|
||||||
|
|
||||||
val recommendedHeight = numRows * singularRowHeight
|
val recommendedHeight = numRows * singularRowHeight
|
||||||
|
|
||||||
|
|
||||||
val foldState = foldStateProvider.foldState.feature
|
val foldState = foldStateProvider.foldState.feature
|
||||||
|
|
||||||
|
val window = (context as LatinIME).window.window
|
||||||
|
val width = ResourceUtils.getDefaultKeyboardWidth(window, context.resources)
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
// Special case: 50% screen height no matter the row count or settings
|
// Special case: 50% screen height no matter the row count or settings
|
||||||
foldState != null && foldState.state == FoldingFeature.State.HALF_OPENED && foldState.orientation == FoldingFeature.Orientation.HORIZONTAL ->
|
foldState != null && foldState.state == FoldingFeature.State.HALF_OPENED && foldState.orientation == FoldingFeature.Orientation.HORIZONTAL ->
|
||||||
SplitKeyboardSize(
|
SplitKeyboardSize(
|
||||||
displayMetrics.heightPixels / 2 - (displayMetrics.density * 80.0f).toInt(),
|
height = displayMetrics.heightPixels / 2 - (displayMetrics.density * 80.0f).toInt(),
|
||||||
Rect(
|
width = width,
|
||||||
|
padding = Rect(
|
||||||
(displayMetrics.density * 44.0f).roundToInt(),
|
(displayMetrics.density * 44.0f).roundToInt(),
|
||||||
(displayMetrics.density * 20.0f).roundToInt(),
|
(displayMetrics.density * 50.0f).roundToInt(),
|
||||||
(displayMetrics.density * 44.0f).roundToInt(),
|
(displayMetrics.density * 44.0f).roundToInt(),
|
||||||
(displayMetrics.density * 12.0f).roundToInt(),
|
(displayMetrics.density * 12.0f).roundToInt(),
|
||||||
),
|
),
|
||||||
displayMetrics.widthPixels * 3 / 5
|
splitLayoutWidth = displayMetrics.widthPixels * 3 / 5
|
||||||
)
|
)
|
||||||
|
|
||||||
isSplit -> SplitKeyboardSize(
|
savedSettings.currentMode == KeyboardMode.Split ->
|
||||||
recommendedHeight.roundToInt(),
|
SplitKeyboardSize(
|
||||||
Rect(sideInset, topPadding, sideInset, bottomOffset),
|
height = recommendedHeight.roundToInt(),
|
||||||
displayMetrics.widthPixels * 3 / 5)
|
width = width,
|
||||||
|
padding = dp(savedSettings.paddingDp),
|
||||||
|
splitLayoutWidth = (displayMetrics.widthPixels * savedSettings.splitWidthFraction).toInt()
|
||||||
|
)
|
||||||
|
|
||||||
else -> RegularKeyboardSize(
|
savedSettings.currentMode == KeyboardMode.OneHanded ->
|
||||||
recommendedHeight.roundToInt(),
|
OneHandedKeyboardSize(
|
||||||
Rect(sideInset, topPadding, sideInset, bottomOffset),
|
height = recommendedHeight.roundToInt(),
|
||||||
)
|
width = width,
|
||||||
|
padding = dp(savedSettings.oneHandedRectDp).let { rect ->
|
||||||
|
when(savedSettings.oneHandedDirection) {
|
||||||
|
OneHandedDirection.Left -> Rect(rect.left, rect.top, rect.left, rect.bottom)
|
||||||
|
OneHandedDirection.Right -> Rect(rect.left, rect.top, rect.left, rect.bottom)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
layoutWidth = dp(savedSettings.oneHandedRectDp.width()).coerceAtMost(displayMetrics.widthPixels * 9 / 10),
|
||||||
|
direction = savedSettings.oneHandedDirection
|
||||||
|
)
|
||||||
|
|
||||||
|
savedSettings.currentMode == KeyboardMode.Floating -> {
|
||||||
|
val singularRowHeightFloat = dp(savedSettings.floatingHeightDp) / 4.0f
|
||||||
|
val recommendedHeightFloat = singularRowHeightFloat * numRows
|
||||||
|
FloatingKeyboardSize(
|
||||||
|
bottomOrigin = Pair(
|
||||||
|
dp(savedSettings.floatingBottomCenterOriginDp.first),
|
||||||
|
dp(savedSettings.floatingBottomCenterOriginDp.second)
|
||||||
|
),
|
||||||
|
width = dp(savedSettings.floatingWidthDp),
|
||||||
|
height = recommendedHeightFloat.toInt(),
|
||||||
|
decorationPadding = dp(
|
||||||
|
Rect(
|
||||||
|
8,
|
||||||
|
8,
|
||||||
|
8,
|
||||||
|
8
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else ->
|
||||||
|
RegularKeyboardSize(
|
||||||
|
height = recommendedHeight.roundToInt(),
|
||||||
|
width = width,
|
||||||
|
padding = dp(savedSettings.paddingDp)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,4 +410,14 @@ class KeyboardSizingCalculator(val context: Context) {
|
|||||||
|
|
||||||
return (minDp / 100.0f).coerceIn(3.0f, 6.0f)
|
return (minDp / 100.0f).coerceIn(3.0f, 6.0f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun calculateSuggestionBarHeightDp(): Float {
|
||||||
|
return 40.0f
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calculateTotalActionBarHeightPx(): Int =
|
||||||
|
when {
|
||||||
|
uixManager.actionsExpanded -> dp(2 * calculateSuggestionBarHeightDp())
|
||||||
|
else -> dp(calculateSuggestionBarHeightDp())
|
||||||
|
}
|
||||||
}
|
}
|
@ -81,10 +81,8 @@ data class LayoutRow(
|
|||||||
)
|
)
|
||||||
|
|
||||||
data class LayoutParams(
|
data class LayoutParams(
|
||||||
|
val size: ComputedKeyboardSize,
|
||||||
val gap: Dp,
|
val gap: Dp,
|
||||||
val useSplitLayout: Boolean,
|
|
||||||
val splitLayoutWidth: Int,
|
|
||||||
val padding: Rect,
|
|
||||||
val standardRowHeight: Double,
|
val standardRowHeight: Double,
|
||||||
val element: KeyboardLayoutElement,
|
val element: KeyboardLayoutElement,
|
||||||
)
|
)
|
||||||
@ -131,8 +129,6 @@ data class LayoutEngine(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun computeRowHeight(): Double {
|
private fun computeRowHeight(): Double {
|
||||||
//val normalKeyboardHeight = ((rowHeight.value + verticalGap.value) * density) * 3
|
|
||||||
|
|
||||||
val normalKeyboardHeight = totalRowHeight
|
val normalKeyboardHeight = totalRowHeight
|
||||||
|
|
||||||
// divide by total row height
|
// divide by total row height
|
||||||
@ -140,19 +136,29 @@ data class LayoutEngine(
|
|||||||
BottomRowHeightMode.Fixed -> ((normalKeyboardHeight - layoutParams.standardRowHeight) / rows.filter { !it.isBottomRow }.sumOf { it.rowHeight })
|
BottomRowHeightMode.Fixed -> ((normalKeyboardHeight - layoutParams.standardRowHeight) / rows.filter { !it.isBottomRow }.sumOf { it.rowHeight })
|
||||||
BottomRowHeightMode.Flexible -> (normalKeyboardHeight) / rows.sumOf { it.rowHeight }
|
BottomRowHeightMode.Flexible -> (normalKeyboardHeight) / rows.sumOf { it.rowHeight }
|
||||||
}
|
}
|
||||||
//return ((normalKeyboardHeight - bottomRowHeightPx) / rows.filter { !it.isBottomRow }.sumOf { it.rowHeight })
|
|
||||||
//return (normalKeyboardHeight) / rows.sumOf { it.rowHeight }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val isSplitLayout = layoutParams.useSplitLayout
|
private val isSplitLayout = layoutParams.size is SplitKeyboardSize
|
||||||
|
private val isOneHandedLayout = layoutParams.size is OneHandedKeyboardSize
|
||||||
|
|
||||||
private val layoutWidth = if(isSplitLayout) {
|
private val layoutWidth = if(isSplitLayout) {
|
||||||
layoutParams.splitLayoutWidth
|
(layoutParams.size as SplitKeyboardSize).splitLayoutWidth
|
||||||
|
} else if(isOneHandedLayout) {
|
||||||
|
(layoutParams.size as OneHandedKeyboardSize).layoutWidth
|
||||||
} else {
|
} else {
|
||||||
params.mId.mWidth
|
params.mId.mWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
private val unsplitLayoutWidth = params.mId.mWidth
|
private val unsplitLayoutWidth = if(isSplitLayout) {
|
||||||
|
params.mId.mWidth
|
||||||
|
} else {
|
||||||
|
layoutWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove
|
||||||
|
private val padding = Rect(0, 0, 0, 0)
|
||||||
|
private val xOffset = 0
|
||||||
|
|
||||||
private val minimumBottomFunctionalKeyWidth = (layoutWidth * keyboard.minimumBottomRowFunctionalKeyWidth)
|
private val minimumBottomFunctionalKeyWidth = (layoutWidth * keyboard.minimumBottomRowFunctionalKeyWidth)
|
||||||
|
|
||||||
private val regularKeyWidth = computeRegularKeyWidth()
|
private val regularKeyWidth = computeRegularKeyWidth()
|
||||||
@ -551,10 +557,10 @@ data class LayoutEngine(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addRowAlignLeft(row: List<LayoutEntry>, y: Int, height: Int)
|
private fun addRowAlignLeft(row: List<LayoutEntry>, y: Int, height: Int)
|
||||||
= addRow(row, 0.0f + layoutParams.padding.left, y, height)
|
= addRow(row, 0.0f + padding.left + xOffset, y, height)
|
||||||
|
|
||||||
private fun addRowAlignRight(row: List<LayoutEntry>, y: Int, height: Int) {
|
private fun addRowAlignRight(row: List<LayoutEntry>, y: Int, height: Int) {
|
||||||
val startingOffset = params.mId.mWidth - row.sumOf { it.widthPx.toDouble() }.toFloat() + layoutParams.padding.left
|
val startingOffset = params.mId.mWidth - row.sumOf { it.widthPx.toDouble() }.toFloat() + padding.left
|
||||||
addRow(row, startingOffset, y, height)
|
addRow(row, startingOffset, y, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,7 +576,7 @@ data class LayoutEngine(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addKeys(rows: List<LayoutRow>): Int {
|
private fun addKeys(rows: List<LayoutRow>): Int {
|
||||||
var currentY = 0.0f + layoutParams.padding.top
|
var currentY = 0.0f + padding.top
|
||||||
rows.forEach { row ->
|
rows.forEach { row ->
|
||||||
addRow(row, currentY.toInt())
|
addRow(row, currentY.toInt())
|
||||||
currentY += row.height
|
currentY += row.height
|
||||||
@ -588,14 +594,14 @@ data class LayoutEngine(
|
|||||||
|
|
||||||
val rows = computeRows(this.rows)
|
val rows = computeRows(this.rows)
|
||||||
|
|
||||||
val totalKeyboardHeight = addKeys(rows).let { totalRowHeight.roundToInt() } + layoutParams.padding.top + layoutParams.padding.bottom
|
val totalKeyboardHeight = addKeys(rows).let { totalRowHeight.roundToInt() } + padding.top + padding.bottom
|
||||||
|
|
||||||
params.mOccupiedHeight = totalKeyboardHeight - verticalGapPx.roundToInt()
|
params.mOccupiedHeight = totalKeyboardHeight - verticalGapPx.roundToInt()
|
||||||
params.mOccupiedWidth = params.mId.mWidth + layoutParams.padding.left + layoutParams.padding.right
|
params.mOccupiedWidth = params.mId.mWidth + padding.left + padding.right
|
||||||
params.mTopPadding = 0//layoutParams.padding.top
|
params.mTopPadding = 0
|
||||||
params.mBottomPadding = 0//layoutParams.padding.bottom
|
params.mBottomPadding = 0
|
||||||
params.mLeftPadding = 0//layoutParams.padding.left
|
params.mLeftPadding = 0
|
||||||
params.mRightPadding = 0//layoutParams.padding.right
|
params.mRightPadding = 0
|
||||||
|
|
||||||
params.mBaseWidth = params.mOccupiedWidth
|
params.mBaseWidth = params.mOccupiedWidth
|
||||||
params.mDefaultKeyWidth = regularKeyWidth.roundToInt()
|
params.mDefaultKeyWidth = regularKeyWidth.roundToInt()
|
||||||
|
@ -33,7 +33,7 @@ object LayoutManager {
|
|||||||
|
|
||||||
private fun getAllLayoutPaths(assetManager: AssetManager): List<String> {
|
private fun getAllLayoutPaths(assetManager: AssetManager): List<String> {
|
||||||
return listFilesRecursively(assetManager, "layouts").filter {
|
return listFilesRecursively(assetManager, "layouts").filter {
|
||||||
(it.endsWith(".yml") || it.endsWith(".yaml")) && it != "mapping.yaml"
|
(it.endsWith(".yml") || it.endsWith(".yaml")) && it != "layouts/mapping.yaml"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user