Support for down to Android 1.5 (Cupcake)
This commit is contained in:
+1
-1
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
@@ -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,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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user