Basic visual keyboard using deprecated APIs, sticky shift and alt

This commit is contained in:
2024-10-07 22:05:05 +02:00
parent 6c405d963f
commit 483c83aee9
10 changed files with 316 additions and 241 deletions
+10 -4
View File
@@ -6,8 +6,14 @@ features a voice input key, a language change key, an emoji key, a menu, and ext
This choice of symbols is strange, because all of those keys can be easily accessed using your right
hand on the Alt key, and the left hand on any of those symbols (they are available on the left half
of the keyboard). What is obstructed by the right hand though is the numbers. This is what the
symbol bar should contain.
symbol bar should contain, and it should look like this:
Additionally, it should contain some symbols that are unavailable on the physical keyboard. That is
the symbols "$", "%", "&", "=". However, as those are not used as often as numbers, they should be
hidden away in a collapsed menu along with more, less frequently used symbols.
(1) (2) (3) (4) (5) (6) (7) (8) (9) (0)
When pressing the shift key, the number bar should change into a symbol bar. This will contain all
the symbols not found on the physical keyboard. It'll look like this (likely the most needed symbols
are in the middle):
(^) (\) (|) (=) (%) (&) ($) (<) (>) (MORE)
When pressing more, additional less-used symbols will be shown.
+1 -2
View File
@@ -12,8 +12,6 @@ android {
targetSdk 34
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@@ -28,3 +26,4 @@ android {
}
}
+1 -1
View File
@@ -9,7 +9,7 @@
<service
android:name="TitanboardIME"
android:directBootAware="true"
android:exported="true"
android:exported="false"
android:label="@string/ime_label"
android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
@@ -1,10 +1,10 @@
package cfpi_fpsi.eu.titanboard;
import android.inputmethodservice.InputMethodService;
import android.util.Log;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import org.xmlpull.v1.XmlPullParser;
@@ -13,71 +13,68 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.HashMap;
public class TitanboardIME extends InputMethodService {
private HashMap<Integer, int[]> keymap;
public class TitanboardIME extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
private HashMap<Integer, int[]> mKeymap;
private boolean mShiftOn = false;
private boolean mAltOn = false;
private KeyboardView mInputView;
private Keyboard mKeyboard;
@Override
public void onCreate() {
super.onCreate();
keymap = new HashMap<>();
// We load the keymap from the XML file into a variable
XmlPullParser parser = getResources().getXml(getResources()
.getIdentifier("keymap_titan", "xml", getPackageName()));
int code = 0;
int value = 0;
int alt = 0;
mKeymap = new HashMap<>();
XmlPullParser parser = getResources().getXml(R.xml.keymap_titan);
int code = 0, value = 0, valueAlt = 0;
try {
while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
switch (parser.getEventType()) {
case XmlPullParser.START_TAG:
if (parser.getName().equals("key")) {
for (int i = 0; i < parser.getAttributeCount(); ++i) {
switch (parser.getAttributeName(i)) {
case "code":
code = Integer.parseInt(parser.getAttributeValue(i));
Log.d("STATE", "KeyCode: " + code);
break;
case "value":
value = Integer.parseInt(String.valueOf(parser.getAttributeValue(i).codePointAt(0)));
break;
case "alt":
alt = Integer.parseInt(String.valueOf(parser.getAttributeValue(i).codePointAt(0)));
break;
}
}
int type = parser.getEventType();
if (type == XmlPullParser.START_TAG && parser.getName().equals("key")) {
for (int i = 0; i < parser.getAttributeCount(); ++i) {
String attr = parser.getAttributeName(i);
if (attr.equals("code")) {
code = Integer.parseInt(parser.getAttributeValue(i));
} else if (attr.equals("value")) {
value = Integer.parseInt(String.valueOf(parser.getAttributeValue(i).codePointAt(0)));
} else if (attr.equals("valueAlt")) {
valueAlt = Integer.parseInt(String.valueOf(parser.getAttributeValue(i).codePointAt(0)));
}
break;
case XmlPullParser.END_TAG:
if (parser.getName().equals("key")) {
Log.d("STATE", "Adding KeyCode " + code + " which corresponds to: " + value + " and " + alt);
keymap.put(code, new int[] { value, alt });
}
break;
default:
break;
}
} else if (type == XmlPullParser.END_TAG && parser.getName().equals("key")) {
mKeymap.put(code, new int[]{value, valueAlt});
}
parser.next();
}
} catch (XmlPullParserException e) {
throw new RuntimeException(e);
} catch (IOException e) {
} catch (XmlPullParserException | IOException e) {
throw new RuntimeException(e);
}
}
@Override
public View onCreateInputView() {
return getLayoutInflater().inflate(R.layout.input, null);
public void onInitializeInterface() {
mInputView = (KeyboardView) getLayoutInflater().inflate(R.layout.keyboard_symbol, null);
mKeyboard = new Keyboard(this, R.xml.keylayout_symbol);
mInputView.setKeyboard(mKeyboard);
mInputView.setOnKeyboardActionListener(this);
}
@Override
public boolean onEvaluateFullscreenMode() {
// This is to override the default behaviour, which seems to do more than detect landscape
// mode.
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
InputConnection conn = getCurrentInputConnection();
EditorInfo info = getCurrentInputEditorInfo();
if (conn == null || info == null) {
if (conn == null) {
return false;
}
@@ -94,20 +91,37 @@ public class TitanboardIME extends InputMethodService {
return false;
// If it's the backspace key, we remove one character.
case KeyEvent.KEYCODE_DEL:
conn.deleteSurroundingText(1, 0);
return true;
// We suppress the alt keys so the system cannot use them.
CharSequence selection = conn.getSelectedText(0);
if (selection != null) {
// This IME won't handle it, and in turn the whole selection gets deleted.
return false;
} else {
conn.deleteSurroundingText(1, 0);
return true;
}
case KeyEvent.KEYCODE_ALT_LEFT:
case KeyEvent.KEYCODE_ALT_RIGHT:
mAltOn = !mAltOn;
mShiftOn = false;
return true;
case KeyEvent.KEYCODE_SHIFT_LEFT:
case KeyEvent.KEYCODE_SHIFT_RIGHT:
mShiftOn = !mShiftOn;
mAltOn = false;
return true;
case KeyEvent.KEYCODE_SPACE:
conn.commitText(" ", 1);
return true;
default:
// And we send the character to the app.
int[] key = keymap.get(keyCode);
int[] key = mKeymap.get(keyCode);
if (key != null) {
if (event.isAltPressed()) {
if (mAltOn) {
conn.commitText(new String(Character.toChars(key[1])), 1);
} else if (event.isShiftPressed()) {
mAltOn = false;
} else if (mShiftOn) {
conn.commitText(new String(Character.toChars(key[0])).toUpperCase(), 1);
mShiftOn = false;
} else {
conn.commitText(new String(Character.toChars(key[0])), 1);
}
@@ -117,4 +131,53 @@ public class TitanboardIME extends InputMethodService {
}
}
}
@Override
public View onCreateInputView() {
return mInputView;
}
@Override
public void onPress(int primaryCode) {
}
@Override
public void onRelease(int primaryCode) {
}
@Override
public void onKey(int primaryCode, int[] keyCodes) {
InputConnection conn = getCurrentInputConnection();
if (conn != null) {
conn.commitText(String.valueOf((char) primaryCode), 1);
}
}
@Override
public void onText(CharSequence text) {
}
@Override
public void swipeLeft() {
}
@Override
public void swipeRight() {
}
@Override
public void swipeDown() {
}
@Override
public void swipeUp() {
}
}
-155
View File
@@ -1,155 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#E8EAF6"
android:gravity="center_vertical"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<Button
android:id="@+id/button12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button" />
<Button
android:id="@+id/button13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button" />
<Button
android:id="@+id/button14"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<Button
android:id="@+id/button"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="1"
android:textSize="14sp" />
<Button
android:id="@+id/button2"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="2"
android:textSize="14sp" />
<Button
android:id="@+id/button3"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="3"
android:textSize="14sp" />
<Button
android:id="@+id/button4"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="4"
android:textSize="14sp" />
<Button
android:id="@+id/button5"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="5"
android:textSize="14sp" />
<Button
android:id="@+id/button6"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="6"
android:textSize="14sp" />
<Button
android:id="@+id/button7"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="7"
android:textSize="14sp" />
<Button
android:id="@+id/button8"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="8"
android:textSize="14sp" />
<Button
android:id="@+id/button9"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="9"
android:textSize="14sp" />
<Button
android:id="@+id/button10"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="0"
android:textSize="14sp" />
<Button
android:id="@+id/button11"
style="@android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:text="M"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.inputmethodservice.KeyboardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
+2 -1
View File
@@ -1,4 +1,5 @@
<resources>
<string name="app_name">Titanboard</string>
<string name="ime_label">Titanboard Input Method</string>
<string name="ime_label">Titanboard</string>
<string name="more_label">More…</string>
</resources>
+74
View File
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyHeight="60dp"
android:horizontalGap="0px"
android:verticalGap="0px">
<Row>
<Key
android:codes="94"
android:keyLabel="^"
android:keyEdgeFlags="left" />
<Key
android:codes="92"
android:keyLabel="\\" />
<Key
android:codes="124"
android:keyLabel="|" />
<Key
android:codes="61"
android:keyLabel="=" />
<Key
android:codes="37"
android:keyLabel="%" />
<Key
android:codes="38"
android:keyLabel="&amp;" />
<Key
android:codes="36"
android:keyLabel="$" />
<Key
android:codes="60"
android:keyLabel="&lt;" />
<Key
android:codes="62"
android:keyLabel="&gt;" />
<Key
android:codes="59"
android:keyLabel=";"
android:keyEdgeFlags="right" />
</Row>
<Row>
<Key
android:codes="49"
android:keyLabel="1"
android:keyEdgeFlags="left" />
<Key
android:codes="50"
android:keyLabel="2" />
<Key
android:codes="51"
android:keyLabel="3" />
<Key
android:codes="52"
android:keyLabel="4" />
<Key
android:codes="53"
android:keyLabel="5" />
<Key
android:codes="54"
android:keyLabel="6" />
<Key
android:codes="55"
android:keyLabel="7" />
<Key
android:codes="56"
android:keyLabel="8" />
<Key
android:codes="57"
android:keyLabel="9" />
<Key
android:codes="48"
android:keyLabel="0"
android:keyEdgeFlags="right" />
</Row>
</Keyboard>
+104 -26
View File
@@ -1,29 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<keymap>
<key code="29" value="a" alt="@"/>
<key code="30" value="b" alt="7"/>
<key code="31" value="c" alt=","/>
<key code="32" value="d" alt="&quot;"/>
<key code="33" value="e" alt="_"/>
<key code="34" value="f" alt="+"/>
<key code="35" value="g" alt="*"/>
<key code="36" value="h" alt="#"/>
<key code="37" value="i" alt="2"/>
<key code="38" value="j" alt="4"/>
<key code="39" value="k" alt="5"/>
<key code="40" value="l" alt="6"/>
<key code="41" value="m" alt="9"/>
<key code="42" value="n" alt="8"/>
<key code="43" value="o" alt="3"/>
<key code="44" value="p" alt="0"/>
<key code="45" value="q" alt=":"/>
<key code="46" value="r" alt="-"/>
<key code="47" value="s" alt="&apos;"/>
<key code="48" value="t" alt="("/>
<key code="49" value="u" alt="1"/>
<key code="50" value="v" alt="."/>
<key code="51" value="w" alt="/"/>
<key code="52" value="x" alt="?"/>
<key code="53" value="y" alt=")"/>
<key code="54" value="z" alt="!"/>
<key
code="29"
value="a"
valueAlt="@" />
<key
code="30"
value="b"
valueAlt="7" />
<key
code="31"
value="c"
valueAlt="," />
<key
code="32"
value="d"
valueAlt="&quot;" />
<key
code="33"
value="e"
valueAlt="_" />
<key
code="34"
value="f"
valueAlt="+" />
<key
code="35"
value="g"
valueAlt="*" />
<key
code="36"
value="h"
valueAlt="#" />
<key
code="37"
value="i"
valueAlt="2" />
<key
code="38"
value="j"
valueAlt="4" />
<key
code="39"
value="k"
valueAlt="5" />
<key
code="40"
value="l"
valueAlt="6" />
<key
code="41"
value="m"
valueAlt="9" />
<key
code="42"
value="n"
valueAlt="8" />
<key
code="43"
value="o"
valueAlt="3" />
<key
code="44"
value="p"
valueAlt="0" />
<key
code="45"
value="q"
valueAlt=":" />
<key
code="46"
value="r"
valueAlt="-" />
<key
code="47"
value="s"
valueAlt="&apos;" />
<key
code="48"
value="t"
valueAlt="(" />
<key
code="49"
value="u"
valueAlt="1" />
<key
code="50"
value="v"
valueAlt="." />
<key
code="51"
value="w"
valueAlt="/" />
<key
code="52"
value="x"
valueAlt="?" />
<key
code="53"
value="y"
valueAlt=")" />
<key
code="54"
value="z"
valueAlt="!" />
</keymap>
+6 -2
View File
@@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<input-method>
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
android:supportsSwitchingToNextInputMethod="true">
<subtype
android:imeSubtypeMode="keyboard"
android:isAsciiCapable="true"
android:label="Default" />
</input-method>