From 4c87a16b276fb2ba6b17895c8243766dba459ecf Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 5 Aug 2024 13:05:40 +0700 Subject: [PATCH 1/4] feat(android/engine): Add special handling for ENTER key --- .../com/keyman/android/SystemKeyboard.java | 3 ++ .../keyman/engine/KMKeyboardJSHandler.java | 29 ++++++++++- .../java/com/keyman/engine/KMManager.java | 49 ++++++++++++++++++- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index c6885b2b56..9bc5a4a855 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -147,6 +147,9 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven KMManager.onStartInput(attribute, restarting); KMManager.resetContext(KeyboardType.KEYBOARD_TYPE_SYSTEM); + // Determine special handling for ENTER key + KMManager.setEnterMode(attribute.imeOptions); + // This method (likely) includes the IME equivalent to `onResume` for `Activity`-based classes, // making it an important time to detect orientation changes. Context appContext = getApplicationContext(); diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java index 926ef094f7..426cfb3e52 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java @@ -20,6 +20,7 @@ import android.webkit.JavascriptInterface; import static android.content.Context.VIBRATOR_SERVICE; +import com.keyman.engine.KMManager.EnterModeType; import com.keyman.engine.KMManager.KeyboardType; import com.keyman.engine.data.Keyboard; import com.keyman.engine.util.CharSequenceUtil; @@ -153,7 +154,33 @@ public class KMKeyboardJSHandler { } if (s.length() > 0 && s.charAt(0) == '\n') { - keyDownUp(KeyEvent.KEYCODE_ENTER, 0); + if (k.keyboardType == KeyboardType.KEYBOARD_TYPE_SYSTEM) { + // Special handling of ENTER key + switch (KMManager.enterMode) { + // Go action + case GO : + ic.performEditorAction(EditorInfo.IME_ACTION_GO); + break; + + // Search action + case SEARCH : + ic.performEditorAction(EditorInfo.IME_ACTION_SEARCH); + break; + + // Messaging apps + case NEWLINE : + // Send newline without advancing cursor + ic.commitText("\n", 0); + break; + + // Default ENTER action + default: + keyDownUp(KeyEvent.KEYCODE_ENTER, 0); + } + } else { + // In-app keyboard uses default ENTER action + keyDownUp(KeyEvent.KEYCODE_ENTER, 0); + } ic.endBatchEdit(); return; } diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index aa1c43626a..adef3d3fe5 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -25,7 +25,6 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.content.res.Configuration; -import android.content.res.Resources; import android.graphics.Point; import android.graphics.Typeface; import android.inputmethodservice.InputMethodService; @@ -180,6 +179,15 @@ public final class KMManager { } } + // Enum for how the System Keyboard ENTER key is handled for the EditorInfo action + // Reference: https://developer.android.com/reference/android/view/inputmethod/EditorInfo#summary + public enum EnterModeType { + GO, // Go action + SEARCH, // Search action + NEWLINE, // Send newline character + DEFAULT, // Default ENTER action + } + protected static InputMethodService IMService; private static boolean debugMode = false; @@ -218,6 +226,9 @@ public final class KMManager { // regardless what the Settings preference is. private static boolean mayPredictOverride = false; + // Determine how system keyboard handles ENTER key + public static EnterModeType enterMode = EnterModeType.DEFAULT; + // Boolean for whether a keyboard can send embedded KMW crash reports to Sentry // When maySendCrashReport is false, KMW will still attempt to send crash reports, but it // will be blocked. @@ -1251,6 +1262,42 @@ public final class KMManager { } } + /** + * Sets enterMode which specifies how the System keyboard ENTER key is handled + * + * @param imeOptions EditorInfo.imeOptions + */ + public static void setEnterMode(int imeOptions) { + int imeActions = imeOptions&EditorInfo.IME_MASK_ACTION; + EnterModeType value = EnterModeType.DEFAULT; + + switch (imeActions) { + case EditorInfo.IME_ACTION_GO: + value = EnterModeType.GO; + break; + + case EditorInfo.IME_ACTION_SEARCH: + value = EnterModeType.SEARCH; + break; + + case EditorInfo.IME_ACTION_DONE: + value = EnterModeType.NEWLINE; + break; + + default: + value = EnterModeType.DEFAULT; + } + enterMode = value; + } + + /** + * Get the value of enterMode + * @return EnterModeType + */ + public static EnterModeType getEnterMode() { + return enterMode; + } + /** * Sets mayPredictOverride true if the InputType field is a hidden password text field * (either TYPE_TEXT_VARIATION_PASSWORD or TYPE_TEXT_VARIATION_WEB_PASSWORD From ea2b062c5273684a78f46dce5da3c34ecbed1648 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 7 Aug 2024 15:21:40 +0700 Subject: [PATCH 2/4] fix(android/engine): Separate DONE from NEWLINE action --- .../java/com/keyman/android/SystemKeyboard.java | 6 +++--- .../com/keyman/engine/KMKeyboardJSHandler.java | 5 +++++ .../src/main/java/com/keyman/engine/KMManager.java | 14 +++++++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index 9bc5a4a855..ab9b4fcb44 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -147,9 +147,6 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven KMManager.onStartInput(attribute, restarting); KMManager.resetContext(KeyboardType.KEYBOARD_TYPE_SYSTEM); - // Determine special handling for ENTER key - KMManager.setEnterMode(attribute.imeOptions); - // This method (likely) includes the IME equivalent to `onResume` for `Activity`-based classes, // making it an important time to detect orientation changes. Context appContext = getApplicationContext(); @@ -178,6 +175,9 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven } } + // Determine special handling for ENTER key + KMManager.setEnterMode(attribute.imeOptions, inputType); + InputConnection ic = getCurrentInputConnection(); if (ic != null) { ExtractedText icText = ic.getExtractedText(new ExtractedTextRequest(), 0); diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java index 426cfb3e52..66af2ebe07 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java @@ -167,6 +167,11 @@ public class KMKeyboardJSHandler { ic.performEditorAction(EditorInfo.IME_ACTION_SEARCH); break; + // Done action + case DONE : + ic.performEditorAction(EditorInfo.IME_ACTION_DONE); + break; + // Messaging apps case NEWLINE : // Send newline without advancing cursor diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index adef3d3fe5..adf9d30737 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -185,6 +185,7 @@ public final class KMManager { GO, // Go action SEARCH, // Search action NEWLINE, // Send newline character + DONE, // Done action DEFAULT, // Default ENTER action } @@ -1266,9 +1267,15 @@ public final class KMManager { * Sets enterMode which specifies how the System keyboard ENTER key is handled * * @param imeOptions EditorInfo.imeOptions + * @param inputType InputType */ - public static void setEnterMode(int imeOptions) { - int imeActions = imeOptions&EditorInfo.IME_MASK_ACTION; + public static void setEnterMode(int imeOptions, int inputType) { + if ((inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0) { + enterMode = EnterModeType.NEWLINE; + return; + } + + int imeActions = imeOptions & EditorInfo.IME_MASK_ACTION; EnterModeType value = EnterModeType.DEFAULT; switch (imeActions) { @@ -1281,12 +1288,13 @@ public final class KMManager { break; case EditorInfo.IME_ACTION_DONE: - value = EnterModeType.NEWLINE; + value = EnterModeType.DONE; break; default: value = EnterModeType.DEFAULT; } + enterMode = value; } From 786a1063ea93a8dbd9d2fc70c535dadbc04fbaf8 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 9 Aug 2024 14:51:45 +0700 Subject: [PATCH 3/4] fix(android): Add SEND, NEXT, PREVIOUS actions --- .../com/keyman/engine/KMKeyboardJSHandler.java | 15 +++++++++++++++ .../main/java/com/keyman/engine/KMManager.java | 17 ++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java index 66af2ebe07..3a995560c6 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java @@ -167,11 +167,26 @@ public class KMKeyboardJSHandler { ic.performEditorAction(EditorInfo.IME_ACTION_SEARCH); break; + // Send action + case SEND : + ic.performEditorAction(EditorInfo.IME_ACTION_SEND); + break; + + // Next action + case NEXT : + ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); + break; + // Done action case DONE : ic.performEditorAction(EditorInfo.IME_ACTION_DONE); break; + // Previous action + case PREVIOUS : + ic.performEditorAction(EditorInfo.IME_ACTION_PREVIOUS); + break; + // Messaging apps case NEWLINE : // Send newline without advancing cursor diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index adf9d30737..0bbe93b932 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -184,8 +184,11 @@ public final class KMManager { public enum EnterModeType { GO, // Go action SEARCH, // Search action - NEWLINE, // Send newline character + SEND, // Send action + NEXT, // Next action DONE, // Done action + PREVIOUS, // Previous action + NEWLINE, // Send newline character DEFAULT, // Default ENTER action } @@ -1287,10 +1290,22 @@ public final class KMManager { value = EnterModeType.SEARCH; break; + case EditorInfo.IME_ACTION_SEND: + value = EnterModeType.SEND; + break; + + case EditorInfo.IME_ACTION_NEXT: + value = EnterModeType.NEXT; + break; + case EditorInfo.IME_ACTION_DONE: value = EnterModeType.DONE; break; + case EditorInfo.IME_ACTION_PREVIOUS: + value = EnterModeType.PREVIOUS; + break; + default: value = EnterModeType.DEFAULT; } From 686cfe04b13e1f0c7de5c9b25ed0c2ade75f2fa5 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 15 Aug 2024 15:00:00 +0700 Subject: [PATCH 4/4] fix(android): Advance cursor on newline --- .../src/main/java/com/keyman/engine/KMKeyboardJSHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java index 3a995560c6..d403a29235 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java @@ -189,8 +189,8 @@ public class KMKeyboardJSHandler { // Messaging apps case NEWLINE : - // Send newline without advancing cursor - ic.commitText("\n", 0); + // Send newline and advance cursor + ic.commitText("\n", 1); break; // Default ENTER action