From 22d407c46a56231efc3d1192616d7923c9228bf1 Mon Sep 17 00:00:00 2001 From: Jules Aguillon Date: Sat, 3 Jun 2023 09:37:59 +0200 Subject: [PATCH] Per-layout shift modmap Specify the behavior of shift for a layout. This is intended for locales that use the same alphabet but have different capital letters (eg. Bengali). The modmap is defined like this: --- srcs/juloo.keyboard2/Keyboard2View.java | 13 ++++- srcs/juloo.keyboard2/KeyboardData.java | 72 +++++++++++++++++++++---- srcs/juloo.keyboard2/Pointers.java | 4 ++ 3 files changed, 77 insertions(+), 12 deletions(-) diff --git a/srcs/juloo.keyboard2/Keyboard2View.java b/srcs/juloo.keyboard2/Keyboard2View.java index cb93b3a..65098d0 100644 --- a/srcs/juloo.keyboard2/Keyboard2View.java +++ b/srcs/juloo.keyboard2/Keyboard2View.java @@ -123,6 +123,15 @@ public class Keyboard2View extends View public KeyValue modifyKey(KeyValue k, Pointers.Modifiers mods) { + if (_keyboard.modmap != null) + { + if (mods.has(KeyValue.Modifier.SHIFT)) + { + KeyValue km = _keyboard.modmap.shift.get(k); + if (km != null) + return km; + } + } return KeyModifier.modify(k, mods); } @@ -372,7 +381,7 @@ public class Keyboard2View extends View private void drawLabel(Canvas canvas, KeyValue kv, float x, float y, float keyH, boolean isKeyDown) { - kv = KeyModifier.modify(kv, _mods); + kv = modifyKey(kv, _mods); if (kv == null) return; float textSize = scaleTextSize(kv, _config.labelTextSize, keyH); @@ -388,7 +397,7 @@ public class Keyboard2View extends View { Paint.Align a = LABEL_POSITION_H[sub_index]; Vertical v = LABEL_POSITION_V[sub_index]; - kv = KeyModifier.modify(kv, _mods); + kv = modifyKey(kv, _mods); if (kv == null) return; float textSize = scaleTextSize(kv, _config.sublabelTextSize, keyH); diff --git a/srcs/juloo.keyboard2/KeyboardData.java b/srcs/juloo.keyboard2/KeyboardData.java index c008682..bc78f23 100644 --- a/srcs/juloo.keyboard2/KeyboardData.java +++ b/srcs/juloo.keyboard2/KeyboardData.java @@ -21,13 +21,15 @@ class KeyboardData public final float keysWidth; /** Total height of the keyboard. */ public final float keysHeight; + /** Might be null. */ + public final Modmap modmap; public KeyboardData mapKeys(MapKey f) { ArrayList rows_ = new ArrayList(); for (Row r : rows) rows_.add(r.mapKeys(f)); - return new KeyboardData(rows_, keysWidth); + return new KeyboardData(rows_, keysWidth, modmap); } /** Add keys from the given iterator into the keyboard. Extra keys are added @@ -47,7 +49,7 @@ class KeyboardData for (int c = 1; c <= 4; c++) addExtraKeys_to_row(rows, k, r, c); } - return new KeyboardData(rows, keysWidth); + return new KeyboardData(rows, keysWidth, modmap); } public KeyboardData addNumPad() @@ -70,14 +72,15 @@ class KeyboardData } extendedRows.add(new Row(keys, row.height, row.shift)); } - return new KeyboardData(extendedRows, compute_max_width(extendedRows)); + return new + KeyboardData(extendedRows, compute_max_width(extendedRows), modmap); } public KeyboardData addNumberRow() { ArrayList rows_ = new ArrayList(this.rows); rows_.add(0, number_row.updateWidth(keysWidth)); - return new KeyboardData(rows_, keysWidth); + return new KeyboardData(rows_, keysWidth, modmap); } public Key findKeyWithValue(KeyValue kv) @@ -173,12 +176,25 @@ class KeyboardData boolean add_bottom_row = attribute_bool(parser, "bottom_row", true); float specified_kw = attribute_float(parser, "width", 0f); ArrayList rows = new ArrayList(); - while (expect_tag(parser, "row")) - rows.add(Row.parse(parser)); + Modmap modmap = null; + while (next_tag(parser)) + { + switch (parser.getName()) + { + case "row": + rows.add(Row.parse(parser)); + break; + case "modmap": + modmap = Modmap.parse(parser); + break; + default: + throw new Exception("Unknown tag: " + parser.getName()); + } + } float kw = (specified_kw != 0f) ? specified_kw : compute_max_width(rows); if (add_bottom_row) rows.add(bottom_row.updateWidth(kw)); - return new KeyboardData(rows, kw); + return new KeyboardData(rows, kw, modmap); } private static float compute_max_width(List rows) @@ -196,12 +212,13 @@ class KeyboardData return Row.parse(parser); } - protected KeyboardData(List rows_, float kw) + protected KeyboardData(List rows_, float kw, Modmap mm) { float kh = 0.f; for (Row r : rows_) kh += r.height + r.shift; rows = rows_; + modmap = mm; keysWidth = kw; keysHeight = kh; } @@ -415,10 +432,37 @@ class KeyboardData } } + public static class Modmap + { + public final Map shift; + + public Modmap(Map s) + { + shift = s; + } + + public static Modmap parse(XmlPullParser parser) throws Exception + { + HashMap shift = new HashMap(); + while (expect_tag(parser, "shift")) + parse_mapping(parser, shift); + return new Modmap(shift); + } + + private static void parse_mapping(XmlPullParser parser, Map dst) throws Exception + { + KeyValue a = KeyValue.getKeyByName(parser.getAttributeValue(null, "a")); + KeyValue b = KeyValue.getKeyByName(parser.getAttributeValue(null, "b")); + while (parser.next() != XmlPullParser.END_TAG) + continue; + dst.put(a, b); + } + } + /** Parsing utils */ /** Returns [false] on [END_DOCUMENT] or [END_TAG], [true] otherwise. */ - private static boolean expect_tag(XmlPullParser parser, String name) throws Exception + private static boolean next_tag(XmlPullParser parser) throws Exception { int status; do @@ -428,8 +472,16 @@ class KeyboardData return false; } while (status != XmlPullParser.START_TAG); + return true; + } + + /** Returns [false] on [END_DOCUMENT] or [END_TAG], [true] otherwise. */ + private static boolean expect_tag(XmlPullParser parser, String name) throws Exception + { + if (!next_tag(parser)) + return false; if (!parser.getName().equals(name)) - throw new Exception("Unknow tag: " + parser.getName()); + throw new Exception("Unknown tag: " + parser.getName()); return true; } diff --git a/srcs/juloo.keyboard2/Pointers.java b/srcs/juloo.keyboard2/Pointers.java index c6d04ea..bcab202 100644 --- a/srcs/juloo.keyboard2/Pointers.java +++ b/srcs/juloo.keyboard2/Pointers.java @@ -478,6 +478,10 @@ public final class Pointers implements Handler.Callback public KeyValue.Modifier get(int i) { return _mods[_size - 1 - i]; } public int size() { return _size; } + public boolean has(KeyValue.Modifier m) + { + return (Arrays.binarySearch(_mods, 0, _size, m) >= 0); + } @Override public int hashCode() { return Arrays.hashCode(_mods); }