mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Compare commits
2 Commits
9f40bfd574
...
f795a7228e
Author | SHA1 | Date | |
---|---|---|---|
|
f795a7228e | ||
|
d692e7b96a |
@ -227,6 +227,7 @@ dependencies {
|
||||
|
||||
implementation 'androidx.datastore:datastore-preferences:1.1.1'
|
||||
implementation 'androidx.autofill:autofill:1.1.0'
|
||||
implementation 'androidx.window:window:1.3.0'
|
||||
|
||||
stableImplementation 'ch.acra:acra-mail:5.11.1'
|
||||
stableImplementation 'ch.acra:acra-dialog:5.11.1'
|
||||
|
11
common/src/org/futo/inputmethod/latin/FoldStateProvider.kt
Normal file
11
common/src/org/futo/inputmethod/latin/FoldStateProvider.kt
Normal file
@ -0,0 +1,11 @@
|
||||
package org.futo.inputmethod.latin
|
||||
|
||||
import androidx.window.layout.FoldingFeature
|
||||
|
||||
data class FoldingOptions(
|
||||
val feature: FoldingFeature?
|
||||
)
|
||||
|
||||
interface FoldStateProvider {
|
||||
val foldState: FoldingOptions
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
<resources>
|
||||
<!-- Preferable keyboard height in absolute scale: 58.0mm -->
|
||||
<!-- This config_default_keyboard_height value should match with keyboard-heights.xml -->
|
||||
<dimen name="config_default_keyboard_height">365.4dp</dimen>
|
||||
<dimen name="config_default_keyboard_height">302.4dp</dimen>
|
||||
<fraction name="config_min_keyboard_height">35%p</fraction>
|
||||
|
||||
<fraction name="config_keyboard_top_padding_holo">1.896%p</fraction>
|
@ -22,7 +22,7 @@
|
||||
<resources>
|
||||
<!-- Preferable keyboard height in absolute scale: 48.0mm -->
|
||||
<!-- This config_default_keyboard_height value should match with keyboard-heights.xml -->
|
||||
<dimen name="config_default_keyboard_height">302.4dp</dimen>
|
||||
<dimen name="config_default_keyboard_height">365.4dp</dimen>
|
||||
<fraction name="config_max_keyboard_height">46%p</fraction>
|
||||
<fraction name="config_min_keyboard_height">-35.0%p</fraction>
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.futo.inputmethod.keyboard;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import org.futo.inputmethod.keyboard.internal.KeyVisualAttributes;
|
||||
@ -64,8 +65,8 @@ public class Keyboard {
|
||||
/** Base width of the keyboard, used to calculate keys' width */
|
||||
public final int mBaseWidth;
|
||||
|
||||
/** The padding above the keyboard */
|
||||
public final int mTopPadding;
|
||||
/** left, right, top, bottom specify respective padding */
|
||||
public final Rect mPadding;
|
||||
/** Default gap between rows */
|
||||
public final int mVerticalGap;
|
||||
|
||||
@ -112,7 +113,7 @@ public class Keyboard {
|
||||
mMoreKeysTemplate = params.mMoreKeysTemplate;
|
||||
mMaxMoreKeysKeyboardColumn = params.mMaxMoreKeysKeyboardColumn;
|
||||
mKeyVisualAttributes = params.mKeyVisualAttributes;
|
||||
mTopPadding = params.mTopPadding;
|
||||
mPadding = new Rect(params.mLeftPadding, params.mTopPadding, params.mRightPadding, params.mBottomPadding);
|
||||
mVerticalGap = params.mVerticalGap;
|
||||
|
||||
mSortedKeys = Collections.unmodifiableList(new ArrayList<>(params.mSortedKeys));
|
||||
@ -140,7 +141,7 @@ public class Keyboard {
|
||||
mMoreKeysTemplate = keyboard.mMoreKeysTemplate;
|
||||
mMaxMoreKeysKeyboardColumn = keyboard.mMaxMoreKeysKeyboardColumn;
|
||||
mKeyVisualAttributes = keyboard.mKeyVisualAttributes;
|
||||
mTopPadding = keyboard.mTopPadding;
|
||||
mPadding = keyboard.mPadding;
|
||||
mVerticalGap = keyboard.mVerticalGap;
|
||||
|
||||
mSortedKeys = keyboard.mSortedKeys;
|
||||
@ -178,7 +179,6 @@ public class Keyboard {
|
||||
/**
|
||||
* Return the sorted list of keys of this keyboard.
|
||||
* The keys are sorted from top-left to bottom-right order.
|
||||
* The list may contain {@link Key.Spacer} object as well.
|
||||
* @return the sorted unmodifiable list of {@link Key}s of this keyboard.
|
||||
*/
|
||||
@Nonnull
|
||||
|
@ -17,12 +17,13 @@
|
||||
package org.futo.inputmethod.keyboard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.util.Log;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@ -46,8 +47,13 @@ import org.futo.inputmethod.latin.settings.SettingsValues;
|
||||
import org.futo.inputmethod.latin.utils.LanguageOnSpacebarUtils;
|
||||
import org.futo.inputmethod.latin.utils.ResourceUtils;
|
||||
import org.futo.inputmethod.latin.utils.ScriptUtils;
|
||||
import org.futo.inputmethod.v2keyboard.ComputedKeyboardSize;
|
||||
import org.futo.inputmethod.v2keyboard.KeyboardLayoutSetKt;
|
||||
import org.futo.inputmethod.v2keyboard.KeyboardLayoutSetV2;
|
||||
import org.futo.inputmethod.v2keyboard.KeyboardLayoutSetV2Params;
|
||||
import org.futo.inputmethod.v2keyboard.KeyboardSizingCalculator;
|
||||
import org.futo.inputmethod.v2keyboard.RegularKeyboardSize;
|
||||
import org.futo.inputmethod.v2keyboard.SplitKeyboardSize;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -124,18 +130,50 @@ public final class KeyboardSwitcher implements SwitchActions {
|
||||
final int currentAutoCapsState, final int currentRecapitalizeState) {
|
||||
|
||||
final Resources res = mThemeContext.getResources();
|
||||
final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
|
||||
|
||||
final RichInputMethodSubtype subtype = mRichImm.getCurrentSubtype();
|
||||
|
||||
String layoutSetName = subtype.getKeyboardLayoutSetName();
|
||||
String overrideLayoutSet = KeyboardLayoutSetKt.getPrimaryLayoutOverride(editorInfo);
|
||||
if(overrideLayoutSet != null) {
|
||||
layoutSetName = overrideLayoutSet;
|
||||
}
|
||||
|
||||
|
||||
final KeyboardSizingCalculator sizingCalculator = new KeyboardSizingCalculator(mLatinIMELegacy.getInputMethodService());
|
||||
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(
|
||||
keyboardWidth,
|
||||
null, // Auto keyboard height
|
||||
subtype.getKeyboardLayoutSetName(),
|
||||
keyboardHeight,
|
||||
padding,
|
||||
layoutSetName,
|
||||
subtype.getLocale(),
|
||||
editorInfo == null ? new EditorInfo() : editorInfo,
|
||||
settingsValues.mIsNumberRowEnabled,
|
||||
4.0f,
|
||||
res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE,
|
||||
sizingCalculator.calculateGap(),
|
||||
splitLayoutWidth != 0,
|
||||
splitLayoutWidth,
|
||||
settingsValues.mShowsActionKey ? settingsValues.mActionKeyId : null,
|
||||
LongPressKeySettings.load(mThemeContext)
|
||||
);
|
||||
@ -176,7 +214,6 @@ public final class KeyboardSwitcher implements SwitchActions {
|
||||
final Keyboard oldKeyboard = keyboardView.getKeyboard();
|
||||
final Keyboard newKeyboard = mKeyboardLayoutSet.getKeyboard(element);
|
||||
keyboardView.setKeyboard(newKeyboard);
|
||||
mCurrentInputView.setKeyboardTopPadding(newKeyboard.mTopPadding);
|
||||
keyboardView.setKeyPreviewPopupEnabled(
|
||||
currentSettingsValues.mKeyPreviewPopupOn,
|
||||
currentSettingsValues.mKeyPreviewPopupDismissDelay);
|
||||
|
@ -401,6 +401,8 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
|
||||
} else {
|
||||
mAccessibilityDelegate = null;
|
||||
}
|
||||
|
||||
setPadding(keyboard.mPadding.left, keyboard.mPadding.top, keyboard.mPadding.right, keyboard.mPadding.bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,10 +41,6 @@ public final class InputView extends FrameLayout {
|
||||
mMainKeyboardView = (MainKeyboardView) findViewById(R.id.keyboard_view);
|
||||
}
|
||||
|
||||
public void setKeyboardTopPadding(final int keyboardTopPadding) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean dispatchHoverEvent(final MotionEvent event) {
|
||||
if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()
|
||||
|
@ -19,10 +19,8 @@ import android.view.inputmethod.InlineSuggestionsResponse
|
||||
import android.view.inputmethod.InputConnection
|
||||
import android.view.inputmethod.InputMethodSubtype
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
@ -58,7 +56,6 @@ import org.futo.inputmethod.latin.uix.DynamicThemeProvider
|
||||
import org.futo.inputmethod.latin.uix.DynamicThemeProviderOwner
|
||||
import org.futo.inputmethod.latin.uix.EmojiTracker.unuseEmoji
|
||||
import org.futo.inputmethod.latin.uix.EmojiTracker.useEmoji
|
||||
import org.futo.inputmethod.latin.uix.KeyboardBottomOffsetSetting
|
||||
import org.futo.inputmethod.latin.uix.KeyboardColorScheme
|
||||
import org.futo.inputmethod.latin.uix.SUGGESTION_BLACKLIST
|
||||
import org.futo.inputmethod.latin.uix.THEME_KEY
|
||||
@ -70,7 +67,6 @@ import org.futo.inputmethod.latin.uix.deferSetSetting
|
||||
import org.futo.inputmethod.latin.uix.differsFrom
|
||||
import org.futo.inputmethod.latin.uix.getSetting
|
||||
import org.futo.inputmethod.latin.uix.getSettingBlocking
|
||||
import org.futo.inputmethod.latin.uix.getSettingFlow
|
||||
import org.futo.inputmethod.latin.uix.isDirectBootUnlocked
|
||||
import org.futo.inputmethod.latin.uix.setSetting
|
||||
import org.futo.inputmethod.latin.uix.theme.ThemeOption
|
||||
@ -79,6 +75,8 @@ import org.futo.inputmethod.latin.uix.theme.applyWindowColors
|
||||
import org.futo.inputmethod.latin.uix.theme.presets.VoiceInputTheme
|
||||
import org.futo.inputmethod.latin.xlm.LanguageModelFacilitator
|
||||
import org.futo.inputmethod.updates.scheduleUpdateCheckingJob
|
||||
import org.futo.inputmethod.v2keyboard.KeyboardSizeSettingKind
|
||||
import org.futo.inputmethod.v2keyboard.KeyboardSizeStateProvider
|
||||
|
||||
private class UnlockedBroadcastReceiver(val onDeviceUnlocked: () -> Unit) : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
@ -90,7 +88,8 @@ private class UnlockedBroadcastReceiver(val onDeviceUnlocked: () -> Unit) : Broa
|
||||
}
|
||||
|
||||
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner,
|
||||
LatinIMELegacy.SuggestionStripController, DynamicThemeProviderOwner {
|
||||
LatinIMELegacy.SuggestionStripController, DynamicThemeProviderOwner, FoldStateProvider,
|
||||
KeyboardSizeStateProvider {
|
||||
|
||||
private lateinit var mLifecycleRegistry: LifecycleRegistry
|
||||
private lateinit var mViewModelStore: ViewModelStore
|
||||
@ -205,7 +204,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
}
|
||||
}
|
||||
|
||||
private fun invalidateKeyboard(refreshSettings: Boolean = false) {
|
||||
fun invalidateKeyboard(refreshSettings: Boolean = false) {
|
||||
settingsRefreshRequired = settingsRefreshRequired || refreshSettings
|
||||
|
||||
if(!uixManager.isMainKeyboardHidden) {
|
||||
@ -427,12 +426,12 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
}
|
||||
}
|
||||
|
||||
val padding = getSettingFlow(KeyboardBottomOffsetSetting).collectAsState(initial = 0.0f)
|
||||
|
||||
|
||||
key(legacyInputView) {
|
||||
AndroidView(factory = {
|
||||
legacyInputView!!
|
||||
}, modifier = modifier.padding(0.dp, 0.dp, 0.dp, padding.value.dp), onRelease = {
|
||||
}, modifier = modifier, onRelease = {
|
||||
val view = it as InputView
|
||||
view.deallocateMemory()
|
||||
view.removeAllViews()
|
||||
@ -762,4 +761,19 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
|
||||
// TODO: Spell checker service
|
||||
}
|
||||
|
||||
override val foldState: FoldingOptions
|
||||
get() = uixManager.foldingOptions.value
|
||||
|
||||
override val currentSizeState: KeyboardSizeSettingKind
|
||||
get() = when {
|
||||
foldState.feature != null ->
|
||||
KeyboardSizeSettingKind.FoldableInnerDisplay
|
||||
|
||||
resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE ->
|
||||
KeyboardSizeSettingKind.Landscape
|
||||
|
||||
else ->
|
||||
KeyboardSizeSettingKind.Portrait
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package org.futo.inputmethod.latin.uix
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Rect
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@ -109,12 +109,14 @@ fun KeyboardLayoutPreview(id: String, width: Dp = 172.dp, locale: Locale? = null
|
||||
KeyboardLayoutSetV2Params(
|
||||
width = widthPx,
|
||||
height = heightPx,
|
||||
padding = Rect(),
|
||||
gap = 4.0f,
|
||||
keyboardLayoutSet = id,
|
||||
locale = loc ?: Locale.ENGLISH,
|
||||
editorInfo = editorInfo,
|
||||
numberRow = numberRow,
|
||||
useSplitLayout = isLandscape,
|
||||
splitLayoutWidth = widthPx * 2 / 3,
|
||||
bottomActionKey = null
|
||||
)
|
||||
)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.futo.inputmethod.latin.uix
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.KeyguardManager
|
||||
import android.content.ClipDescription
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@ -62,11 +61,15 @@ import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import androidx.window.layout.WindowInfoTracker
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.futo.inputmethod.accessibility.AccessibilityUtils
|
||||
import org.futo.inputmethod.latin.AudioAndHapticFeedbackManager
|
||||
import org.futo.inputmethod.latin.BuildConfig
|
||||
import org.futo.inputmethod.latin.FoldingOptions
|
||||
import org.futo.inputmethod.latin.LanguageSwitcherDialog
|
||||
import org.futo.inputmethod.latin.LatinIME
|
||||
import org.futo.inputmethod.latin.R
|
||||
@ -103,6 +106,12 @@ val LocalThemeProvider = compositionLocalOf<DynamicThemeProvider> {
|
||||
error("No LocalThemeProvider provided")
|
||||
}
|
||||
|
||||
val LocalFoldingState = compositionLocalOf<FoldingOptions> {
|
||||
FoldingOptions(null)
|
||||
}
|
||||
|
||||
|
||||
|
||||
private class LatinIMEActionInputTransaction(
|
||||
private val inputLogic: InputLogic,
|
||||
shouldApplySpace: Boolean,
|
||||
@ -323,6 +332,8 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
isShowingActionEditor.value = true
|
||||
}
|
||||
|
||||
val foldingOptions = mutableStateOf(FoldingOptions(null))
|
||||
|
||||
var isInputOverridden = mutableStateOf(false)
|
||||
|
||||
var currWindowActionWindow: ActionWindow? = null
|
||||
@ -622,6 +633,7 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
CompositionLocalProvider(LocalManager provides keyboardManagerForAction) {
|
||||
CompositionLocalProvider(LocalThemeProvider provides latinIME.getDrawableProvider()) {
|
||||
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
|
||||
CompositionLocalProvider(LocalFoldingState provides foldingOptions.value) {
|
||||
InputDarkener(isInputOverridden.value || isShowingActionEditor.value) {
|
||||
closeActionWindow()
|
||||
isShowingActionEditor.value = false
|
||||
@ -647,7 +659,9 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
|
||||
ForgetWordDialog()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ActionEditorHost()
|
||||
@ -658,6 +672,7 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun showUpdateNoticeIfNeeded() {
|
||||
if(!BuildConfig.UPDATE_CHECKING) return
|
||||
@ -852,6 +867,13 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
}
|
||||
|
||||
isActionsExpanded.value = latinIME.getSettingBlocking(ActionBarExpanded)
|
||||
|
||||
latinIME.lifecycleScope.launch(Dispatchers.Main) {
|
||||
WindowInfoTracker.getOrCreate(latinIME).windowLayoutInfo(latinIME).collect {
|
||||
foldingOptions.value = FoldingOptions(it.displayFeatures.filterIsInstance<FoldingFeature>().firstOrNull())
|
||||
latinIME.invalidateKeyboard(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onPersistentStatesUnlocked() {
|
||||
|
@ -22,10 +22,11 @@ import kotlinx.coroutines.delay
|
||||
import org.futo.inputmethod.latin.R
|
||||
import org.futo.inputmethod.latin.uix.Action
|
||||
import org.futo.inputmethod.latin.uix.ActionWindow
|
||||
import org.futo.inputmethod.latin.uix.settings.ScreenTitle
|
||||
import org.futo.inputmethod.latin.uix.LocalFoldingState
|
||||
import org.futo.inputmethod.latin.uix.settings.ScrollableList
|
||||
import org.futo.inputmethod.latin.uix.theme.ThemeOptions
|
||||
import org.futo.inputmethod.latin.uix.theme.Typography
|
||||
import org.futo.inputmethod.v2keyboard.KeyboardSizeStateProvider
|
||||
|
||||
val DebugLabel = Typography.labelSmall.copy(fontFamily = FontFamily.Monospace)
|
||||
val DebugTitle = Typography.titleSmall.copy(fontFamily = FontFamily.Monospace, fontWeight = FontWeight.Bold)
|
||||
@ -190,6 +191,8 @@ val MemoryDebugAction = Action(
|
||||
}
|
||||
}
|
||||
|
||||
val foldingState = LocalFoldingState.current
|
||||
|
||||
ScrollableList {
|
||||
Text("Editor Info", style = DebugTitle)
|
||||
latinIme.currentInputEditorInfo?.let { info ->
|
||||
@ -228,6 +231,16 @@ val MemoryDebugAction = Action(
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Text("Screen State Info", style = DebugTitle)
|
||||
Text("size mode = ${(manager.getContext() as KeyboardSizeStateProvider).currentSizeState}", style = DebugLabel)
|
||||
Text("Fold State", style = DebugTitle)
|
||||
Text("state = ${foldingState.feature?.state}", style = DebugLabel)
|
||||
Text("orientation = ${foldingState.feature?.orientation}", style = DebugLabel)
|
||||
Text("isSeparating = ${foldingState.feature?.isSeparating}", style = DebugLabel)
|
||||
Text("occlusionType = ${foldingState.feature?.occlusionType}", style = DebugLabel)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Text("Memory Use", style = DebugTitle)
|
||||
state.value.forEach {
|
||||
val value = it.value.toInt().toFloat() / 1000.0f
|
||||
|
@ -18,11 +18,15 @@ package org.futo.inputmethod.latin.utils;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Insets;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Window;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowMetrics;
|
||||
|
||||
import org.futo.inputmethod.annotations.UsedForTesting;
|
||||
import org.futo.inputmethod.latin.R;
|
||||
@ -182,9 +186,14 @@ public final class ResourceUtils {
|
||||
return matchedAll;
|
||||
}
|
||||
|
||||
public static int getDefaultKeyboardWidth(final Resources res) {
|
||||
final DisplayMetrics dm = res.getDisplayMetrics();
|
||||
return dm.widthPixels;
|
||||
public static int getDefaultKeyboardWidth(final Window window, final Resources res) {
|
||||
if(window != null && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)) {
|
||||
WindowMetrics metrics = window.getWindowManager().getCurrentWindowMetrics();
|
||||
Insets insets = metrics.getWindowInsets().getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars() | WindowInsets.Type.displayCutout());
|
||||
|
||||
return metrics.getBounds().width() - (insets.left + insets.right);
|
||||
}
|
||||
return (int)(res.getConfiguration().screenWidthDp * res.getDisplayMetrics().density);
|
||||
}
|
||||
|
||||
public static int getKeyboardHeight(final Resources res, final SettingsValues settingsValues) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.futo.inputmethod.v2keyboard
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.text.InputType
|
||||
import android.util.Log
|
||||
import android.view.inputmethod.EditorInfo
|
||||
@ -20,7 +21,6 @@ import org.futo.inputmethod.latin.uix.getSettingBlocking
|
||||
import org.futo.inputmethod.latin.utils.InputTypeUtils
|
||||
import org.futo.inputmethod.latin.utils.ResourceUtils
|
||||
import java.util.Locale
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Serializable
|
||||
enum class Script(val id: Int, val iso4letterCode: String) {
|
||||
@ -71,24 +71,25 @@ private fun EditorInfo.getPrivateImeOptions(): Map<String, String> {
|
||||
return options
|
||||
}
|
||||
|
||||
private fun EditorInfo.getPrimaryLayoutOverride(): String? =
|
||||
getPrivateImeOptions()["org.futo.inputmethod.latin.ForceLayout"]
|
||||
|
||||
fun getPrimaryLayoutOverride(editorInfo: EditorInfo?): String? {
|
||||
return editorInfo?.getPrivateImeOptions()?.get("org.futo.inputmethod.latin.ForceLayout")
|
||||
}
|
||||
|
||||
data class KeyboardLayoutSetV2Params(
|
||||
val width: Int,
|
||||
val height: Int?,
|
||||
val height: Int,
|
||||
val padding: Rect,
|
||||
val keyboardLayoutSet: String,
|
||||
val locale: Locale,
|
||||
val editorInfo: EditorInfo?,
|
||||
val numberRow: Boolean,
|
||||
val gap: Float = 4.0f,
|
||||
val useSplitLayout: Boolean,
|
||||
val splitLayoutWidth: Int,
|
||||
val bottomActionKey: Int?,
|
||||
val longPressKeySettings: LongPressKeySettings? = null
|
||||
)
|
||||
|
||||
|
||||
class KeyboardLayoutSetV2 internal constructor(
|
||||
private val context: Context,
|
||||
private val params: KeyboardLayoutSetV2Params
|
||||
@ -183,31 +184,22 @@ class KeyboardLayoutSetV2 internal constructor(
|
||||
NumberRowMode.AlwaysDisabled -> false
|
||||
}
|
||||
|
||||
private val widthMinusPadding = params.width - params.padding.left - params.padding.right
|
||||
private val heightMinusPadding = params.height - params.padding.top - params.padding.bottom
|
||||
|
||||
private val singularRowHeight: Double
|
||||
get() = params.height?.let { it / 4.0 } ?: run {
|
||||
get() = heightMinusPadding?.let { it / 4.0 } ?: run {
|
||||
(ResourceUtils.getDefaultKeyboardHeight(context.resources) / 4.0) *
|
||||
keyboardHeightMultiplier
|
||||
}
|
||||
|
||||
private fun getRecommendedKeyboardHeight(): Int {
|
||||
val numRows = 4.0 +
|
||||
((mainLayout.effectiveRows.size - 5) / 2.0).coerceAtLeast(0.0) +
|
||||
if(isNumberRowActive) { 0.5 } else { 0.0 }
|
||||
|
||||
// Clamp if necessary (disabled for now)
|
||||
if(false && params.height == null) {
|
||||
return ResourceUtils.clampKeyboardHeight(context.resources, (singularRowHeight * numRows).roundToInt())
|
||||
} else {
|
||||
return (singularRowHeight * numRows).roundToInt()
|
||||
}
|
||||
}
|
||||
|
||||
fun getKeyboard(element: KeyboardLayoutElement): Keyboard {
|
||||
|
||||
val keyboardId = KeyboardId(
|
||||
params.keyboardLayoutSet,
|
||||
forcedLocale ?: params.locale,
|
||||
params.width,
|
||||
params.height ?: getRecommendedKeyboardHeight(),
|
||||
widthMinusPadding,
|
||||
heightMinusPadding,
|
||||
keyboardMode,
|
||||
element.elementId,
|
||||
editorInfo,
|
||||
@ -231,6 +223,8 @@ class KeyboardLayoutSetV2 internal constructor(
|
||||
val layoutParams = LayoutParams(
|
||||
gap = params.gap.dp,
|
||||
useSplitLayout = params.useSplitLayout,
|
||||
splitLayoutWidth = params.splitLayoutWidth,
|
||||
padding = params.padding,
|
||||
standardRowHeight = singularRowHeight,
|
||||
element = element
|
||||
)
|
||||
|
@ -0,0 +1,158 @@
|
||||
package org.futo.inputmethod.v2keyboard
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.floatPreferencesKey
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import org.futo.inputmethod.latin.FoldStateProvider
|
||||
import org.futo.inputmethod.latin.uix.SettingsKey
|
||||
import org.futo.inputmethod.latin.uix.getSettingBlocking
|
||||
import org.futo.inputmethod.latin.utils.ResourceUtils
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
interface KeyboardSizeStateProvider {
|
||||
val currentSizeState: KeyboardSizeSettingKind
|
||||
}
|
||||
|
||||
sealed class ComputedKeyboardSize()
|
||||
|
||||
class RegularKeyboardSize(val height: Int, val padding: Rect) : ComputedKeyboardSize()
|
||||
|
||||
class SplitKeyboardSize(val height: 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()
|
||||
//class FloatingKeyboardSize(val x: Int, val y: Int, val width: Int, val height: Int): ComputedKeyboardSize()
|
||||
|
||||
|
||||
enum class KeyboardSizeSettingKind {
|
||||
Portrait,
|
||||
Landscape,
|
||||
FoldableInnerDisplay
|
||||
}
|
||||
|
||||
val SplitKeyboardSettings = mapOf(
|
||||
KeyboardSizeSettingKind.Portrait to SettingsKey(
|
||||
booleanPreferencesKey("split_keyboard_portrait"), false),
|
||||
KeyboardSizeSettingKind.Landscape to SettingsKey(
|
||||
booleanPreferencesKey("split_keyboard_landscape"), true),
|
||||
KeyboardSizeSettingKind.FoldableInnerDisplay to SettingsKey(
|
||||
booleanPreferencesKey("split_keyboard_fold"), true),
|
||||
)
|
||||
|
||||
val KeyboardHeightSettings = mapOf(
|
||||
KeyboardSizeSettingKind.Portrait to SettingsKey(
|
||||
floatPreferencesKey("keyboardHeightMultiplier"), 1.0f),
|
||||
KeyboardSizeSettingKind.Landscape to SettingsKey(
|
||||
floatPreferencesKey("keyboard_height_landscape"), 0.9f),
|
||||
KeyboardSizeSettingKind.FoldableInnerDisplay to SettingsKey(
|
||||
floatPreferencesKey("keyboard_height_fold"), 0.67f),
|
||||
)
|
||||
|
||||
val KeyboardOffsetSettings = mapOf(
|
||||
KeyboardSizeSettingKind.Portrait to SettingsKey(
|
||||
floatPreferencesKey("keyboard_offset_portrait"), 8.0f),
|
||||
KeyboardSizeSettingKind.Landscape to SettingsKey(
|
||||
floatPreferencesKey("keyboard_offset_landscape"), 0.0f),
|
||||
KeyboardSizeSettingKind.FoldableInnerDisplay to SettingsKey(
|
||||
floatPreferencesKey("keyboard_offset_fold"), 8.0f),
|
||||
)
|
||||
|
||||
val KeyboardSideInsetSettings = mapOf(
|
||||
KeyboardSizeSettingKind.Portrait to SettingsKey(
|
||||
floatPreferencesKey("keyboard_inset_portrait"), 2.0f),
|
||||
KeyboardSizeSettingKind.Landscape to SettingsKey(
|
||||
floatPreferencesKey("keyboard_inset_landscape"), 8.0f),
|
||||
KeyboardSizeSettingKind.FoldableInnerDisplay to SettingsKey(
|
||||
floatPreferencesKey("keyboard_inset_fold"), 44.0f),
|
||||
)
|
||||
|
||||
|
||||
class KeyboardSizingCalculator(val context: Context) {
|
||||
private val sizeStateProvider = context as KeyboardSizeStateProvider
|
||||
private val foldStateProvider = context as FoldStateProvider
|
||||
|
||||
private fun isSplitKeyboard(mode: KeyboardSizeSettingKind): Boolean =
|
||||
context.getSettingBlocking(SplitKeyboardSettings[mode]!!)
|
||||
|
||||
private fun heightMultiplier(mode: KeyboardSizeSettingKind): Float =
|
||||
context.getSettingBlocking(KeyboardHeightSettings[mode]!!)
|
||||
|
||||
private fun bottomOffsetPx(mode: KeyboardSizeSettingKind): Int =
|
||||
(context.getSettingBlocking(KeyboardOffsetSettings[mode]!!) * context.resources.displayMetrics.density).toInt()
|
||||
|
||||
private fun sideInsetPx(mode: KeyboardSizeSettingKind): Int =
|
||||
(context.getSettingBlocking(KeyboardSideInsetSettings[mode]!!) * context.resources.displayMetrics.density).toInt()
|
||||
|
||||
private fun topPaddingPx(mode: KeyboardSizeSettingKind): Int =
|
||||
(when(mode) {
|
||||
KeyboardSizeSettingKind.Portrait -> 4.0f
|
||||
KeyboardSizeSettingKind.Landscape -> 0.0f
|
||||
KeyboardSizeSettingKind.FoldableInnerDisplay -> 8.0f
|
||||
} * context.resources.displayMetrics.density).toInt()
|
||||
|
||||
fun calculate(layoutName: String, isNumberRowActive: Boolean): ComputedKeyboardSize {
|
||||
val layout = LayoutManager.getLayout(context, layoutName)
|
||||
val effectiveRowCount = layout.effectiveRows.size
|
||||
|
||||
val configuration = context.resources.configuration
|
||||
val displayMetrics = context.resources.displayMetrics
|
||||
|
||||
val mode = sizeStateProvider.currentSizeState
|
||||
|
||||
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 +
|
||||
((effectiveRowCount - 5) / 2.0).coerceAtLeast(0.0) +
|
||||
if(isNumberRowActive) { 0.5 } else { 0.0 }
|
||||
|
||||
println("Num rows; $numRows, $effectiveRowCount ($layoutName) ($layout)")
|
||||
|
||||
val recommendedHeight = numRows * singularRowHeight
|
||||
|
||||
|
||||
val foldState = foldStateProvider.foldState.feature
|
||||
|
||||
return when {
|
||||
// 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 ->
|
||||
SplitKeyboardSize(
|
||||
displayMetrics.heightPixels / 2 - (displayMetrics.density * 80.0f).toInt(),
|
||||
Rect(
|
||||
(displayMetrics.density * 44.0f).roundToInt(),
|
||||
(displayMetrics.density * 20.0f).roundToInt(),
|
||||
(displayMetrics.density * 44.0f).roundToInt(),
|
||||
(displayMetrics.density * 12.0f).roundToInt(),
|
||||
),
|
||||
displayMetrics.widthPixels * 3 / 5
|
||||
)
|
||||
|
||||
isSplit -> SplitKeyboardSize(
|
||||
recommendedHeight.roundToInt(),
|
||||
Rect(sideInset, topPadding, sideInset, bottomOffset),
|
||||
displayMetrics.widthPixels * 3 / 5)
|
||||
|
||||
else -> RegularKeyboardSize(
|
||||
recommendedHeight.roundToInt(),
|
||||
Rect(sideInset, topPadding, sideInset, bottomOffset),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun calculateGap(): Float {
|
||||
val displayMetrics = context.resources.displayMetrics
|
||||
|
||||
val widthDp = displayMetrics.widthPixels / displayMetrics.density
|
||||
val heightDp = displayMetrics.heightPixels / displayMetrics.density
|
||||
|
||||
val minDp = Math.min(widthDp, heightDp)
|
||||
|
||||
return (minDp / 100.0f).coerceIn(3.0f, 6.0f)
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package org.futo.inputmethod.v2keyboard
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import org.futo.inputmethod.keyboard.KeyConsts
|
||||
import org.futo.inputmethod.keyboard.internal.KeyboardLayoutElement
|
||||
@ -82,6 +83,8 @@ data class LayoutRow(
|
||||
data class LayoutParams(
|
||||
val gap: Dp,
|
||||
val useSplitLayout: Boolean,
|
||||
val splitLayoutWidth: Int,
|
||||
val padding: Rect,
|
||||
val standardRowHeight: Double,
|
||||
val element: KeyboardLayoutElement,
|
||||
)
|
||||
@ -144,7 +147,7 @@ data class LayoutEngine(
|
||||
private val isSplitLayout = layoutParams.useSplitLayout
|
||||
|
||||
private val layoutWidth = if(isSplitLayout) {
|
||||
params.mId.mWidth * 2 / 3
|
||||
layoutParams.splitLayoutWidth
|
||||
} else {
|
||||
params.mId.mWidth
|
||||
}
|
||||
@ -526,10 +529,10 @@ data class LayoutEngine(
|
||||
}
|
||||
|
||||
private fun addRowAlignLeft(row: List<LayoutEntry>, y: Int, height: Int)
|
||||
= addRow(row, 0.0f, y, height)
|
||||
= addRow(row, 0.0f + layoutParams.padding.left, y, height)
|
||||
|
||||
private fun addRowAlignRight(row: List<LayoutEntry>, y: Int, height: Int) {
|
||||
val startingOffset = params.mId.mWidth - row.sumOf { it.widthPx.toDouble() }.toFloat()
|
||||
val startingOffset = params.mId.mWidth - row.sumOf { it.widthPx.toDouble() }.toFloat() + layoutParams.padding.left
|
||||
addRow(row, startingOffset, y, height)
|
||||
}
|
||||
|
||||
@ -545,7 +548,7 @@ data class LayoutEngine(
|
||||
}
|
||||
|
||||
private fun addKeys(rows: List<LayoutRow>): Int {
|
||||
var currentY = 0.0f
|
||||
var currentY = 0.0f + layoutParams.padding.top
|
||||
rows.forEach { row ->
|
||||
addRow(row, currentY.toInt())
|
||||
currentY += row.height
|
||||
@ -563,14 +566,14 @@ data class LayoutEngine(
|
||||
|
||||
val rows = computeRows(this.rows)
|
||||
|
||||
val totalKeyboardHeight = addKeys(rows).let { totalRowHeight.roundToInt() }
|
||||
val totalKeyboardHeight = addKeys(rows).let { totalRowHeight.roundToInt() } + layoutParams.padding.top + layoutParams.padding.bottom
|
||||
|
||||
params.mOccupiedHeight = totalKeyboardHeight - verticalGapPx.roundToInt()
|
||||
params.mOccupiedWidth = params.mId.mWidth
|
||||
params.mTopPadding = 0
|
||||
params.mBottomPadding = 0
|
||||
params.mLeftPadding = 0
|
||||
params.mRightPadding = 0
|
||||
params.mOccupiedWidth = params.mId.mWidth + layoutParams.padding.left + layoutParams.padding.right
|
||||
params.mTopPadding = 0//layoutParams.padding.top
|
||||
params.mBottomPadding = 0//layoutParams.padding.bottom
|
||||
params.mLeftPadding = 0//layoutParams.padding.left
|
||||
params.mRightPadding = 0//layoutParams.padding.right
|
||||
|
||||
params.mBaseWidth = params.mOccupiedWidth
|
||||
params.mDefaultKeyWidth = regularKeyWidth.roundToInt()
|
||||
|
@ -18,6 +18,7 @@ package org.futo.inputmethod.keyboard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
@ -142,7 +143,7 @@ public abstract class KeyboardLayoutSetTestsBase extends AndroidTestCase {
|
||||
final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) {
|
||||
final Context context = getContext();
|
||||
final Resources res = context.getResources();
|
||||
final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
|
||||
final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(null, res);
|
||||
final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res);
|
||||
|
||||
final RichInputMethodSubtype richInputMethodSubtype = RichInputMethodSubtype.getRichInputMethodSubtype(subtype);
|
||||
@ -150,11 +151,11 @@ public abstract class KeyboardLayoutSetTestsBase extends AndroidTestCase {
|
||||
return new KeyboardLayoutSetV2(
|
||||
context,
|
||||
new KeyboardLayoutSetV2Params(
|
||||
keyboardWidth, keyboardHeight,
|
||||
keyboardWidth, keyboardHeight, new Rect(),
|
||||
richInputMethodSubtype.getKeyboardLayoutSetName(),
|
||||
richInputMethodSubtype.getLocale(),
|
||||
editorInfo, false,
|
||||
4.0f, splitLayoutEnabled,
|
||||
4.0f, splitLayoutEnabled, 0,
|
||||
languageSwitchKeyEnabled ? ActionRegistry.INSTANCE.actionStringIdToIdx("switch_language") : null,
|
||||
LongPressKeySettings.forTest()
|
||||
)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.futo.inputmethod.keyboard.internal
|
||||
|
||||
import android.graphics.Rect
|
||||
import android.test.AndroidTestCase
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.datastore.preferences.core.edit
|
||||
@ -14,12 +15,14 @@ import kotlin.math.absoluteValue
|
||||
class KeyboardLayoutSetV2Tests : AndroidTestCase() {
|
||||
private val layoutParams = KeyboardLayoutSetV2Params(
|
||||
width = 1024,
|
||||
height = null,
|
||||
height = 1024,
|
||||
padding = Rect(),
|
||||
keyboardLayoutSet = "qwerty",
|
||||
locale = Locale.ENGLISH,
|
||||
editorInfo = EditorInfo(),
|
||||
numberRow = false,
|
||||
useSplitLayout = false,
|
||||
splitLayoutWidth = 0,
|
||||
bottomActionKey = null
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user