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.datastore:datastore-preferences:1.1.1'
|
||||||
implementation 'androidx.autofill:autofill:1.1.0'
|
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-mail:5.11.1'
|
||||||
stableImplementation 'ch.acra:acra-dialog: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>
|
<resources>
|
||||||
<!-- Preferable keyboard height in absolute scale: 58.0mm -->
|
<!-- Preferable keyboard height in absolute scale: 58.0mm -->
|
||||||
<!-- This config_default_keyboard_height value should match with keyboard-heights.xml -->
|
<!-- 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_min_keyboard_height">35%p</fraction>
|
||||||
|
|
||||||
<fraction name="config_keyboard_top_padding_holo">1.896%p</fraction>
|
<fraction name="config_keyboard_top_padding_holo">1.896%p</fraction>
|
@ -22,7 +22,7 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<!-- Preferable keyboard height in absolute scale: 48.0mm -->
|
<!-- Preferable keyboard height in absolute scale: 48.0mm -->
|
||||||
<!-- This config_default_keyboard_height value should match with keyboard-heights.xml -->
|
<!-- 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_max_keyboard_height">46%p</fraction>
|
||||||
<fraction name="config_min_keyboard_height">-35.0%p</fraction>
|
<fraction name="config_min_keyboard_height">-35.0%p</fraction>
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.futo.inputmethod.keyboard;
|
package org.futo.inputmethod.keyboard;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import org.futo.inputmethod.keyboard.internal.KeyVisualAttributes;
|
import org.futo.inputmethod.keyboard.internal.KeyVisualAttributes;
|
||||||
@ -64,8 +65,8 @@ public class Keyboard {
|
|||||||
/** Base width of the keyboard, used to calculate keys' width */
|
/** Base width of the keyboard, used to calculate keys' width */
|
||||||
public final int mBaseWidth;
|
public final int mBaseWidth;
|
||||||
|
|
||||||
/** The padding above the keyboard */
|
/** left, right, top, bottom specify respective padding */
|
||||||
public final int mTopPadding;
|
public final Rect mPadding;
|
||||||
/** Default gap between rows */
|
/** Default gap between rows */
|
||||||
public final int mVerticalGap;
|
public final int mVerticalGap;
|
||||||
|
|
||||||
@ -112,7 +113,7 @@ public class Keyboard {
|
|||||||
mMoreKeysTemplate = params.mMoreKeysTemplate;
|
mMoreKeysTemplate = params.mMoreKeysTemplate;
|
||||||
mMaxMoreKeysKeyboardColumn = params.mMaxMoreKeysKeyboardColumn;
|
mMaxMoreKeysKeyboardColumn = params.mMaxMoreKeysKeyboardColumn;
|
||||||
mKeyVisualAttributes = params.mKeyVisualAttributes;
|
mKeyVisualAttributes = params.mKeyVisualAttributes;
|
||||||
mTopPadding = params.mTopPadding;
|
mPadding = new Rect(params.mLeftPadding, params.mTopPadding, params.mRightPadding, params.mBottomPadding);
|
||||||
mVerticalGap = params.mVerticalGap;
|
mVerticalGap = params.mVerticalGap;
|
||||||
|
|
||||||
mSortedKeys = Collections.unmodifiableList(new ArrayList<>(params.mSortedKeys));
|
mSortedKeys = Collections.unmodifiableList(new ArrayList<>(params.mSortedKeys));
|
||||||
@ -140,7 +141,7 @@ public class Keyboard {
|
|||||||
mMoreKeysTemplate = keyboard.mMoreKeysTemplate;
|
mMoreKeysTemplate = keyboard.mMoreKeysTemplate;
|
||||||
mMaxMoreKeysKeyboardColumn = keyboard.mMaxMoreKeysKeyboardColumn;
|
mMaxMoreKeysKeyboardColumn = keyboard.mMaxMoreKeysKeyboardColumn;
|
||||||
mKeyVisualAttributes = keyboard.mKeyVisualAttributes;
|
mKeyVisualAttributes = keyboard.mKeyVisualAttributes;
|
||||||
mTopPadding = keyboard.mTopPadding;
|
mPadding = keyboard.mPadding;
|
||||||
mVerticalGap = keyboard.mVerticalGap;
|
mVerticalGap = keyboard.mVerticalGap;
|
||||||
|
|
||||||
mSortedKeys = keyboard.mSortedKeys;
|
mSortedKeys = keyboard.mSortedKeys;
|
||||||
@ -178,7 +179,6 @@ public class Keyboard {
|
|||||||
/**
|
/**
|
||||||
* Return the sorted list of keys of this keyboard.
|
* Return the sorted list of keys of this keyboard.
|
||||||
* The keys are sorted from top-left to bottom-right order.
|
* 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.
|
* @return the sorted unmodifiable list of {@link Key}s of this keyboard.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -17,12 +17,13 @@
|
|||||||
package org.futo.inputmethod.keyboard;
|
package org.futo.inputmethod.keyboard;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.Window;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
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.LanguageOnSpacebarUtils;
|
||||||
import org.futo.inputmethod.latin.utils.ResourceUtils;
|
import org.futo.inputmethod.latin.utils.ResourceUtils;
|
||||||
import org.futo.inputmethod.latin.utils.ScriptUtils;
|
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.KeyboardLayoutSetV2;
|
||||||
import org.futo.inputmethod.v2keyboard.KeyboardLayoutSetV2Params;
|
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.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -124,18 +130,50 @@ public final class KeyboardSwitcher implements SwitchActions {
|
|||||||
final int currentAutoCapsState, final int currentRecapitalizeState) {
|
final int currentAutoCapsState, final int currentRecapitalizeState) {
|
||||||
|
|
||||||
final Resources res = mThemeContext.getResources();
|
final Resources res = mThemeContext.getResources();
|
||||||
final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
|
|
||||||
|
|
||||||
final RichInputMethodSubtype subtype = mRichImm.getCurrentSubtype();
|
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(
|
final KeyboardLayoutSetV2Params params = new KeyboardLayoutSetV2Params(
|
||||||
keyboardWidth,
|
keyboardWidth,
|
||||||
null, // Auto keyboard height
|
keyboardHeight,
|
||||||
subtype.getKeyboardLayoutSetName(),
|
padding,
|
||||||
|
layoutSetName,
|
||||||
subtype.getLocale(),
|
subtype.getLocale(),
|
||||||
editorInfo == null ? new EditorInfo() : editorInfo,
|
editorInfo == null ? new EditorInfo() : editorInfo,
|
||||||
settingsValues.mIsNumberRowEnabled,
|
settingsValues.mIsNumberRowEnabled,
|
||||||
4.0f,
|
sizingCalculator.calculateGap(),
|
||||||
res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE,
|
splitLayoutWidth != 0,
|
||||||
|
splitLayoutWidth,
|
||||||
settingsValues.mShowsActionKey ? settingsValues.mActionKeyId : null,
|
settingsValues.mShowsActionKey ? settingsValues.mActionKeyId : null,
|
||||||
LongPressKeySettings.load(mThemeContext)
|
LongPressKeySettings.load(mThemeContext)
|
||||||
);
|
);
|
||||||
@ -176,7 +214,6 @@ public final class KeyboardSwitcher implements SwitchActions {
|
|||||||
final Keyboard oldKeyboard = keyboardView.getKeyboard();
|
final Keyboard oldKeyboard = keyboardView.getKeyboard();
|
||||||
final Keyboard newKeyboard = mKeyboardLayoutSet.getKeyboard(element);
|
final Keyboard newKeyboard = mKeyboardLayoutSet.getKeyboard(element);
|
||||||
keyboardView.setKeyboard(newKeyboard);
|
keyboardView.setKeyboard(newKeyboard);
|
||||||
mCurrentInputView.setKeyboardTopPadding(newKeyboard.mTopPadding);
|
|
||||||
keyboardView.setKeyPreviewPopupEnabled(
|
keyboardView.setKeyPreviewPopupEnabled(
|
||||||
currentSettingsValues.mKeyPreviewPopupOn,
|
currentSettingsValues.mKeyPreviewPopupOn,
|
||||||
currentSettingsValues.mKeyPreviewPopupDismissDelay);
|
currentSettingsValues.mKeyPreviewPopupDismissDelay);
|
||||||
|
@ -401,6 +401,8 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
|
|||||||
} else {
|
} else {
|
||||||
mAccessibilityDelegate = null;
|
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);
|
mMainKeyboardView = (MainKeyboardView) findViewById(R.id.keyboard_view);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKeyboardTopPadding(final int keyboardTopPadding) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean dispatchHoverEvent(final MotionEvent event) {
|
protected boolean dispatchHoverEvent(final MotionEvent event) {
|
||||||
if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()
|
if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()
|
||||||
|
@ -19,10 +19,8 @@ import android.view.inputmethod.InlineSuggestionsResponse
|
|||||||
import android.view.inputmethod.InputConnection
|
import android.view.inputmethod.InputConnection
|
||||||
import android.view.inputmethod.InputMethodSubtype
|
import android.view.inputmethod.InputMethodSubtype
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
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.collectAsState
|
|
||||||
import androidx.compose.runtime.key
|
import androidx.compose.runtime.key
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clipToBounds
|
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.DynamicThemeProviderOwner
|
||||||
import org.futo.inputmethod.latin.uix.EmojiTracker.unuseEmoji
|
import org.futo.inputmethod.latin.uix.EmojiTracker.unuseEmoji
|
||||||
import org.futo.inputmethod.latin.uix.EmojiTracker.useEmoji
|
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.KeyboardColorScheme
|
||||||
import org.futo.inputmethod.latin.uix.SUGGESTION_BLACKLIST
|
import org.futo.inputmethod.latin.uix.SUGGESTION_BLACKLIST
|
||||||
import org.futo.inputmethod.latin.uix.THEME_KEY
|
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.differsFrom
|
||||||
import org.futo.inputmethod.latin.uix.getSetting
|
import org.futo.inputmethod.latin.uix.getSetting
|
||||||
import org.futo.inputmethod.latin.uix.getSettingBlocking
|
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.isDirectBootUnlocked
|
||||||
import org.futo.inputmethod.latin.uix.setSetting
|
import org.futo.inputmethod.latin.uix.setSetting
|
||||||
import org.futo.inputmethod.latin.uix.theme.ThemeOption
|
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.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.KeyboardSizeSettingKind
|
||||||
|
import org.futo.inputmethod.v2keyboard.KeyboardSizeStateProvider
|
||||||
|
|
||||||
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?) {
|
||||||
@ -90,7 +88,8 @@ private class UnlockedBroadcastReceiver(val onDeviceUnlocked: () -> Unit) : Broa
|
|||||||
}
|
}
|
||||||
|
|
||||||
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner,
|
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner,
|
||||||
LatinIMELegacy.SuggestionStripController, DynamicThemeProviderOwner {
|
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
|
||||||
@ -205,7 +204,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invalidateKeyboard(refreshSettings: Boolean = false) {
|
fun invalidateKeyboard(refreshSettings: Boolean = false) {
|
||||||
settingsRefreshRequired = settingsRefreshRequired || refreshSettings
|
settingsRefreshRequired = settingsRefreshRequired || refreshSettings
|
||||||
|
|
||||||
if(!uixManager.isMainKeyboardHidden) {
|
if(!uixManager.isMainKeyboardHidden) {
|
||||||
@ -427,12 +426,12 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val padding = getSettingFlow(KeyboardBottomOffsetSetting).collectAsState(initial = 0.0f)
|
|
||||||
|
|
||||||
key(legacyInputView) {
|
key(legacyInputView) {
|
||||||
AndroidView(factory = {
|
AndroidView(factory = {
|
||||||
legacyInputView!!
|
legacyInputView!!
|
||||||
}, modifier = modifier.padding(0.dp, 0.dp, 0.dp, padding.value.dp), onRelease = {
|
}, modifier = modifier, onRelease = {
|
||||||
val view = it as InputView
|
val view = it as InputView
|
||||||
view.deallocateMemory()
|
view.deallocateMemory()
|
||||||
view.removeAllViews()
|
view.removeAllViews()
|
||||||
@ -762,4 +761,19 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
|||||||
|
|
||||||
// TODO: Spell checker service
|
// 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
|
package org.futo.inputmethod.latin.uix
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.graphics.Rect
|
||||||
import android.view.ContextThemeWrapper
|
import android.view.ContextThemeWrapper
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@ -109,12 +109,14 @@ fun KeyboardLayoutPreview(id: String, width: Dp = 172.dp, locale: Locale? = null
|
|||||||
KeyboardLayoutSetV2Params(
|
KeyboardLayoutSetV2Params(
|
||||||
width = widthPx,
|
width = widthPx,
|
||||||
height = heightPx,
|
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,
|
useSplitLayout = isLandscape,
|
||||||
|
splitLayoutWidth = widthPx * 2 / 3,
|
||||||
bottomActionKey = null
|
bottomActionKey = null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.futo.inputmethod.latin.uix
|
package org.futo.inputmethod.latin.uix
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.KeyguardManager
|
|
||||||
import android.content.ClipDescription
|
import android.content.ClipDescription
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -62,11 +61,15 @@ 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
|
||||||
import androidx.lifecycle.lifecycleScope
|
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.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.futo.inputmethod.accessibility.AccessibilityUtils
|
import org.futo.inputmethod.accessibility.AccessibilityUtils
|
||||||
import org.futo.inputmethod.latin.AudioAndHapticFeedbackManager
|
import org.futo.inputmethod.latin.AudioAndHapticFeedbackManager
|
||||||
import org.futo.inputmethod.latin.BuildConfig
|
import org.futo.inputmethod.latin.BuildConfig
|
||||||
|
import org.futo.inputmethod.latin.FoldingOptions
|
||||||
import org.futo.inputmethod.latin.LanguageSwitcherDialog
|
import org.futo.inputmethod.latin.LanguageSwitcherDialog
|
||||||
import org.futo.inputmethod.latin.LatinIME
|
import org.futo.inputmethod.latin.LatinIME
|
||||||
import org.futo.inputmethod.latin.R
|
import org.futo.inputmethod.latin.R
|
||||||
@ -103,6 +106,12 @@ val LocalThemeProvider = compositionLocalOf<DynamicThemeProvider> {
|
|||||||
error("No LocalThemeProvider provided")
|
error("No LocalThemeProvider provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val LocalFoldingState = compositionLocalOf<FoldingOptions> {
|
||||||
|
FoldingOptions(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private class LatinIMEActionInputTransaction(
|
private class LatinIMEActionInputTransaction(
|
||||||
private val inputLogic: InputLogic,
|
private val inputLogic: InputLogic,
|
||||||
shouldApplySpace: Boolean,
|
shouldApplySpace: Boolean,
|
||||||
@ -323,6 +332,8 @@ class UixManager(private val latinIME: LatinIME) {
|
|||||||
isShowingActionEditor.value = true
|
isShowingActionEditor.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val foldingOptions = mutableStateOf(FoldingOptions(null))
|
||||||
|
|
||||||
var isInputOverridden = mutableStateOf(false)
|
var isInputOverridden = mutableStateOf(false)
|
||||||
|
|
||||||
var currWindowActionWindow: ActionWindow? = null
|
var currWindowActionWindow: ActionWindow? = null
|
||||||
@ -622,35 +633,39 @@ class UixManager(private val latinIME: LatinIME) {
|
|||||||
CompositionLocalProvider(LocalManager provides keyboardManagerForAction) {
|
CompositionLocalProvider(LocalManager provides keyboardManagerForAction) {
|
||||||
CompositionLocalProvider(LocalThemeProvider provides latinIME.getDrawableProvider()) {
|
CompositionLocalProvider(LocalThemeProvider provides latinIME.getDrawableProvider()) {
|
||||||
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
|
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
|
||||||
InputDarkener(isInputOverridden.value || isShowingActionEditor.value) {
|
CompositionLocalProvider(LocalFoldingState provides foldingOptions.value) {
|
||||||
closeActionWindow()
|
InputDarkener(isInputOverridden.value || isShowingActionEditor.value) {
|
||||||
isShowingActionEditor.value = false
|
closeActionWindow()
|
||||||
}
|
isShowingActionEditor.value = false
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Spacer(modifier = Modifier.weight(1.0f))
|
Spacer(modifier = Modifier.weight(1.0f))
|
||||||
Surface(modifier = Modifier.onSizeChanged {
|
Surface(modifier = Modifier.onSizeChanged {
|
||||||
latinIME.updateTouchableHeight(it.height)
|
latinIME.updateTouchableHeight(it.height)
|
||||||
}, color = latinIME.keyboardColor) {
|
}, color = latinIME.keyboardColor) {
|
||||||
Box {
|
Box {
|
||||||
Column {
|
Column {
|
||||||
when {
|
when {
|
||||||
currWindowActionWindow != null -> ActionViewWithHeader(
|
currWindowActionWindow != null -> ActionViewWithHeader(
|
||||||
currWindowActionWindow!!
|
currWindowActionWindow!!
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> MainKeyboardViewWithActionBar()
|
else -> MainKeyboardViewWithActionBar()
|
||||||
|
}
|
||||||
|
|
||||||
|
latinIME.LegacyKeyboardView(hidden = isMainKeyboardHidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
latinIME.LegacyKeyboardView(hidden = isMainKeyboardHidden)
|
ForgetWordDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
ForgetWordDialog()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ActionEditorHost()
|
}
|
||||||
|
|
||||||
|
ActionEditorHost()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -852,6 +867,13 @@ class UixManager(private val latinIME: LatinIME) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isActionsExpanded.value = latinIME.getSettingBlocking(ActionBarExpanded)
|
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() {
|
fun onPersistentStatesUnlocked() {
|
||||||
|
@ -22,10 +22,11 @@ import kotlinx.coroutines.delay
|
|||||||
import org.futo.inputmethod.latin.R
|
import org.futo.inputmethod.latin.R
|
||||||
import org.futo.inputmethod.latin.uix.Action
|
import org.futo.inputmethod.latin.uix.Action
|
||||||
import org.futo.inputmethod.latin.uix.ActionWindow
|
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.settings.ScrollableList
|
||||||
import org.futo.inputmethod.latin.uix.theme.ThemeOptions
|
import org.futo.inputmethod.latin.uix.theme.ThemeOptions
|
||||||
import org.futo.inputmethod.latin.uix.theme.Typography
|
import org.futo.inputmethod.latin.uix.theme.Typography
|
||||||
|
import org.futo.inputmethod.v2keyboard.KeyboardSizeStateProvider
|
||||||
|
|
||||||
val DebugLabel = Typography.labelSmall.copy(fontFamily = FontFamily.Monospace)
|
val DebugLabel = Typography.labelSmall.copy(fontFamily = FontFamily.Monospace)
|
||||||
val DebugTitle = Typography.titleSmall.copy(fontFamily = FontFamily.Monospace, fontWeight = FontWeight.Bold)
|
val DebugTitle = Typography.titleSmall.copy(fontFamily = FontFamily.Monospace, fontWeight = FontWeight.Bold)
|
||||||
@ -190,6 +191,8 @@ val MemoryDebugAction = Action(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val foldingState = LocalFoldingState.current
|
||||||
|
|
||||||
ScrollableList {
|
ScrollableList {
|
||||||
Text("Editor Info", style = DebugTitle)
|
Text("Editor Info", style = DebugTitle)
|
||||||
latinIme.currentInputEditorInfo?.let { info ->
|
latinIme.currentInputEditorInfo?.let { info ->
|
||||||
@ -228,6 +231,16 @@ val MemoryDebugAction = Action(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
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)
|
Text("Memory Use", style = DebugTitle)
|
||||||
state.value.forEach {
|
state.value.forEach {
|
||||||
val value = it.value.toInt().toFloat() / 1000.0f
|
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.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Insets;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
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.annotations.UsedForTesting;
|
||||||
import org.futo.inputmethod.latin.R;
|
import org.futo.inputmethod.latin.R;
|
||||||
@ -182,9 +186,14 @@ public final class ResourceUtils {
|
|||||||
return matchedAll;
|
return matchedAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getDefaultKeyboardWidth(final Resources res) {
|
public static int getDefaultKeyboardWidth(final Window window, final Resources res) {
|
||||||
final DisplayMetrics dm = res.getDisplayMetrics();
|
if(window != null && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)) {
|
||||||
return dm.widthPixels;
|
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) {
|
public static int getKeyboardHeight(final Resources res, final SettingsValues settingsValues) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.futo.inputmethod.v2keyboard
|
package org.futo.inputmethod.v2keyboard
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Rect
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.inputmethod.EditorInfo
|
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.InputTypeUtils
|
||||||
import org.futo.inputmethod.latin.utils.ResourceUtils
|
import org.futo.inputmethod.latin.utils.ResourceUtils
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class Script(val id: Int, val iso4letterCode: String) {
|
enum class Script(val id: Int, val iso4letterCode: String) {
|
||||||
@ -71,24 +71,25 @@ private fun EditorInfo.getPrivateImeOptions(): Map<String, String> {
|
|||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun EditorInfo.getPrimaryLayoutOverride(): String? =
|
fun getPrimaryLayoutOverride(editorInfo: EditorInfo?): String? {
|
||||||
getPrivateImeOptions()["org.futo.inputmethod.latin.ForceLayout"]
|
return editorInfo?.getPrivateImeOptions()?.get("org.futo.inputmethod.latin.ForceLayout")
|
||||||
|
}
|
||||||
|
|
||||||
data class KeyboardLayoutSetV2Params(
|
data class KeyboardLayoutSetV2Params(
|
||||||
val width: Int,
|
val width: Int,
|
||||||
val height: Int?,
|
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 useSplitLayout: Boolean,
|
||||||
|
val splitLayoutWidth: Int,
|
||||||
val bottomActionKey: Int?,
|
val bottomActionKey: Int?,
|
||||||
val longPressKeySettings: LongPressKeySettings? = null
|
val longPressKeySettings: LongPressKeySettings? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class KeyboardLayoutSetV2 internal constructor(
|
class KeyboardLayoutSetV2 internal constructor(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val params: KeyboardLayoutSetV2Params
|
private val params: KeyboardLayoutSetV2Params
|
||||||
@ -183,31 +184,22 @@ class KeyboardLayoutSetV2 internal constructor(
|
|||||||
NumberRowMode.AlwaysDisabled -> false
|
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
|
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) *
|
(ResourceUtils.getDefaultKeyboardHeight(context.resources) / 4.0) *
|
||||||
keyboardHeightMultiplier
|
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 {
|
fun getKeyboard(element: KeyboardLayoutElement): Keyboard {
|
||||||
|
|
||||||
val keyboardId = KeyboardId(
|
val keyboardId = KeyboardId(
|
||||||
params.keyboardLayoutSet,
|
params.keyboardLayoutSet,
|
||||||
forcedLocale ?: params.locale,
|
forcedLocale ?: params.locale,
|
||||||
params.width,
|
widthMinusPadding,
|
||||||
params.height ?: getRecommendedKeyboardHeight(),
|
heightMinusPadding,
|
||||||
keyboardMode,
|
keyboardMode,
|
||||||
element.elementId,
|
element.elementId,
|
||||||
editorInfo,
|
editorInfo,
|
||||||
@ -231,6 +223,8 @@ class KeyboardLayoutSetV2 internal constructor(
|
|||||||
val layoutParams = LayoutParams(
|
val layoutParams = LayoutParams(
|
||||||
gap = params.gap.dp,
|
gap = params.gap.dp,
|
||||||
useSplitLayout = params.useSplitLayout,
|
useSplitLayout = params.useSplitLayout,
|
||||||
|
splitLayoutWidth = params.splitLayoutWidth,
|
||||||
|
padding = params.padding,
|
||||||
standardRowHeight = singularRowHeight,
|
standardRowHeight = singularRowHeight,
|
||||||
element = element
|
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
|
package org.futo.inputmethod.v2keyboard
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Rect
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import org.futo.inputmethod.keyboard.KeyConsts
|
import org.futo.inputmethod.keyboard.KeyConsts
|
||||||
import org.futo.inputmethod.keyboard.internal.KeyboardLayoutElement
|
import org.futo.inputmethod.keyboard.internal.KeyboardLayoutElement
|
||||||
@ -82,6 +83,8 @@ data class LayoutRow(
|
|||||||
data class LayoutParams(
|
data class LayoutParams(
|
||||||
val gap: Dp,
|
val gap: Dp,
|
||||||
val useSplitLayout: Boolean,
|
val useSplitLayout: Boolean,
|
||||||
|
val splitLayoutWidth: Int,
|
||||||
|
val padding: Rect,
|
||||||
val standardRowHeight: Double,
|
val standardRowHeight: Double,
|
||||||
val element: KeyboardLayoutElement,
|
val element: KeyboardLayoutElement,
|
||||||
)
|
)
|
||||||
@ -144,7 +147,7 @@ data class LayoutEngine(
|
|||||||
private val isSplitLayout = layoutParams.useSplitLayout
|
private val isSplitLayout = layoutParams.useSplitLayout
|
||||||
|
|
||||||
private val layoutWidth = if(isSplitLayout) {
|
private val layoutWidth = if(isSplitLayout) {
|
||||||
params.mId.mWidth * 2 / 3
|
layoutParams.splitLayoutWidth
|
||||||
} else {
|
} else {
|
||||||
params.mId.mWidth
|
params.mId.mWidth
|
||||||
}
|
}
|
||||||
@ -526,10 +529,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, y, height)
|
= addRow(row, 0.0f + layoutParams.padding.left, 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()
|
val startingOffset = params.mId.mWidth - row.sumOf { it.widthPx.toDouble() }.toFloat() + layoutParams.padding.left
|
||||||
addRow(row, startingOffset, y, height)
|
addRow(row, startingOffset, y, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,7 +548,7 @@ data class LayoutEngine(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addKeys(rows: List<LayoutRow>): Int {
|
private fun addKeys(rows: List<LayoutRow>): Int {
|
||||||
var currentY = 0.0f
|
var currentY = 0.0f + layoutParams.padding.top
|
||||||
rows.forEach { row ->
|
rows.forEach { row ->
|
||||||
addRow(row, currentY.toInt())
|
addRow(row, currentY.toInt())
|
||||||
currentY += row.height
|
currentY += row.height
|
||||||
@ -563,14 +566,14 @@ data class LayoutEngine(
|
|||||||
|
|
||||||
val rows = computeRows(this.rows)
|
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.mOccupiedHeight = totalKeyboardHeight - verticalGapPx.roundToInt()
|
||||||
params.mOccupiedWidth = params.mId.mWidth
|
params.mOccupiedWidth = params.mId.mWidth + layoutParams.padding.left + layoutParams.padding.right
|
||||||
params.mTopPadding = 0
|
params.mTopPadding = 0//layoutParams.padding.top
|
||||||
params.mBottomPadding = 0
|
params.mBottomPadding = 0//layoutParams.padding.bottom
|
||||||
params.mLeftPadding = 0
|
params.mLeftPadding = 0//layoutParams.padding.left
|
||||||
params.mRightPadding = 0
|
params.mRightPadding = 0//layoutParams.padding.right
|
||||||
|
|
||||||
params.mBaseWidth = params.mOccupiedWidth
|
params.mBaseWidth = params.mOccupiedWidth
|
||||||
params.mDefaultKeyWidth = regularKeyWidth.roundToInt()
|
params.mDefaultKeyWidth = regularKeyWidth.roundToInt()
|
||||||
|
@ -18,6 +18,7 @@ package org.futo.inputmethod.keyboard;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
@ -142,7 +143,7 @@ public abstract class KeyboardLayoutSetTestsBase extends AndroidTestCase {
|
|||||||
final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) {
|
final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) {
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
final Resources res = context.getResources();
|
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 int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res);
|
||||||
|
|
||||||
final RichInputMethodSubtype richInputMethodSubtype = RichInputMethodSubtype.getRichInputMethodSubtype(subtype);
|
final RichInputMethodSubtype richInputMethodSubtype = RichInputMethodSubtype.getRichInputMethodSubtype(subtype);
|
||||||
@ -150,11 +151,11 @@ public abstract class KeyboardLayoutSetTestsBase extends AndroidTestCase {
|
|||||||
return new KeyboardLayoutSetV2(
|
return new KeyboardLayoutSetV2(
|
||||||
context,
|
context,
|
||||||
new KeyboardLayoutSetV2Params(
|
new KeyboardLayoutSetV2Params(
|
||||||
keyboardWidth, keyboardHeight,
|
keyboardWidth, keyboardHeight, new Rect(),
|
||||||
richInputMethodSubtype.getKeyboardLayoutSetName(),
|
richInputMethodSubtype.getKeyboardLayoutSetName(),
|
||||||
richInputMethodSubtype.getLocale(),
|
richInputMethodSubtype.getLocale(),
|
||||||
editorInfo, false,
|
editorInfo, false,
|
||||||
4.0f, splitLayoutEnabled,
|
4.0f, splitLayoutEnabled, 0,
|
||||||
languageSwitchKeyEnabled ? ActionRegistry.INSTANCE.actionStringIdToIdx("switch_language") : null,
|
languageSwitchKeyEnabled ? ActionRegistry.INSTANCE.actionStringIdToIdx("switch_language") : null,
|
||||||
LongPressKeySettings.forTest()
|
LongPressKeySettings.forTest()
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.futo.inputmethod.keyboard.internal
|
package org.futo.inputmethod.keyboard.internal
|
||||||
|
|
||||||
|
import android.graphics.Rect
|
||||||
import android.test.AndroidTestCase
|
import android.test.AndroidTestCase
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
@ -14,12 +15,14 @@ import kotlin.math.absoluteValue
|
|||||||
class KeyboardLayoutSetV2Tests : AndroidTestCase() {
|
class KeyboardLayoutSetV2Tests : AndroidTestCase() {
|
||||||
private val layoutParams = KeyboardLayoutSetV2Params(
|
private val layoutParams = KeyboardLayoutSetV2Params(
|
||||||
width = 1024,
|
width = 1024,
|
||||||
height = null,
|
height = 1024,
|
||||||
|
padding = Rect(),
|
||||||
keyboardLayoutSet = "qwerty",
|
keyboardLayoutSet = "qwerty",
|
||||||
locale = Locale.ENGLISH,
|
locale = Locale.ENGLISH,
|
||||||
editorInfo = EditorInfo(),
|
editorInfo = EditorInfo(),
|
||||||
numberRow = false,
|
numberRow = false,
|
||||||
useSplitLayout = false,
|
useSplitLayout = false,
|
||||||
|
splitLayoutWidth = 0,
|
||||||
bottomActionKey = null
|
bottomActionKey = null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user