From 65466860704a5cf2753ca2c97e339715e9a52891 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Wed, 10 Jan 2024 12:21:39 +0100 Subject: [PATCH] fix #397 and add some related tests --- .../openboard/inputmethod/keyboard/Key.java | 5 +- .../openboard/inputmethod/latin/ParserTest.kt | 79 ++++++++++++++++++- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/Key.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/Key.java index 21c17aaf6..70a6d4f8b 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/Key.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/Key.java @@ -1086,6 +1086,7 @@ public class Key implements Comparable { actionFlags = ACTION_FLAGS_NO_KEY_PREVIEW; // label + String label = null; if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) { mLabel = params.mId.mCustomActionLabel; } else if (code >= Character.MIN_SUPPLEMENTARY_CODE_POINT) { @@ -1094,14 +1095,14 @@ public class Key implements Comparable { // code point nor as a surrogate pair. mLabel = new StringBuilder().appendCodePoint(code).toString(); } else { - final String label = KeySpecParser.getLabel(keySpec); + label = KeySpecParser.getLabel(keySpec); mLabel = needsToUpcase ? StringUtils.toTitleCaseOfKeyLabel(label, localeForUpcasing) : label; } // moreKeys - final String[] moreKeys = MoreKeysUtilsKt.createMoreKeysArray(popupSet, mKeyboardParams, mLabel != null ? mLabel : keySpec); + final String[] moreKeys = MoreKeysUtilsKt.createMoreKeysArray(popupSet, mKeyboardParams, label != null ? label : keySpec); mMoreKeysColumnAndFlags = getMoreKeysColumnAndFlagsAndSetNullInArray(params, moreKeys); final String[] finalMoreKeys = moreKeys == null ? null : MoreKeySpec.filterOutEmptyString(moreKeys); if (finalMoreKeys != null) { diff --git a/app/src/test/java/org/dslul/openboard/inputmethod/latin/ParserTest.kt b/app/src/test/java/org/dslul/openboard/inputmethod/latin/ParserTest.kt index 8b0594064..6d834d37c 100644 --- a/app/src/test/java/org/dslul/openboard/inputmethod/latin/ParserTest.kt +++ b/app/src/test/java/org/dslul/openboard/inputmethod/latin/ParserTest.kt @@ -1,12 +1,20 @@ package org.dslul.openboard.inputmethod.latin +import android.view.inputmethod.EditorInfo +import android.view.inputmethod.InputMethodSubtype +import com.android.inputmethod.keyboard.ProximityInfo +import org.dslul.openboard.inputmethod.keyboard.Key.KeyParams +import org.dslul.openboard.inputmethod.keyboard.Keyboard import org.dslul.openboard.inputmethod.keyboard.KeyboardId import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet +import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardBuilder import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardParams +import org.dslul.openboard.inputmethod.keyboard.internal.TouchPositionCorrection +import org.dslul.openboard.inputmethod.keyboard.internal.UniqueKeysCache import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.MORE_KEYS_NORMAL import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.SimpleKeyboardParser import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.addLocaleKeyTextsToParams -import org.junit.Assert +import org.dslul.openboard.inputmethod.latin.utils.AdditionalSubtypeUtils.createEmojiCapableAdditionalSubtype import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test @@ -14,11 +22,14 @@ import org.junit.runner.RunWith import org.robolectric.Robolectric import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements import org.robolectric.shadows.ShadowLog @RunWith(RobolectricTestRunner::class) @Config(shadows = [ ShadowInputMethodManager2::class, + ShadowProximityInfo::class, ]) class ParserTest { private lateinit var latinIME: LatinIME @@ -98,4 +109,70 @@ f""", // no newline at the end assertEquals(wantedKeyLabels, keyLabels) } } + + @Test fun canLoadKeyboard() { + val editorInfo = EditorInfo() + val subtype = createEmojiCapableAdditionalSubtype("en", "qwerty", true) + val (kb, keys) = buildKeyboard(editorInfo, subtype, KeyboardId.ELEMENT_ALPHABET) + assertEquals(kb.sortedKeys.size, keys.sumOf { it.size }) + } + + @Test fun `dvorak has 4 rows`() { + val editorInfo = EditorInfo() + val subtype = createEmojiCapableAdditionalSubtype("en", "dvorak", true) + val (kb, keys) = buildKeyboard(editorInfo, subtype, KeyboardId.ELEMENT_ALPHABET) + assertEquals(keys.size, 4) + } + + @Test fun `de_DE has extra keys`() { + val editorInfo = EditorInfo() + val subtype = createEmojiCapableAdditionalSubtype("de_DE", "qwertz+", true) + val (kb, keys) = buildKeyboard(editorInfo, subtype, KeyboardId.ELEMENT_ALPHABET) + assertEquals(keys[0].size, 11) + assertEquals(keys[1].size, 11) + assertEquals(keys[2].size, 10) + val (kb2, keys2) = buildKeyboard(editorInfo, subtype, KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) + assertEquals(keys2[0].size, 11) + assertEquals(keys2[1].size, 11) + assertEquals(keys2[2].size, 10) + } + + @Test fun `moreKey count does not depend on shift for (for simply layout)`() { + val editorInfo = EditorInfo() + val subtype = createEmojiCapableAdditionalSubtype("en", "qwerty", true) + val (kb, keys) = buildKeyboard(editorInfo, subtype, KeyboardId.ELEMENT_ALPHABET) + val (kb2, keys2) = buildKeyboard(editorInfo, subtype, KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) + assertEquals(kb.sortedKeys.size, kb2.sortedKeys.size) + keys.forEachIndexed { i, kpList -> kpList.forEachIndexed { j, kp -> + assertEquals(kp.mMoreKeys?.size, keys2[i][j].mMoreKeys?.size) + } } + kb.sortedKeys.forEachIndexed { index, key -> + assertEquals(key.moreKeys?.size, kb2.sortedKeys[index].moreKeys?.size) + } + } + + private fun buildKeyboard(editorInfo: EditorInfo, subtype: InputMethodSubtype, elementId: Int): Pair>> { + val layoutParams = KeyboardLayoutSet.Params() + val editorInfoField = KeyboardLayoutSet.Params::class.java.getDeclaredField("mEditorInfo").apply { isAccessible = true } + editorInfoField.set(layoutParams, editorInfo) + val subtypeField = KeyboardLayoutSet.Params::class.java.getDeclaredField("mSubtype").apply { isAccessible = true } + subtypeField.set(layoutParams, RichInputMethodSubtype(subtype)) + val widthField = KeyboardLayoutSet.Params::class.java.getDeclaredField("mKeyboardWidth").apply { isAccessible = true } + widthField.setInt(layoutParams, 500) + val heightField = KeyboardLayoutSet.Params::class.java.getDeclaredField("mKeyboardHeight").apply { isAccessible = true } + heightField.setInt(layoutParams, 300) + + val keysInRowsField = KeyboardBuilder::class.java.getDeclaredField("keysInRows").apply { isAccessible = true } + + val id = KeyboardId(elementId, layoutParams) + val builder = KeyboardBuilder(latinIME, KeyboardParams(UniqueKeysCache.NO_CACHE)) + builder.load(id) + return builder.build() to keysInRowsField.get(builder) as ArrayList> + } +} + +@Implements(ProximityInfo::class) +class ShadowProximityInfo { + @Implementation + fun createNativeProximityInfo(tpc: TouchPositionCorrection): Long = 0 }