Define the bottom row separately

Avoid divergences when the bottom row is modified.
This commit is contained in:
Jules Aguillon 2022-02-07 00:55:32 +01:00
parent a76541458d
commit 1ff8526d24
10 changed files with 89 additions and 119 deletions

View File

@ -34,11 +34,4 @@
<key key0="n" key1="accent_tilde" key2="§" key4="!"/> <key key0="n" key1="accent_tilde" key2="§" key4="!"/>
<key width="2.0" key0="backspace" key2="delete"/> <key width="2.0" key0="backspace" key2="delete"/>
</row> </row>
<row height="0.95">
<key width="1.8" key0="ctrl" key2="meta" key3="switch_numeric"/>
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space"/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
<key width="1.8" key0="enter" key2="action"/>
</row>
</keyboard> </keyboard>

8
res/xml/bottom_row.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<row height="0.95">
<key width="1.8" key0="ctrl" key2="meta" key3="switch_numeric"/>
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space"/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
<key width="1.8" key0="enter" key2="action"/>
</row>

View File

@ -34,11 +34,4 @@
<key key0="v"/> <key key0="v"/>
<key key0="z" key2="-" key3="_"/> <key key0="z" key2="-" key3="_"/>
</row> </row>
<row height="0.95">
<key width="1.8" key0="ctrl" key2="meta" key3="switch_numeric"/>
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space"/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
<key width="1.8" key0="enter" key2="action"/>
</row>
</keyboard> </keyboard>

View File

@ -34,11 +34,4 @@
<key key0="м" key2="&quot;" key3="'"/> <key key0="м" key2="&quot;" key3="'"/>
<key width="1.5" key0="backspace" key2="delete"/> <key width="1.5" key0="backspace" key2="delete"/>
</row> </row>
<row height="0.95">
<key width="1.8" key0="ctrl" key2="meta" key3="switch_numeric"/>
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space"/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down"/>
<key width="1.8" key0="enter" key2="action"/>
</row>
</keyboard> </keyboard>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<keyboard> <keyboard bottom_row="false">
<row> <row>
<key width="0.75" key0="esc" key2="~" key4="!"/> <key width="0.75" key0="esc" key2="~" key4="!"/>
<key width="0.75" key0="(" key2="[" key4="{"/> <key width="0.75" key0="(" key2="[" key4="{"/>

View File

@ -34,11 +34,4 @@
<key key0="m" key2="&quot;" key3="'"/> <key key0="m" key2="&quot;" key3="'"/>
<key width="1.5" key0="backspace" key2="delete"/> <key width="1.5" key0="backspace" key2="delete"/>
</row> </row>
<row height="0.95">
<key width="1.8" key0="ctrl" key2="meta" key3="switch_numeric"/>
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space"/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
<key width="1.8" key0="enter" key2="action"/>
</row>
</keyboard> </keyboard>

View File

@ -34,11 +34,4 @@
<key key0="m" key1="'" key2="&quot;" key3="," key4="\?" /> <key key0="m" key1="'" key2="&quot;" key3="," key4="\?" />
<key width="1.5" key0="backspace" key2="delete" /> <key width="1.5" key0="backspace" key2="delete" />
</row> </row>
<row height="0.95">
<key width="1.8" key0="ctrl" key2="meta" key3="switch_numeric"/>
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config" />
<key width="4.0" key0="space" />
<key width="1.2" key0="." key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
<key width="1.8" key0="enter" key2="action" />
</row>
</keyboard> </keyboard>

View File

@ -34,11 +34,4 @@
<key key0="m" key1="_" /> <key key0="m" key1="_" />
<key width="1.5" key0="backspace" key2="delete"/> <key width="1.5" key0="backspace" key2="delete"/>
</row> </row>
<row height="0.95">
<key width="1.8" key0="ctrl" key2="meta" key3="switch_numeric"/>
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space"/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
<key width="1.8" key0="enter" key2="action"/>
</row>
</keyboard> </keyboard>

View File

@ -1,31 +1,24 @@
package juloo.keyboard2; package juloo.keyboard2;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.inputmethodservice.InputMethodService; import android.inputmethodservice.InputMethodService;
import android.os.Build.VERSION; import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.text.InputType;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.InputType;
import android.view.ContextThemeWrapper;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import android.view.ContextThemeWrapper;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewParent; import android.view.ViewParent;
import android.util.Log;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map;
public class Keyboard2 extends InputMethodService public class Keyboard2 extends InputMethodService
implements SharedPreferences.OnSharedPreferenceChangeListener implements SharedPreferences.OnSharedPreferenceChangeListener
@ -36,17 +29,9 @@ public class Keyboard2 extends InputMethodService
private Config _config; private Config _config;
private Map<Integer, KeyboardData> _layoutCache = new HashMap<Integer, KeyboardData>();
private KeyboardData getLayout(int resId) private KeyboardData getLayout(int resId)
{ {
KeyboardData l = _layoutCache.get(resId); return KeyboardData.load(getResources(), resId);
if (l == null)
{
l = KeyboardData.parse(getResources().getXml(resId));
_layoutCache.put(resId, l);
}
return l;
} }
@Override @Override

View File

@ -1,8 +1,11 @@
package juloo.keyboard2; package juloo.keyboard2;
import android.content.res.Resources;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
class KeyboardData class KeyboardData
{ {
@ -12,7 +15,58 @@ class KeyboardData
/* Total height of the keyboard. Unit is abstract. */ /* Total height of the keyboard. Unit is abstract. */
public final float keysHeight; public final float keysHeight;
public KeyboardData(List<Row> rows_) public KeyboardData replaceKeys(MapKeys f)
{
ArrayList<Row> rows_ = new ArrayList<Row>();
for (Row r : rows)
rows_.add(r.replaceKeys(f));
return new KeyboardData(rows_);
}
private static Row _bottomRow = null;
private static Map<Integer, KeyboardData> _layoutCache = new HashMap<Integer, KeyboardData>();
public static KeyboardData load(Resources res, int id)
{
KeyboardData l = _layoutCache.get(id);
if (l == null)
{
try
{
if (_bottomRow == null)
_bottomRow = parse_bottom_row(res.getXml(R.xml.bottom_row));
l = parse_keyboard(res.getXml(id));
_layoutCache.put(id, l);
}
catch (Exception e)
{
e.printStackTrace();
}
}
return l;
}
private static KeyboardData parse_keyboard(XmlResourceParser parser) throws Exception
{
if (!expect_tag(parser, "keyboard"))
throw new Exception("Empty layout file");
boolean bottom_row = parser.getAttributeBooleanValue(null, "bottom_row", true);
ArrayList<Row> rows = new ArrayList<Row>();
while (expect_tag(parser, "row"))
rows.add(Row.parse(parser));
if (bottom_row)
rows.add(_bottomRow);
return new KeyboardData(rows);
}
private static Row parse_bottom_row(XmlResourceParser parser) throws Exception
{
if (!expect_tag(parser, "row"))
throw new Exception("Failed to parse bottom row");
return Row.parse(parser);
}
protected KeyboardData(List<Row> rows_)
{ {
float kw = 0.f; float kw = 0.f;
float kh = 0.f; float kh = 0.f;
@ -26,45 +80,6 @@ class KeyboardData
keysHeight = kh; keysHeight = kh;
} }
public static KeyboardData parse(XmlResourceParser parser)
{
ArrayList<Row> rows = new ArrayList<Row>();
try
{
int status;
while (parser.next() != XmlResourceParser.START_TAG)
continue ;
if (!parser.getName().equals("keyboard"))
throw new Exception("Unknow tag: " + parser.getName());
while ((status = parser.next()) != XmlResourceParser.END_DOCUMENT)
{
if (status == XmlResourceParser.START_TAG)
{
String tag = parser.getName();
if (tag.equals("row"))
rows.add(Row.parse(parser));
else
throw new Exception("Unknow keyboard tag: " + tag);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return new KeyboardData(rows);
}
public KeyboardData replaceKeys(MapKeys f)
{
ArrayList<Row> rows_ = new ArrayList<Row>();
for (Row r : rows)
rows_.add(r.replaceKeys(f));
return new KeyboardData(rows_);
}
public static class Row public static class Row
{ {
public final List<Key> keys; public final List<Key> keys;
@ -75,7 +90,7 @@ class KeyboardData
/* Total width of very keys. Unit is abstract. */ /* Total width of very keys. Unit is abstract. */
private final float keysWidth; private final float keysWidth;
public Row(List<Key> keys_, float h, float s) protected Row(List<Key> keys_, float h, float s)
{ {
float kw = 0.f; float kw = 0.f;
for (Key k : keys_) kw += k.width + k.shift; for (Key k : keys_) kw += k.width + k.shift;
@ -91,17 +106,8 @@ class KeyboardData
int status; int status;
float h = parser.getAttributeFloatValue(null, "height", 1f); float h = parser.getAttributeFloatValue(null, "height", 1f);
float shift = parser.getAttributeFloatValue(null, "shift", 0f); float shift = parser.getAttributeFloatValue(null, "shift", 0f);
while ((status = parser.next()) != XmlResourceParser.END_TAG) while (expect_tag(parser, "key"))
{
if (status == XmlResourceParser.START_TAG)
{
String tag = parser.getName();
if (tag.equals("key"))
keys.add(Key.parse(parser)); keys.add(Key.parse(parser));
else
throw new Exception("Unknow row tag: " + tag);
}
}
return new Row(keys, h, shift); return new Row(keys, h, shift);
} }
@ -134,7 +140,7 @@ class KeyboardData
/* Put keys 1 to 4 on the edges instead of the corners. */ /* Put keys 1 to 4 on the edges instead of the corners. */
public final boolean edgekeys; public final boolean edgekeys;
public Key(KeyValue k0, KeyValue k1, KeyValue k2, KeyValue k3, KeyValue k4, float w, float s, boolean e) protected Key(KeyValue k0, KeyValue k1, KeyValue k2, KeyValue k3, KeyValue k4, float w, float s, boolean e)
{ {
key0 = k0; key0 = k0;
key1 = k1; key1 = k1;
@ -146,11 +152,6 @@ class KeyboardData
edgekeys = e; edgekeys = e;
} }
public Key(KeyValue k0, KeyValue k1, KeyValue k2, KeyValue k3, KeyValue k4, float w, float s)
{
this(k0, k1, k2, k3, k4, w, s, false);
}
public static Key parse(XmlResourceParser parser) throws Exception public static Key parse(XmlResourceParser parser) throws Exception
{ {
KeyValue k0 = KeyValue.getKeyByName(parser.getAttributeValue(null, "key0")); KeyValue k0 = KeyValue.getKeyByName(parser.getAttributeValue(null, "key0"));
@ -236,4 +237,22 @@ class KeyboardData
return k; return k;
} }
} }
/** Parsing utils */
/** Returns [false] on [END_DOCUMENT] or [END_TAG], [true] otherwise. */
private static boolean expect_tag(XmlResourceParser parser, String name) throws Exception
{
int status;
do
{
status = parser.next();
if (status == XmlResourceParser.END_DOCUMENT || status == XmlResourceParser.END_TAG)
return false;
}
while (status != XmlResourceParser.START_TAG);
if (!parser.getName().equals(name))
throw new Exception("Unknow tag: " + parser.getName());
return true;
}
} }