From 552fa0d94f3e87e24ea4e2984998af0d8a9af204 Mon Sep 17 00:00:00 2001 From: Emil Kosz Date: Mon, 21 Oct 2024 15:15:35 +0200 Subject: [PATCH] New method for cycling symbols. --- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 2 +- .../cfpi_fpsi/eu/titanboard/InputMethod.java | 76 +- .../cfpi_fpsi/eu/titanboard/InputView.java | 2 +- .../cfpi_fpsi/eu/titanboard/Settings.java | 35 +- .../cfpi_fpsi/eu/titanboard/SymbolCycler.java | 77 ++ app/src/main/res/values/arrays.xml | 23 +- app/src/main/res/values/strings.xml | 5 +- app/src/main/res/xml/keymaps_titan.xml | 719 ++++++++++++++---- app/src/main/res/xml/preferences.xml | 12 +- 10 files changed, 725 insertions(+), 230 deletions(-) create mode 100644 app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolCycler.java diff --git a/app/build.gradle b/app/build.gradle index 8059653..a5686dd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { minSdk 19 //noinspection OldTargetApi targetSdk 34 - versionCode 21 - versionName "0.2.1" + versionCode 3 + versionName "0.3" } buildTypes { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 85ee460..44cf684 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,7 +27,7 @@ diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/InputMethod.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/InputMethod.java index 758b0b1..d44b8aa 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/InputMethod.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/InputMethod.java @@ -22,32 +22,27 @@ package cfpi_fpsi.eu.titanboard; import android.annotation.SuppressLint; import android.inputmethodservice.InputMethodService; import android.os.Vibrator; -import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import java.util.ArrayList; -import java.util.Set; // TODO: Implement auto-correct. // TODO: Implement auto-caps. // TODO: Implement device recognition and a keymap picking based on it. /** - * @noinspection deprecation */ public class InputMethod extends InputMethodService { public MetaKeyManager mMetaKeyManager; public KeymapManager mKeymapManager; - public String mCurrentLanguage; - private int mKeyCounter = 0; + public String mCurrentKeymap; + private SymbolCycler mSymbolCycler; private boolean mRegularKeyPressed = false; - private InputView mInputView; - private Settings mSettings; + public InputView mInputView; + public Settings mSettings; @Override public void onCreate() { @@ -56,6 +51,7 @@ public class InputMethod extends InputMethodService { Vibrator mVibrator = (Vibrator) getBaseContext().getSystemService(VIBRATOR_SERVICE); mMetaKeyManager = new MetaKeyManager(mVibrator); mKeymapManager = new KeymapManager(getResources().getXml(R.xml.keymaps_titan)); + mSymbolCycler = new SymbolCycler(this); cycleKeymaps(); } @@ -100,30 +96,17 @@ public class InputMethod extends InputMethodService { mMetaKeyManager.adjustMetaStateAfterKeypress(); return true; default: - ArrayList mCurrentValues = getKeyValues(keyCode); + ArrayList symbols = getKeyValues(keyCode); - if (mCurrentValues == null) { + if (symbols == null) { return false; } mRegularKeyPressed = true; - if (event.getRepeatCount() == 0) { - conn.commitText(mCurrentValues.get(0), 1); - } else if (event.getRepeatCount() % 7 == 0) { - mKeyCounter++; - if (mKeyCounter >= mCurrentValues.size()) { - mKeyCounter = 0; - } - - mInputView.updateSymbolsView(mCurrentValues, mKeyCounter); - - ExtractedText text = conn.getExtractedText(new ExtractedTextRequest(), 0); - - if (text != null) { - conn.setComposingRegion(text.selectionStart - 1, text.selectionStart); - conn.setComposingText(mCurrentValues.get(mKeyCounter), 1); - } + if (event.getRepeatCount() == 0 && !symbols.isEmpty()) { + conn.commitText(symbols.get(0), 1); + mSymbolCycler.startAutomaticCycling(symbols, conn); } return true; @@ -135,36 +118,37 @@ public class InputMethod extends InputMethodService { // there, and then select the next keymap. ArrayList selectedLanguages = mSettings.getSelectedKeymaps(); - if (selectedLanguages.isEmpty() || mCurrentLanguage == null) { - mCurrentLanguage = "eu"; + if (selectedLanguages.isEmpty() || mCurrentKeymap == null) { + mCurrentKeymap = getBaseContext().getResources().getString(R.string.keymap_default); return; } - int index = selectedLanguages.indexOf(mCurrentLanguage); + int index = selectedLanguages.indexOf(mCurrentKeymap); if (index == selectedLanguages.size() - 1) { index = 0; } else { ++index; } - mCurrentLanguage = selectedLanguages.get(index); + mCurrentKeymap = selectedLanguages.get(index); } public boolean onKeyUp(int keyCode, KeyEvent event) { if (mRegularKeyPressed) { - InputConnection conn = getCurrentInputConnection(); - - if (conn == null) { - return false; - } - - conn.finishComposingText(); mMetaKeyManager.adjustMetaStateAfterKeypress(); - mKeyCounter = 0; - mRegularKeyPressed = false; - mInputView.updateSymbolsView(null, 0); } + InputConnection conn = getCurrentInputConnection(); + + if (conn == null) { + return false; + } + + conn.finishComposingText(); + mSymbolCycler.stopCycling(); + mRegularKeyPressed = false; + mInputView.updateSymbolsView(null, 0); + mMetaKeyManager.updateMetaStateUp(keyCode, event); mInputView.updateStateText(); @@ -179,9 +163,11 @@ public class InputMethod extends InputMethodService { @Override public void onStartInput(EditorInfo info, boolean restarting) { super.onStartInput(info, restarting); - if (!mSettings.getSelectedKeymaps().contains(mCurrentLanguage)) { + + if (!mSettings.getSelectedKeymaps().contains(mCurrentKeymap)) { cycleKeymaps(); } + mInputView.updateStateText(); } @@ -193,13 +179,13 @@ public class InputMethod extends InputMethodService { private ArrayList getKeyValues(int keyCode) { if (mMetaKeyManager.getAlt().isActive()) { - return mKeymapManager.getKeyAlt(mCurrentLanguage, keyCode); + return mKeymapManager.getKeyAlt(mCurrentKeymap, keyCode); } if (mMetaKeyManager.getShift().isActive()) { - return mKeymapManager.getKeyShift(mCurrentLanguage, keyCode); + return mKeymapManager.getKeyShift(mCurrentKeymap, keyCode); } - return mKeymapManager.getKeyBase(mCurrentLanguage, keyCode); + return mKeymapManager.getKeyBase(mCurrentKeymap, keyCode); } } diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/InputView.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/InputView.java index 95f1c29..0752efc 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/InputView.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/InputView.java @@ -67,7 +67,7 @@ public class InputView extends RelativeLayout { public void updateStateText() { MetaKeyManager metaManager = mInputMethod.mMetaKeyManager; KeymapManager keymapManager = mInputMethod.mKeymapManager; - String currentLanguage = mInputMethod.mCurrentLanguage; + String currentLanguage = mInputMethod.mCurrentKeymap; mStateButton.setPaintFlags(mStateButton.getPaintFlags() & ~(Paint.UNDERLINE_TEXT_FLAG)); diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/Settings.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/Settings.java index 3c9a3d3..4898aca 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/Settings.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/Settings.java @@ -24,16 +24,21 @@ import android.content.SharedPreferences; import android.preference.PreferenceManager; import java.util.ArrayList; -import java.util.HashMap; import java.util.Map; import java.util.Set; +/** + * @noinspection deprecation + */ public class Settings implements SharedPreferences.OnSharedPreferenceChangeListener { - private final SharedPreferences mPreferences; private final Map mPreferenceValues; + private final Context mContext; + @SuppressWarnings("unchecked") public Settings(Context context) { - mPreferences = PreferenceManager.getDefaultSharedPreferences(context); + mContext = context; + SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext); + PreferenceManager.setDefaultValues(mContext, R.xml.preferences, false); mPreferences.registerOnSharedPreferenceChangeListener(this); mPreferenceValues = (Map) mPreferences.getAll(); } @@ -46,24 +51,36 @@ public class Settings implements SharedPreferences.OnSharedPreferenceChangeListe } } + public Object getOrDefault(String key, Object defaultValue) { + Object value = mPreferenceValues.get(key); + return value == null ? defaultValue : value; + } + public boolean isAutoCapsEnabled() { - return (boolean) mPreferenceValues.get("auto_caps"); + return (boolean) getOrDefault("auto_caps", + mContext.getResources().getBoolean(R.bool.auto_caps_default)); } public boolean isAutoPeriodsEnabled() { - return (boolean) mPreferenceValues.get("auto_periods"); + return (boolean) getOrDefault("auto_periods", + mContext.getResources().getBoolean(R.bool.auto_periods_default)); } public boolean isAutocorrectEnabled() { - return (boolean) mPreferenceValues.get("auto_correct"); + return (boolean) getOrDefault("auto_correct", + mContext.getResources().getBoolean(R.bool.autocorrect_default)); } - public int getLongClickSpeed() { - return Integer.parseInt((String) mPreferenceValues.get("long_click_speed")); + public int getCycleSpeed() { + return Integer.parseInt((String) getOrDefault("cycle_speed", + mContext.getResources().getString(R.string.cycle_speed_default))); } + @SuppressWarnings("unchecked") public ArrayList getSelectedKeymaps() { - Set selectedKeymaps = (Set) mPreferenceValues.get("selected_keymaps"); + Set selectedKeymaps = (Set) + getOrDefault("selected_keymaps", + mContext.getResources().getStringArray(R.array.selected_keymap_defaults)); return new ArrayList<>(selectedKeymaps); } } diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolCycler.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolCycler.java new file mode 100644 index 0000000..3bab644 --- /dev/null +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolCycler.java @@ -0,0 +1,77 @@ +/* + * An input method for the Unihertz Titan/physical keyboard phones + * Copyright (C) 2024 Emil Kosz + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package cfpi_fpsi.eu.titanboard; + +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; + +import java.util.ArrayList; + +public class SymbolCycler extends Handler { + private final InputMethod mInputMethod; + private final SymbolCyclerRunnable mRunnable; + private int mIndex; + private ArrayList mSymbols; + private InputConnection mConn; + + public SymbolCycler(Context context) { + super(Looper.getMainLooper()); + mInputMethod = (InputMethod) context; + mRunnable = new SymbolCyclerRunnable(); + } + + public void startAutomaticCycling(ArrayList symbols, InputConnection conn) { + mSymbols = symbols; + mConn = conn; + mIndex = 0; + stopCycling(); + postDelayed(mRunnable, mInputMethod.mSettings.getCycleSpeed()); + } + + public void stopCycling() { + removeCallbacks(mRunnable); + } + + public void cycle() { + mIndex++; + if (mIndex == mSymbols.size()) { + mIndex = 0; + } + + mInputMethod.mInputView.updateSymbolsView(mSymbols, mIndex); + ExtractedText text = mConn.getExtractedText(new ExtractedTextRequest(), 0); + if (text != null) { + mConn.setComposingRegion(text.selectionStart - 1, text.selectionStart); + mConn.setComposingText(mSymbols.get(mIndex), 1); + } + } + + private class SymbolCyclerRunnable implements Runnable { + @Override + public void run() { + cycle(); + postDelayed(this, mInputMethod.mSettings.getCycleSpeed()); + } + } +} diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 425cf8b..f252a11 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -19,20 +19,27 @@ - European - Phonetic Cyrillic + English + Russian (Phonetic) + French + Polish + Greek - eu - цp + en + ru + fr + pl + el - - eu + + en + ru - + 200 ms 300 ms 400 ms @@ -41,7 +48,7 @@ 1000 ms - + 200 300 400 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dfebda9..2016e2c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,7 +3,7 @@ Titanboard Titanboard preferences - Long click speed + Cycling speed Automatic capitalization Automatic periods Autocorrect @@ -13,5 +13,6 @@ #? #! - 400 + en + 500 \ No newline at end of file diff --git a/app/src/main/res/xml/keymaps_titan.xml b/app/src/main/res/xml/keymaps_titan.xml index b14d1f1..24e0cd2 100644 --- a/app/src/main/res/xml/keymaps_titan.xml +++ b/app/src/main/res/xml/keymaps_titan.xml @@ -18,271 +18,160 @@ --> - - + - + name="en" + latched-name="En" + locked-name="EN"> - - - - - - - - - + + + - - - - - - - - - - - + - - - + - - - - - - + - - - - - - - - - + + + - - - - - - - - - + - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - + - - - - - - - @@ -290,48 +179,405 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + name="ru" + latched-name="Ru" + locked-name="RU"> - + @@ -352,10 +598,10 @@ - - + + @@ -383,6 +629,7 @@ + @@ -421,8 +668,8 @@ - - + + @@ -444,8 +691,8 @@ - - + + @@ -484,7 +731,6 @@ - @@ -498,7 +744,168 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index d514ca0..cce4a1a 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -32,13 +32,13 @@ android:key="autocorrect" android:title="@string/preferences_auto_correct" /> + android:defaultValue="@string/cycle_speed_default" + android:entries="@array/cycle_speed_labels" + android:entryValues="@array/cycle_speeds" + android:key="cycle_speed" + android:title="@string/preferences_cycle_speed" />