From 989752669ab4918e448eba099d9895415e5b2ac4 Mon Sep 17 00:00:00 2001 From: Emil Kosz Date: Wed, 23 Oct 2024 20:21:23 +0200 Subject: [PATCH] Support for down to Android 1.5 (Cupcake) --- app/build.gradle | 2 +- .../cfpi_fpsi/eu/titanboard/InputMethod.java | 41 ++++++++----- .../cfpi_fpsi/eu/titanboard/InputView.java | 25 -------- .../eu/titanboard/KeymapManager.java | 4 +- .../eu/titanboard/SettingsActivity.java | 3 - .../cfpi_fpsi/eu/titanboard/SymbolCycler.java | 12 +++- .../cfpi_fpsi/eu/titanboard/SymbolsView.java | 35 ----------- app/src/main/res/drawable/icon.xml | 2 - app/src/main/res/layout/input.xml | 59 +------------------ app/src/main/res/layout/symbols.xml | 56 ------------------ app/src/main/res/values/styles.xml | 30 ++++------ app/src/main/res/xml/method.xml | 11 +++- 12 files changed, 59 insertions(+), 221 deletions(-) delete mode 100644 app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolsView.java delete mode 100644 app/src/main/res/layout/symbols.xml diff --git a/app/build.gradle b/app/build.gradle index 5f80b93..ec2596b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ android { defaultConfig { applicationId "cfpi_fpsi.eu.titanboard" - minSdk 19 + minSdk 3 //noinspection OldTargetApi targetSdk 34 versionCode 29 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 2924447..e378353 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/InputMethod.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/InputMethod.java @@ -22,11 +22,9 @@ package cfpi_fpsi.eu.titanboard; import android.annotation.SuppressLint; import android.inputmethodservice.InputMethodService; import android.os.Vibrator; -import android.text.TextUtils; import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputConnection; import java.util.ArrayList; import java.util.regex.Matcher; @@ -84,8 +82,9 @@ public class InputMethod extends InputMethodService { return true; } return false; - case KeyEvent.KEYCODE_ENTER: case KeyEvent.KEYCODE_DEL: + case KeyEvent.KEYCODE_ENTER: + mMetaKeyManager.adjustMetaStateAfterKeypress(); return false; case KeyEvent.KEYCODE_SPACE: handleSpacebar(event); @@ -104,7 +103,7 @@ public class InputMethod extends InputMethodService { mSymbolPressed = keyCode; mLastKeyTime = event.getEventTime(); mSymbolCycler.stopCycling(); - mSymbolCycler.startCycling(symbols, getCurrentInputConnection()); + mSymbolCycler.prepareForCycling(symbols, getCurrentInputConnection()); if (!mSettings.isCyclingWithSpaceEnabled()) { mSymbolCycler.startAutomaticCycling(); } @@ -115,8 +114,6 @@ public class InputMethod extends InputMethodService { } public void handleSpacebar(KeyEvent event) { - InputConnection conn = getCurrentInputConnection(); - if (mSettings.isCyclingWithSpaceEnabled() && mSymbolPressed != -1 && event.getEventTime() - mLastKeyTime > 200) { mSymbolCycler.cycle(); @@ -126,20 +123,20 @@ public class InputMethod extends InputMethodService { if (mSettings.isAutoPeriodsEnabled()) { String text = getTextBeforeCursor(2); - if (!text.isEmpty()) { + if (text.length() != 0) { Pattern pattern = Pattern.compile("[^\\.… ]+ $"); Matcher matcher = pattern.matcher(text); if (matcher.find()) { // InputConnection.replaceSelection needs a higher API, so we just do exactly // what it does to support more devices. - conn.finishComposingText(); - conn.setSelection(mCurrentCursorPosition - 1, mCurrentCursorPosition); - conn.commitText(".", 1); + getCurrentInputConnection().finishComposingText(); + getCurrentInputConnection().setSelection(mCurrentCursorPosition - 1, mCurrentCursorPosition); + getCurrentInputConnection().commitText(".", 1); } } } - conn.commitText(" ", 1); + getCurrentInputConnection().commitText(" ", 1); mMetaKeyManager.adjustMetaStateAfterKeypress(); } @@ -147,10 +144,14 @@ public class InputMethod extends InputMethodService { if (mSymbolPressed == keyCode) { mSymbolPressed = -1; mSymbolCycler.stopCycling(); - mInputView.updateSymbolsView(null, 0); + getCurrentInputConnection().finishComposingText(); + } + + // TODO: Not ideal. Should be handled on key down ideally. + if (keyCode == KeyEvent.KEYCODE_DEL) { + detectAutoCapitalization(); } - getCurrentInputConnection().finishComposingText(); mMetaKeyManager.updateMetaStateUp(keyCode, event); mInputView.updateStateText(); @@ -173,10 +174,19 @@ public class InputMethod extends InputMethodService { if (!mSettings.isAutoCapsEnabled()) { return; } - - if (getCurrentInputConnection().getCursorCapsMode(TextUtils.CAP_MODE_SENTENCES) > 0) { + // Get a bunch of text, run a regex through it, and bam. Is there a better way to do this? + String text = getTextBeforeCursor(16); + if (text.length() == 0) { mMetaKeyManager.getShift().setLatched(true); mInputView.updateStateText(); + } else { + // If, on the other hand, we have some characters before the cursor, we scan. + Pattern pattern = Pattern.compile("[\\.…\\!\\?] +$"); + Matcher matcher = pattern.matcher(text); + if (matcher.find()) { + mMetaKeyManager.getShift().setLatched(true); + mInputView.updateStateText(); + } } } @@ -188,7 +198,6 @@ public class InputMethod extends InputMethodService { @Override public void onStartInput(EditorInfo info, boolean restarting) { super.onStartInput(info, restarting); - detectAutoCapitalization(); mKeymapManager.checkCurrentKeymap(mSettings.getSelectedKeymaps()); mInputView.updateStateText(); 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 3f73e67..550b8e5 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/InputView.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/InputView.java @@ -24,16 +24,11 @@ import android.content.Intent; import android.graphics.Paint; import android.util.AttributeSet; import android.widget.Button; -import android.widget.LinearLayout; import android.widget.RelativeLayout; -import android.widget.TextView; - -import java.util.ArrayList; public class InputView extends RelativeLayout { private final InputMethod mInputMethod; private Button mStateButton; - private LinearLayout mMultiList; public InputView(Context context, AttributeSet attrs) { super(context, attrs, 0); @@ -43,7 +38,6 @@ public class InputView extends RelativeLayout { @Override protected void onFinishInflate() { super.onFinishInflate(); - mMultiList = findViewById(R.id.multi_list); mStateButton = findViewById(R.id.input_state); mStateButton.setOnClickListener(button -> { @@ -104,23 +98,4 @@ public class InputView extends RelativeLayout { mStateButton.setText(keymapManager.getCurrentKeymap().getCode()); } - - public void updateSymbolsView(ArrayList symbols, int index) { - for (int i = 0; i < mMultiList.getChildCount(); ++i) { - TextView view = (TextView) mMultiList.getChildAt(i); - view.setText(""); - } - - if (symbols != null) { - for (int i = 0; i < Math.min(mMultiList.getChildCount(), symbols.size()); ++i) { - TextView view = (TextView) mMultiList.getChildAt(i); - view.setText(symbols.get(i)); - if (i == index) { - view.setTextAppearance(getContext(), R.style.InputViewSymbolSelected); - } else { - view.setTextAppearance(getContext(), R.style.InputViewSymbol); - } - } - } - } } diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/KeymapManager.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/KeymapManager.java index 40a1512..6c00b6b 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/KeymapManager.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/KeymapManager.java @@ -149,7 +149,9 @@ public class KeymapManager { mCurrentKeymap = mKeymaps.get(selectedKeymaps.get(index)); } - public Keymap getCurrentKeymap() { return mCurrentKeymap; } + public Keymap getCurrentKeymap() { + return mCurrentKeymap; + } public static class Keymap extends HashMap { private String mCode; // A two-letter code for when the keyboard is lowercase. diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/SettingsActivity.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/SettingsActivity.java index d6950c6..dedbffe 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/SettingsActivity.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/SettingsActivity.java @@ -22,8 +22,6 @@ package cfpi_fpsi.eu.titanboard; import android.os.Bundle; import android.preference.PreferenceActivity; -import java.util.Objects; - /** * @noinspection deprecation */ @@ -32,6 +30,5 @@ public class SettingsActivity extends PreferenceActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); - Objects.requireNonNull(getActionBar()).setDisplayHomeAsUpEnabled(true); } } diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolCycler.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolCycler.java index f98c690..964cd76 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolCycler.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolCycler.java @@ -32,6 +32,7 @@ public class SymbolCycler extends Handler { private int mIndex; private ArrayList mSymbols; private InputConnection mConn; + private boolean hasCycled = false; public SymbolCycler(Context context) { super(Looper.getMainLooper()); @@ -39,7 +40,7 @@ public class SymbolCycler extends Handler { mRunnable = new SymbolCyclerRunnable(); } - public void startCycling(ArrayList symbols, InputConnection conn) { + public void prepareForCycling(ArrayList symbols, InputConnection conn) { mSymbols = symbols; mConn = conn; mIndex = 0; @@ -50,17 +51,22 @@ public class SymbolCycler extends Handler { } public void stopCycling() { + hasCycled = false; removeCallbacks(mRunnable); } public void cycle() { + if (!hasCycled) { + mConn.deleteSurroundingText(mSymbols.get(0).length(), 0); + hasCycled = true; + } + mIndex++; + if (mIndex == mSymbols.size()) { mIndex = 0; } - mInputMethod.mInputView.updateSymbolsView(mSymbols, mIndex); - mConn.setComposingRegion(mInputMethod.mCurrentCursorPosition - 1, mInputMethod.mCurrentCursorPosition); mConn.setComposingText(mSymbols.get(mIndex), 1); } diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolsView.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolsView.java deleted file mode 100644 index d3a0423..0000000 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/SymbolsView.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.util.AttributeSet; -import android.widget.RelativeLayout; - -public class SymbolsView extends RelativeLayout { - public SymbolsView(Context context, AttributeSet attrs) { - super(context, attrs, 0); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - } -} diff --git a/app/src/main/res/drawable/icon.xml b/app/src/main/res/drawable/icon.xml index 49eddee..5361c3b 100644 --- a/app/src/main/res/drawable/icon.xml +++ b/app/src/main/res/drawable/icon.xml @@ -6,8 +6,6 @@ android:viewportWidth="98" android:viewportHeight="200.67188"> diff --git a/app/src/main/res/layout/input.xml b/app/src/main/res/layout/input.xml index 354e856..a77209c 100644 --- a/app/src/main/res/layout/input.xml +++ b/app/src/main/res/layout/input.xml @@ -5,67 +5,14 @@ android:layout_height="wrap_content" android:layout_gravity="bottom"> - - - - - - - - - - - - - - - - - - - - - - - - - - -