Support for down to Android 1.5 (Cupcake)

This commit is contained in:
2024-10-23 20:24:06 +02:00
parent 681e2024de
commit 989752669a
12 changed files with 59 additions and 221 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ android {
defaultConfig {
applicationId "cfpi_fpsi.eu.titanboard"
minSdk 19
minSdk 3
//noinspection OldTargetApi
targetSdk 34
versionCode 29
@@ -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();
@@ -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<String> 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);
}
}
}
}
}
@@ -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<Integer, Key> {
private String mCode; // A two-letter code for when the keyboard is lowercase.
@@ -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);
}
}
@@ -32,6 +32,7 @@ public class SymbolCycler extends Handler {
private int mIndex;
private ArrayList<String> 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<String> symbols, InputConnection conn) {
public void prepareForCycling(ArrayList<String> 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);
}
@@ -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 <https://www.gnu.org/licenses/>.
*
*/
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();
}
}
-2
View File
@@ -6,8 +6,6 @@
android:viewportWidth="98"
android:viewportHeight="200.67188">
<group
android:scaleX="0.44929066"
android:scaleY="0.92"
android:translateX="26.984758"
android:translateY="8.0268755">
<group android:translateY="158.69531">
+3 -56
View File
@@ -5,67 +5,14 @@
android:layout_height="wrap_content"
android:layout_gravity="bottom">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="@id/input_state"
android:layout_alignBottom="@id/input_state"
android:layout_toStartOf="@id/input_state">
<LinearLayout
android:id="@+id/multi_list"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
style="@style/InputViewSymbol"
android:layout_height="wrap_content" />
<TextView
style="@style/InputViewSymbol"
android:layout_height="wrap_content" />
<TextView
style="@style/InputViewSymbol"
android:layout_height="wrap_content" />
<TextView
style="@style/InputViewSymbol"
android:layout_height="wrap_content" />
<TextView
style="@style/InputViewSymbol"
android:layout_height="wrap_content" />
<TextView
style="@style/InputViewSymbol"
android:layout_height="wrap_content" />
<TextView
style="@style/InputViewSymbol"
android:layout_height="wrap_content" />
<TextView
style="@style/InputViewSymbol"
android:layout_height="wrap_content" />
<TextView
style="@style/InputViewSymbol"
android:layout_height="wrap_content" />
<TextView
style="@style/InputViewSymbol"
android:layout_height="wrap_content" />
</LinearLayout>
</HorizontalScrollView>
<Button
android:id="@+id/input_state"
style="@style/InputViewButton"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:gravity="center"
android:text="@string/inputview_default_state" />
</cfpi_fpsi.eu.titanboard.InputView>
-56
View File
@@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ 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 <https://www.gnu.org/licenses/>.
~
-->
<cfpi_fpsi.eu.titanboard.SymbolsView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageView"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_below="@id/textView"
android:src="@drawable/triangle" />
<TextView
android:id="@+id/textView"
style="@style/SymbolsViewSymbol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:text="A" />
<TextView
android:id="@+id/textView2"
style="@style/SymbolsViewSymbol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/textView"
android:text="B" />
<TextView
android:id="@+id/textView3"
style="@style/SymbolsViewSymbol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/textView2"
android:text="C" />
</cfpi_fpsi.eu.titanboard.SymbolsView>
+10 -20
View File
@@ -10,35 +10,25 @@
<item name="android:background">@drawable/button</item>
<item name="android:textColor">#AAA</item>
<item name="android:textSize">18sp</item>
<item name="android:textAlignment">center</item>
<item name="android:gravity">center_vertical</item>
<item name="android:layout_width">48dp</item>
<item name="android:layout_height">48dp</item>
<item name="android:clickable">true</item>
</style>
<style name="InputViewSymbol">
<item name="android:textColor">#AAA</item>
<item name="android:textSize">18sp</item>
<item name="android:textAlignment">center</item>
<item name="android:layout_width">32dp</item>
<item name="android:layout_height">48dp</item>
<item name="android:layout_marginStart">8dp</item>
<item name="android:layout_weight">0</item>
<style name="SymbolCyclerViewBackground">
<item name="android:background">#AA333333</item>
</style>
<style name="SymbolCyclerViewSymbol">
<item name="android:textColor">#FFF</item>
<item name="android:textSize">16sp</item>
<item name="android:layout_margin">8dp</item>
<item name="android:layout_gravity">center_vertical</item>
</style>
<style name="InputViewSymbolSelected" parent="InputViewSymbol">
<item name="android:textColor">#DDD</item>
<style name="SymbolCyclerViewSymbolSelected" parent="SymbolCyclerViewSymbol">
<item name="android:textStyle">bold</item>
</style>
<style name="SymbolsViewSymbol">
<item name="android:background">#333</item>
<item name="android:textColor">#AAA</item>
<item name="android:textSize">16sp</item>
<item name="android:textAlignment">center</item>
<item name="android:padding">8dp</item>
<item name="android:layout_gravity">center_vertical</item>
</style>
</resources>
+8 -3
View File
@@ -1,9 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
android:settingsActivity="cfpi_fpsi.eu.titanboard.SettingsActivity"
android:supportsSwitchingToNextInputMethod="false">
xmlns:tools="http://schemas.android.com/tools"
android:settingsActivity="cfpi_fpsi.eu.titanboard.SettingsActivity">
<!-- Needed for higher Android version so it can be the only used input method.
None of these subtypes are actually used. -->
<subtype
android:imeSubtypeMode="keyboard"
tools:targetApi="honeycomb" />
<subtype
android:imeSubtypeMode="keyboard"
android:isAsciiCapable="true"
android:label="Default" />
tools:targetApi="kitkat" />
</input-method>