From 5e3a3f894b4d4b76f825eb150b9768f4d2a5b60a Mon Sep 17 00:00:00 2001 From: Tomasz Cielecki Date: Wed, 3 Apr 2024 23:46:39 +0200 Subject: [PATCH 1/9] Add Danish layout (#606) --- check_layout.output | 2 ++ res/values/layouts.xml | 3 +++ res/xml/method.xml | 1 + srcs/layouts/latn_qwerty_da.xml | 41 +++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 srcs/layouts/latn_qwerty_da.xml diff --git a/check_layout.output b/check_layout.output index 84e57055f..c63839970 100644 --- a/check_layout.output +++ b/check_layout.output @@ -83,6 +83,8 @@ Some keys contain whitespaces, unexpected: ́ # latn_qwerty_cz Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder 1 warnings +# latn_qwerty_da +0 warnings # latn_qwerty_es 0 warnings # latn_qwerty_gb diff --git a/res/values/layouts.xml b/res/values/layouts.xml index b4b5d0619..4bab9da20 100644 --- a/res/values/layouts.xml +++ b/res/values/layouts.xml @@ -32,6 +32,7 @@ latn_neo2 latn_qwerty_br latn_qwerty_cz + latn_qwerty_da latn_qwerty_es latn_qwerty_gb latn_qwerty_hu @@ -86,6 +87,7 @@ Neo 2 QWERTY (Brasileiro) QWERTY (Czech) + QWERTY (Danish) QWERTY (Español) QWERTY (UK) QWERTY (Magyar) @@ -140,6 +142,7 @@ @xml/latn_neo2 @xml/latn_qwerty_br @xml/latn_qwerty_cz + @xml/latn_qwerty_da @xml/latn_qwerty_es @xml/latn_qwerty_gb @xml/latn_qwerty_hu diff --git a/res/xml/method.xml b/res/xml/method.xml index 4bd2b3943..ca2c91771 100644 --- a/res/xml/method.xml +++ b/res/xml/method.xml @@ -7,6 +7,7 @@ + diff --git a/srcs/layouts/latn_qwerty_da.xml b/srcs/layouts/latn_qwerty_da.xml new file mode 100644 index 000000000..b1ba9573a --- /dev/null +++ b/srcs/layouts/latn_qwerty_da.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 78f85e52a2d2afdb9a466b2c27fbe1699a2a15c1 Mon Sep 17 00:00:00 2001 From: Jules Aguillon Date: Wed, 3 Apr 2024 23:55:38 +0200 Subject: [PATCH 2/9] Fix space key without a symbol The symbol on the space key was accidentally lost in be97364 when the string "\r" (Java's only way to write "\x0D") was not replaced by "\xE00D". --- srcs/juloo.keyboard2/KeyValue.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/srcs/juloo.keyboard2/KeyValue.java b/srcs/juloo.keyboard2/KeyValue.java index 2a00a596f..4462edf37 100644 --- a/srcs/juloo.keyboard2/KeyValue.java +++ b/srcs/juloo.keyboard2/KeyValue.java @@ -265,6 +265,11 @@ private static KeyValue charKey(String symbol, char c, int flags) return new KeyValue(symbol, Kind.Char, c, flags); } + private static KeyValue charKey(int symbol, char c, int flags) + { + return charKey(String.valueOf((char)symbol), c, flags); + } + private static KeyValue modifierKey(String symbol, Modifier m, int flags) { if (symbol.length() > 1) @@ -447,7 +452,7 @@ public static KeyValue getKeyByName(String name) /* Spaces */ case "\\t": return charKey("\\t", '\t', 0); // Send the tab character - case "space": return charKey("\r", ' ', FLAG_KEY_FONT | FLAG_SECONDARY); + case "space": return charKey(0xE00D, ' ', FLAG_KEY_FONT | FLAG_SMALLER_FONT | FLAG_GREYED); case "nbsp": return charKey("\u237d", '\u00a0', FLAG_SMALLER_FONT); /* bidi */ From 2684d1f04111f433c4ee21773a620bcc5c4f3734 Mon Sep 17 00:00:00 2001 From: JapanYoshi Date: Fri, 19 Apr 2024 21:38:35 +0900 Subject: [PATCH 3/9] =?UTF-8?q?Turkish:=20Correct=20shift=20behavior=20for?= =?UTF-8?q?=20=C4=B1=20and=20i=20(#615)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- srcs/layouts/latn_qwerty_tr.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/srcs/layouts/latn_qwerty_tr.xml b/srcs/layouts/latn_qwerty_tr.xml index 229a6d860..d2cf522c7 100644 --- a/srcs/layouts/latn_qwerty_tr.xml +++ b/srcs/layouts/latn_qwerty_tr.xml @@ -1,5 +1,9 @@ + + + + From 94b2ded843f482175ec91a4f7ab35fe1eacfa48d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8D=E4=BA=88?= Date: Wed, 24 Apr 2024 19:31:29 +0800 Subject: [PATCH 4/9] Update Simplified Chinese translation (#617) --- .../android/zh-CN/full_description.txt | 6 ++ .../android/zh-CN/short_description.txt | 1 + fastlane/metadata/android/zh-CN/title.txt | 1 + res/values-zh-rCN/strings.xml | 92 +++++++++---------- 4 files changed, 54 insertions(+), 46 deletions(-) create mode 100644 fastlane/metadata/android/zh-CN/full_description.txt create mode 100644 fastlane/metadata/android/zh-CN/short_description.txt create mode 100644 fastlane/metadata/android/zh-CN/title.txt diff --git a/fastlane/metadata/android/zh-CN/full_description.txt b/fastlane/metadata/android/zh-CN/full_description.txt new file mode 100644 index 000000000..674911162 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/full_description.txt @@ -0,0 +1,6 @@ +此应用的主要功能是,通过将按键沿四角滑动,您可以输入更多字符。 + +此应用最初是为使用 Termux 的程序员而设计的。 +现在对于日常使用来说也很完美。 + +此应用没有广告,不会发送任何网络请求,而且是开源的。 diff --git a/fastlane/metadata/android/zh-CN/short_description.txt b/fastlane/metadata/android/zh-CN/short_description.txt new file mode 100644 index 000000000..fd943f5d9 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/short_description.txt @@ -0,0 +1 @@ +适用于 Android 的轻量级、注重隐私的虚拟键盘。 diff --git a/fastlane/metadata/android/zh-CN/title.txt b/fastlane/metadata/android/zh-CN/title.txt new file mode 100644 index 000000000..c18b05b33 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/title.txt @@ -0,0 +1 @@ +Unexpected Keyboard diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 50c63bcdc..2ceff86ea 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -2,13 +2,13 @@ Unexpected Keyboard Unexpected Keyboard (debug) - - +此应用没有广告,不会发送任何网络请求,而且是开源的。" Unexpected Keyboard 设置 在竖屏模式下 在横屏模式下 @@ -19,9 +19,9 @@ This application contains no ads, doesn't make any network requests and is Open 调整按下的按键的透明度 系统设置 自定义布局 - - - + 添加其他布局 + 布局 %1$d:%2$s + 移除布局 自定义布局 显示数字小键盘 从不 @@ -33,24 +33,24 @@ This application contains no ads, doesn't make any network requests and is Open 大数字在上方 小数字在上方 选择要显示的按键 - - + 添加自定义按键 + 选择要添加到键盘的按键 输入 滑动触发距离 输入按键四角的符号需要滑动的距离 (%s) 长按到开始重复输入的时间 长按后每次重复输入的时间间隔 - 双击Shift键锁定大写 - 任何时候都可以长按修改键以锁定 + 双击 Shift 键锁定大写 + 任何时候长按修饰键均可将其锁定 行为 句首自动大写 在句子的开头自动按下Shift 切换到最近使用的键盘 切换键盘按钮的行为 - - - - + 自定义振动 + 振动强度 + 数字输入布局 + 输入数字、日期与电话号码时 样式 键盘下边距 键盘高度 @@ -65,8 +65,8 @@ This application contains no ads, doesn't make any network requests and is Open 黑色带边框 白色 白色带边框 - - + 沙漠 + 雨林 非常短 中(默认) @@ -74,40 +74,40 @@ This application contains no ads, doesn't make any network requests and is Open 非常长 按键的左右边距 按键的上下边距 - - - + 自定义边界 + 边界宽度 + 圆角半径 下一项 完成 前往 - 前一项 + 上一项 搜索 发送 启用键盘 - + 选择键盘 这是一个虚拟键盘软件。点击按钮进入系统设置,然后启用 Unexpected-Keyboard 即可使用。 - 这是一个免费且开源的软件。你可以在 Github 上找到源代码或者反馈 bug。 + 这是一个免费且开源的软件。你可以在 GitHub 上找到源代码或反馈问题。 启用键盘后,可以在这里测试效果: - - - - - - - - - - - - - - - - - - - - - - + 在这里测试 + 大写锁定 + Compose + 希腊 & 数学符号 + 切换键盘 + 语音输入 + 复制 + 粘贴 + 剪切 + 全选 + 分享文本 + 粘贴为纯文本 + 撤销 + 重做 + 次序标志 + 次序标志 + 上标 + 下标 + 上一页 + 下一页 + Home + End From 5386541db3d088351df70064337dfaf1ce42eac5 Mon Sep 17 00:00:00 2001 From: JapanYoshi Date: Thu, 25 Apr 2024 20:24:52 +0900 Subject: [PATCH 5/9] Add more accented characters to KeyModifier.java (#622) --- srcs/juloo.keyboard2/KeyModifier.java | 70 +++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/srcs/juloo.keyboard2/KeyModifier.java b/srcs/juloo.keyboard2/KeyModifier.java index a5fcde2ba..377f54fcb 100644 --- a/srcs/juloo.keyboard2/KeyModifier.java +++ b/srcs/juloo.keyboard2/KeyModifier.java @@ -559,14 +559,19 @@ public String apply(char c) switch (c) { case 'a': return "á"; + case 'c': return "ć"; case 'e': return "é"; case 'i': return "í"; case 'l': return "ĺ"; + case 'ń': return "ń"; case 'o': return "ó"; case 'r': return "ŕ"; case 's': return "ś"; case 'u': return "ú"; case 'y': return "ý"; + case 'z': return "ź"; + // used in Pinyin + case 'ü': return "ǘ"; // Combining diacritic case 'j': // Russian vowels @@ -584,15 +589,21 @@ public String apply(char c) { switch (c) { + case 'a': return "ǎ"; case 'c': return "č"; case 'd': return "ď"; case 'e': return "ě"; + case 'i': return "ǐ"; case 'l': return "ľ"; case 'n': return "ň"; + case 'o': return "ǒ"; case 'r': return "ř"; case 's': return "š"; case 't': return "ť"; + case 'u': return "ǔ"; case 'z': return "ž"; + // used in Pinyin + case 'ü': return "ǚ"; default: return map_dead_char(c, '\u02C7'); } } @@ -605,8 +616,16 @@ public String apply(char c) switch (c) { case 'c': return "ç"; - case 's': return "ş"; + case 'd': return "ḑ"; + case 'e': return "ȩ"; case 'g': return "ģ"; + case 'h': return "ḩ"; + case 'k': return "ķ"; + case 'l': return "ļ"; + case 'n': return "ņ"; + case 'r': return "ŗ"; + case 's': return "ş"; + case 't': return "ţ"; default: return map_dead_char(c, '\u00B8'); } } @@ -619,10 +638,16 @@ public String apply(char c) switch (c) { case 'a': return "â"; + case 'c': return "ĉ"; case 'e': return "ê"; + case 'g': return "ĝ"; + case 'h': return "ĥ"; case 'i': return "î"; + case 'j': return "ĵ"; case 'o': return "ô"; + case 'ŝ': return "ŝ"; case 'u': return "û"; + case 'z': return "ẑ"; default: return map_dead_char(c, '\u02C6'); } } @@ -634,7 +659,26 @@ public String apply(char c) { switch (c) { - case 'ė': return "ė"; + case 'a': return "ȧ"; + case 'b': return "ḃ"; + case 'c': return "ċ"; + case 'd': return "ḋ"; + case 'e': return "ė"; + case 'f': return "ḟ"; + case 'g': return "ġ"; + case 'h': return "ḣ"; + // Turkish ı / İ is handled elsewhere + case 'm': return "ṁ"; + case 'n': return "ṅ"; + case 'o': return "ȯ"; + case 'p': return "ṗ"; + case 'r': return "ṙ"; + case 's': return "ṡ"; + case 't': return "ṫ"; + case 'w': return "ẇ"; + case 'x': return "ẋ"; + case 'y': return "ẏ"; + case 'z': return "ż"; default: return map_dead_char(c, '\u02D9'); } } @@ -651,6 +695,8 @@ public String apply(char c) case 'i': return "ì"; case 'o': return "ò"; case 'u': return "ù"; + // used in Pinyin + case 'ü': return "ǜ"; default: return map_dead_char(c, '\u02CB'); } } @@ -665,7 +711,10 @@ public String apply(char c) case 'a': return "ā"; case 'e': return "ē"; case 'i': return "ī"; + case 'o': return "ō"; case 'u': return "ū"; + // used in Pinyin + case 'ü': return "ǖ"; default: return map_dead_char(c, '\u00AF'); } } @@ -683,6 +732,7 @@ public String apply(char c) case 'k': return "ķ"; case 'l': return "ļ"; case 'n': return "ņ"; + case 'o': return "ǫ"; case 'u': return "ų"; default: return map_dead_char(c, '\u02DB'); } @@ -709,8 +759,17 @@ public String apply(char c) switch (c) { case 'a': return "ã"; - case 'o': return "õ"; + case 'e': return "ẽ"; + case 'i': return "ĩ"; case 'n': return "ñ"; + case 'o': return "õ"; + case 'u': return "ũ"; + // Vietnamese + case 'ă': return "ẵ"; + case 'â': return "ẫ"; + case 'ê': return "ễ"; + case 'ơ': return "ỡ"; + case 'ư': return "ữ"; default: return map_dead_char(c, '\u02DC'); } } @@ -888,14 +947,17 @@ public String apply(char c) { switch (c) { + case '0': return "↔"; case '1': return "↙"; case '2': return "↓"; case '3': return "↘"; case '4': return "←"; + case '5': return "↕"; case '6': return "→"; case '7': return "↖"; case '8': return "↑"; case '9': return "↗"; + case '.': return "↵"; default: return null; } } @@ -1053,6 +1115,8 @@ public String apply(char c) } }; + // Used with Arabic despite the name; called "Hindi numerals" in Arabic + // map_char_numpad_devanagari is used in Hindi private static final Map_char map_char_numpad_hindu = new Map_char() { public String apply(char c) From c7ed2bcae915886b9d35bd19934f40816ef86b81 Mon Sep 17 00:00:00 2001 From: Jules Aguillon Date: Thu, 2 May 2024 11:58:44 +0200 Subject: [PATCH 6/9] Clear cache when changing layout Due to the modmap, the cache must be cleared when switching layout to or from a layout that contain a modmap. This is broken since 3f6b6fd23, which moves the modmap handling into KeyModifier. --- srcs/juloo.keyboard2/KeyModifier.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/srcs/juloo.keyboard2/KeyModifier.java b/srcs/juloo.keyboard2/KeyModifier.java index 377f54fcb..79531b277 100644 --- a/srcs/juloo.keyboard2/KeyModifier.java +++ b/srcs/juloo.keyboard2/KeyModifier.java @@ -13,7 +13,14 @@ public final class KeyModifier /** The optional modmap takes priority over modifiers usual behaviors. Set to [null] to disable. */ private static KeyboardData.Modmap _modmap = null; - public static void set_modmap(KeyboardData.Modmap mm) { _modmap = mm; } + public static void set_modmap(KeyboardData.Modmap mm) + { + // Clear the cache when switching to or from a layout that contain a modmap + // as the cache would otherwise override the modmap. + if (_modmap != null || mm != null) + _cache.clear(); + _modmap = mm; + } /** Modify a key according to modifiers. */ public static KeyValue modify(KeyValue k, Pointers.Modifiers mods) From 82e0840568655c8d71f2ac0c0ac5b1c18ef17845 Mon Sep 17 00:00:00 2001 From: alotbsol555 <159767443+alotbsol555@users.noreply.github.com> Date: Thu, 2 May 2024 12:09:39 +0200 Subject: [PATCH 7/9] allow for in (#626) --- srcs/juloo.keyboard2/KeyModifier.java | 6 ++++++ srcs/juloo.keyboard2/KeyboardData.java | 25 +++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/srcs/juloo.keyboard2/KeyModifier.java b/srcs/juloo.keyboard2/KeyModifier.java index 79531b277..3dc50a998 100644 --- a/srcs/juloo.keyboard2/KeyModifier.java +++ b/srcs/juloo.keyboard2/KeyModifier.java @@ -165,6 +165,12 @@ private static KeyValue apply_shift(KeyValue k) private static KeyValue apply_fn(KeyValue k) { + if (_modmap != null) + { + KeyValue mapped = _modmap.fn.get(k); + if (mapped != null) + return mapped; + } String name = null; switch (k.getKind()) { diff --git a/srcs/juloo.keyboard2/KeyboardData.java b/srcs/juloo.keyboard2/KeyboardData.java index c8dcd1358..25110efd2 100644 --- a/srcs/juloo.keyboard2/KeyboardData.java +++ b/srcs/juloo.keyboard2/KeyboardData.java @@ -515,18 +515,35 @@ public Key apply(Key k) public static class Modmap { public final Map shift; + public final Map fn; - public Modmap(Map s) + public Modmap(Map s, Map f) { shift = s; + fn = f; } 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); + HashMap fn = new HashMap(); + + while (next_tag(parser)) + { + switch (parser.getName()) + { + case "shift": + parse_mapping(parser, shift); + break; + case "fn": + parse_mapping(parser, fn); + break; + default: + throw error(parser, "Expecting tag or , got <" + parser.getName() + ">"); + } + } + + return new Modmap(shift, fn); } private static void parse_mapping(XmlPullParser parser, Map dst) throws Exception From 0f11a884185b832496fa5374ff03cfe61b91f9fb Mon Sep 17 00:00:00 2001 From: Jules Aguillon Date: Thu, 2 May 2024 19:31:48 +0200 Subject: [PATCH 8/9] More precise and faster spacebar slider (#593) * Make slider speed independent from swipe distance Swipe distances other than the default resulted in a slider that were not easy to control. * refactor: Add class Pointers.Sliding It holds the states and the code needed to make the slider work. 'Pointer.sliding' is set to [null] when sliding is not in progress. The implementation is changed not to depend on [downX] and [dx] but instead use the pointer's [x] coordinate directly. * Move the cursor further for faster slides In sliding mode, compute the speed of the pointer and use it to increase at which the cursor moves. * refactor: Separate kind for cursor movement keys This allows to define a key that moves the cursor more than one position at a time. This will be used to avoid lag during fast slider movements. * Reduce lag when sliding quickly on the spacebar Avoid sending key events in a loop while sliding quickly in a cursor movement key. Key of kind Cursor_move are "multiplied", meaning a single key event represents a movement of more than one position, reducing the number of key events sent. This is only for cursor move keys. --- srcs/juloo.keyboard2/Config.java | 2 +- srcs/juloo.keyboard2/KeyEventHandler.java | 3 +- srcs/juloo.keyboard2/KeyValue.java | 25 +++- srcs/juloo.keyboard2/Pointers.java | 133 ++++++++++++++++------ 4 files changed, 119 insertions(+), 44 deletions(-) diff --git a/srcs/juloo.keyboard2/Config.java b/srcs/juloo.keyboard2/Config.java index 70ccb94e3..9e9774bfa 100644 --- a/srcs/juloo.keyboard2/Config.java +++ b/srcs/juloo.keyboard2/Config.java @@ -132,7 +132,7 @@ public void refresh(Resources res) float swipe_scaling = Math.min(dm.widthPixels, dm.heightPixels) / 10.f * dpi_ratio; float swipe_dist_value = Float.valueOf(_prefs.getString("swipe_dist", "15")); swipe_dist_px = swipe_dist_value / 25.f * swipe_scaling; - slide_step_px = swipe_dist_px / 4.f; + slide_step_px = 0.2f * swipe_scaling; vibrate_custom = _prefs.getBoolean("vibrate_custom", false); vibrate_duration = _prefs.getInt("vibrate_duration", 20); longPressTimeout = _prefs.getInt("longpress_timeout", 600); diff --git a/srcs/juloo.keyboard2/KeyEventHandler.java b/srcs/juloo.keyboard2/KeyEventHandler.java index 01c430089..b6225f17b 100644 --- a/srcs/juloo.keyboard2/KeyEventHandler.java +++ b/srcs/juloo.keyboard2/KeyEventHandler.java @@ -94,6 +94,7 @@ public void key_up(KeyValue key, Pointers.Modifiers mods) case Compose_pending: _recv.set_compose_pending(true); break; + case Cursor_move: move_cursor(key.getCursorMove()); break; } update_meta_state(old_mods); } @@ -222,8 +223,6 @@ void handle_editing_key(KeyValue.Editing ev) case REPLACE: send_context_menu_action(android.R.id.replaceText); break; case ASSIST: send_context_menu_action(android.R.id.textAssist); break; case AUTOFILL: send_context_menu_action(android.R.id.autofill); break; - case CURSOR_LEFT: move_cursor(-1); break; - case CURSOR_RIGHT: move_cursor(1); break; } } diff --git a/srcs/juloo.keyboard2/KeyValue.java b/srcs/juloo.keyboard2/KeyValue.java index 4462edf37..da21d845f 100644 --- a/srcs/juloo.keyboard2/KeyValue.java +++ b/srcs/juloo.keyboard2/KeyValue.java @@ -71,8 +71,6 @@ public static enum Editing SHARE, ASSIST, AUTOFILL, - CURSOR_LEFT, - CURSOR_RIGHT, } public static enum Placeholder @@ -89,7 +87,8 @@ public static enum Placeholder public static enum Kind { Char, String, Keyevent, Event, Compose_pending, Modifier, Editing, - Placeholder + Placeholder, + Cursor_move // Value is encoded as a 16-bit integer } private static final int FLAGS_OFFSET = 19; @@ -196,6 +195,12 @@ public int getPendingCompose() return (_code & VALUE_BITS); } + /** Defined only when [getKind() == Kind.Cursor_move]. */ + public short getCursorMove() + { + return (short)(_code & VALUE_BITS); + } + /* Update the char and the symbol. */ public KeyValue withChar(char c) { @@ -325,6 +330,16 @@ private static KeyValue editingKey(int symbol, Editing action) return editingKey(String.valueOf((char)symbol), action, FLAG_KEY_FONT); } + /** A key that moves the cursor [d] times to the right. If [d] is negative, + it moves the cursor [abs(d)] times to the left. */ + public static KeyValue cursorMoveKey(int d) + { + int symbol = (d < 0) ? 0xE008 : 0xE006; + return new KeyValue(String.valueOf((char)symbol), Kind.Cursor_move, + ((short)d) & 0xFFFF, + FLAG_SPECIAL | FLAG_SECONDARY | FLAG_KEY_FONT); + } + /** A key that do nothing but has a unique ID. */ private static KeyValue placeholderKey(Placeholder id) { @@ -507,8 +522,8 @@ public static KeyValue getKeyByName(String name) case "pasteAsPlainText": return editingKey(0xE035, Editing.PASTE_PLAIN); case "undo": return editingKey(0xE036, Editing.UNDO); case "redo": return editingKey(0xE037, Editing.REDO); - case "cursor_left": return editingKey(0xE008, Editing.CURSOR_LEFT); - case "cursor_right": return editingKey(0xE006, Editing.CURSOR_RIGHT); + case "cursor_left": return cursorMoveKey(-1); + case "cursor_right": return cursorMoveKey(1); // These keys are not used case "replaceText": return editingKey("repl", Editing.REPLACE); case "textAssist": return editingKey(0xE038, Editing.ASSIST); diff --git a/srcs/juloo.keyboard2/Pointers.java b/srcs/juloo.keyboard2/Pointers.java index 4a1c2d037..4d6ff9ac5 100644 --- a/srcs/juloo.keyboard2/Pointers.java +++ b/srcs/juloo.keyboard2/Pointers.java @@ -139,7 +139,7 @@ public void onTouchUp(int pointerId) if (ptr.hasFlagsAny(FLAG_P_SLIDING)) { clearLatched(); - onTouchUp_sliding(ptr); + ptr.sliding.onTouchUp(ptr); return; } stopKeyRepeat(ptr); @@ -248,6 +248,11 @@ public void onTouchMove(float x, float y, int pointerId) Pointer ptr = getPtr(pointerId); if (ptr == null) return; + if (ptr.hasFlagsAny(FLAG_P_SLIDING)) + { + ptr.sliding.onTouchMove(ptr, x); + return; + } // The position in a IME windows is clampled to view. // For a better up swipe behaviour, set the y position to a negative value when clamped. @@ -255,12 +260,6 @@ public void onTouchMove(float x, float y, int pointerId) float dx = x - ptr.downX; float dy = y - ptr.downY; - if (ptr.hasFlagsAny(FLAG_P_SLIDING)) - { - onTouchMove_sliding(ptr, dx); - return; - } - float dist = Math.abs(dx) + Math.abs(dy); Integer direction; if (dist < _config.swipe_dist_px) @@ -290,7 +289,7 @@ public void onTouchMove(float x, float y, int pointerId) (newValue.equals(ptr.key.getKeyValue(5)) || newValue.equals(ptr.key.getKeyValue(6)))) { - startSliding(ptr, dy); + startSliding(ptr, x); } _handler.onPointerDown(newValue, true); } @@ -425,34 +424,11 @@ private boolean handleKeyRepeat(Pointer ptr) // Sliding - void startSliding(Pointer ptr, float initial_dy) + void startSliding(Pointer ptr, float x) { stopKeyRepeat(ptr); ptr.flags |= FLAG_P_SLIDING; - ptr.sliding_count = (int)(initial_dy / _config.slide_step_px); - } - - /** Handle a sliding pointer going up. Latched modifiers are not cleared to - allow easy adjustments to the cursors. The pointer is cancelled. */ - void onTouchUp_sliding(Pointer ptr) - { - removePtr(ptr); - _handler.onPointerFlagsChanged(false); - } - - /** Handle move events for sliding pointers. [dx] is distance travelled from - [downX]. */ - void onTouchMove_sliding(Pointer ptr, float dx) - { - int count = (int)(dx / _config.slide_step_px); - if (count == ptr.sliding_count) - return; - int key_index = (count < ptr.sliding_count) ? 5 : 6; - KeyValue newValue = _handler.modifyKey(ptr.key.keys[key_index], ptr.modifiers); - ptr.sliding_count = count; - ptr.value = newValue; - if (newValue != null) - _handler.onPointerHold(newValue, ptr.modifiers); + ptr.sliding = new Sliding(x); } /** Return the [FLAG_P_*] flags that correspond to pressing [kv]. */ @@ -489,8 +465,8 @@ private static final class Pointer public int flags; /** Identify timeout messages. */ public int timeoutWhat; - /** Number of event already caused by sliding. */ - public int sliding_count; + /** [null] when not in sliding mode. */ + public Sliding sliding; public Pointer(int p, KeyboardData.Key k, KeyValue v, float x, float y, Modifiers m) { @@ -503,7 +479,7 @@ public Pointer(int p, KeyboardData.Key k, KeyValue v, float x, float y, Modifier modifiers = m; flags = (v == null) ? 0 : pointer_flags_of_kv(v); timeoutWhat = -1; - sliding_count = 0; + sliding = null; } public boolean hasFlagsAny(int has) @@ -512,6 +488,91 @@ public boolean hasFlagsAny(int has) } } + public final class Sliding + { + /** Accumulated distance since last event. */ + float d = 0.f; + /** The slider speed changes depending on the pointer speed. */ + float speed = 1.f; + /** Coordinate of the last move. */ + float last_x; + /** [System.currentTimeMillis()] at the time of the last move. */ + long last_move_ms; + + public Sliding(float x) + { + last_x = x; + last_move_ms = System.currentTimeMillis(); + } + + static final float SPEED_SMOOTHING = 0.7f; + /** Avoid absurdly large values. */ + static final float SPEED_MAX = 4.f; + + public void onTouchMove(Pointer ptr, float x) + { + d += (x - last_x) * speed / _config.slide_step_px; + update_speed(x); + // Send an event when [abs(d)] exceeds [1]. + int d_ = (int)d; + if (d_ != 0) + { + d -= d_; + int key_index = (d_ < 0) ? 5 : 6; + ptr.value = _handler.modifyKey(ptr.key.keys[key_index], ptr.modifiers); + send_key(ptr, Math.abs(d_)); + } + } + + /** Handle a sliding pointer going up. Latched modifiers are not + cleared to allow easy adjustments to the cursors. The pointer is + cancelled. */ + public void onTouchUp(Pointer ptr) + { + removePtr(ptr); + _handler.onPointerFlagsChanged(false); + } + + /** Send the pressed key [n] times. */ + void send_key(Pointer ptr, int n) + { + if (ptr.value == null) + return; + // Avoid looping if possible to avoid lag while sliding fast + KeyValue multiplied = multiply_key(ptr.value, n); + if (multiplied != null) + _handler.onPointerHold(multiplied, ptr.modifiers); + else + for (int i = 0; i < n; i++) + _handler.onPointerHold(ptr.value, ptr.modifiers); + } + + /** Return a key performing the same action as [kv] but [n] times. Returns + [null] if [kv] cannot be multiplied. */ + KeyValue multiply_key(KeyValue kv, int n) + { + switch (kv.getKind()) + { + case Cursor_move: + return KeyValue.cursorMoveKey(kv.getCursorMove() * n); + } + return null; + } + + /** [speed] is computed from the elapsed time and distance traveled + between two move events. Exponential smoothing is used to smooth out + the noise. Sets [last_move_ms] and [last_x]. */ + void update_speed(float x) + { + long now = System.currentTimeMillis(); + float instant_speed = Math.min(SPEED_MAX, + Math.abs(x - last_x) / (float)(now - last_move_ms) + 1.f); + speed = speed + (instant_speed - speed) * SPEED_SMOOTHING; + last_move_ms = now; + last_x = x; + } + } + /** Represent modifiers currently activated. Sorted in the order they should be evaluated. */ public static final class Modifiers From d96414c6c6d995db020ec38556ef2e635574b759 Mon Sep 17 00:00:00 2001 From: Jules Aguillon Date: Thu, 2 May 2024 19:37:18 +0200 Subject: [PATCH 9/9] Allow the newline character '\n' in layouts --- srcs/juloo.keyboard2/KeyValue.java | 1 + 1 file changed, 1 insertion(+) diff --git a/srcs/juloo.keyboard2/KeyValue.java b/srcs/juloo.keyboard2/KeyValue.java index da21d845f..1f00464ee 100644 --- a/srcs/juloo.keyboard2/KeyValue.java +++ b/srcs/juloo.keyboard2/KeyValue.java @@ -467,6 +467,7 @@ public static KeyValue getKeyByName(String name) /* Spaces */ case "\\t": return charKey("\\t", '\t', 0); // Send the tab character + case "\\n": return charKey("\\n", '\n', 0); // Send the newline character case "space": return charKey(0xE00D, ' ', FLAG_KEY_FONT | FLAG_SMALLER_FONT | FLAG_GREYED); case "nbsp": return charKey("\u237d", '\u00a0', FLAG_SMALLER_FONT);