abouttreesummaryrefslogcommitdiff
diff options
context:
space:
mode:
authorJules Aguillon2025-03-10 23:41:51 +0100
committerGitHub2025-03-10 23:41:51 +0100
commit9cfeb0f0c22dd649fcf32260925a5a84a731d1b3 (patch)
tree447ceb35fe87b086ec7f75c0bee7addc4619a16c
parent5e77fa84cff5a55cc26f3e02e2823ad0ec845c51 (diff)
downloadunexpected-keyboard-9cfeb0f0c22dd649fcf32260925a5a84a731d1b3.tar.gz
unexpected-keyboard-9cfeb0f0c22dd649fcf32260925a5a84a731d1b3.zip
Add a delay after a Keyevent key in a macro (#918)
* Construct a single handler * Add a delay after a Keyevent key in a macro Add a delay before sending the next key to avoid race conditions causing keys to be handled in the wrong order. Notably, KeyEvent keys handling is scheduled differently than the other edit functions.
-rw-r--r--srcs/juloo.keyboard2/Autocapitalisation.java5
-rw-r--r--srcs/juloo.keyboard2/KeyEventHandler.java69
-rw-r--r--srcs/juloo.keyboard2/Keyboard2.java10
3 files changed, 67 insertions, 17 deletions
diff --git a/srcs/juloo.keyboard2/Autocapitalisation.java b/srcs/juloo.keyboard2/Autocapitalisation.java
index a77d2e5..21fcaf6 100644
--- a/srcs/juloo.keyboard2/Autocapitalisation.java
+++ b/srcs/juloo.keyboard2/Autocapitalisation.java
@@ -1,7 +1,6 @@
package juloo.keyboard2;
import android.os.Handler;
-import android.os.Looper;
import android.text.InputType;
import android.text.TextUtils;
import android.view.inputmethod.EditorInfo;
@@ -27,9 +26,9 @@ public final class Autocapitalisation
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES |
InputType.TYPE_TEXT_FLAG_CAP_WORDS;
- public Autocapitalisation(Looper looper, Callback cb)
+ public Autocapitalisation(Handler h, Callback cb)
{
- _handler = new Handler(looper);
+ _handler = h;
_callback = cb;
}
diff --git a/srcs/juloo.keyboard2/KeyEventHandler.java b/srcs/juloo.keyboard2/KeyEventHandler.java
index a841c30..30282c7 100644
--- a/srcs/juloo.keyboard2/KeyEventHandler.java
+++ b/srcs/juloo.keyboard2/KeyEventHandler.java
@@ -2,6 +2,7 @@ package juloo.keyboard2;
import android.annotation.SuppressLint;
import android.os.Looper;
+import android.os.Handler;
import android.text.InputType;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -28,10 +29,10 @@ public final class KeyEventHandler
[setSelection] could be used instead. */
boolean _move_cursor_force_fallback = false;
- public KeyEventHandler(Looper looper, IReceiver recv)
+ public KeyEventHandler(IReceiver recv)
{
_recv = recv;
- _autocap = new Autocapitalisation(looper,
+ _autocap = new Autocapitalisation(recv.getHandler(),
this.new Autocapitalisation_callback());
_mods = Pointers.Modifiers.EMPTY;
}
@@ -324,31 +325,72 @@ public final class KeyEventHandler
void evaluate_macro(KeyValue[] keys)
{
- final Pointers.Modifiers empty = Pointers.Modifiers.EMPTY;
+ if (keys.length == 0)
+ return;
// Ignore modifiers that are activated at the time the macro is evaluated
- mods_changed(empty);
- Pointers.Modifiers mods = empty;
- final boolean autocap_paused = _autocap.pause();
- for (KeyValue kv : keys)
+ mods_changed(Pointers.Modifiers.EMPTY);
+ evaluate_macro_loop(keys, 0, Pointers.Modifiers.EMPTY, _autocap.pause());
+ }
+
+ /** Evaluate the macro asynchronously to make sure event are processed in the
+ right order. */
+ void evaluate_macro_loop(final KeyValue[] keys, int i, Pointers.Modifiers mods, final boolean autocap_paused)
+ {
+ boolean should_delay = false;
+ KeyValue kv = KeyModifier.modify(keys[i], mods);
+ if (kv != null)
{
- kv = KeyModifier.modify(kv, mods);
- if (kv == null)
- continue;
if (kv.hasFlagsAny(KeyValue.FLAG_LATCH))
{
// Non-special latchable keys clear latched modifiers
if (!kv.hasFlagsAny(KeyValue.FLAG_SPECIAL))
- mods = empty;
+ mods = Pointers.Modifiers.EMPTY;
mods = mods.with_extra_mod(kv);
}
else
{
key_down(kv, false);
key_up(kv, mods);
- mods = empty;
+ mods = Pointers.Modifiers.EMPTY;
}
+ should_delay = wait_after_macro_key(kv);
+ }
+ i++;
+ if (i >= keys.length) // Stop looping
+ {
+ _autocap.unpause(autocap_paused);
+ }
+ else if (should_delay)
+ {
+ // Add a delay before sending the next key to avoid race conditions
+ // causing keys to be handled in the wrong order. Notably, KeyEvent keys
+ // handling is scheduled differently than the other edit functions.
+ final int i_ = i;
+ final Pointers.Modifiers mods_ = mods;
+ _recv.getHandler().postDelayed(new Runnable() {
+ public void run()
+ {
+ evaluate_macro_loop(keys, i_, mods_, autocap_paused);
+ }
+ }, 1000/30);
+ }
+ else
+ evaluate_macro_loop(keys, i, mods, autocap_paused);
+ }
+
+ boolean wait_after_macro_key(KeyValue kv)
+ {
+ switch (kv.getKind())
+ {
+ case Keyevent:
+ case Editing:
+ case Event:
+ return true;
+ case Slider:
+ return _move_cursor_force_fallback;
+ default:
+ return false;
}
- _autocap.unpause(autocap_paused);
}
/** Repeat calls to [send_key_down_up]. */
@@ -364,6 +406,7 @@ public final class KeyEventHandler
public void set_shift_state(boolean state, boolean lock);
public void set_compose_pending(boolean pending);
public InputConnection getCurrentInputConnection();
+ public Handler getHandler();
}
class Autocapitalisation_callback implements Autocapitalisation.Callback
diff --git a/srcs/juloo.keyboard2/Keyboard2.java b/srcs/juloo.keyboard2/Keyboard2.java
index 6d3516d..02c062a 100644
--- a/srcs/juloo.keyboard2/Keyboard2.java
+++ b/srcs/juloo.keyboard2/Keyboard2.java
@@ -6,6 +6,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.inputmethodservice.InputMethodService;
import android.os.Build.VERSION;
+import android.os.Handler;
import android.os.IBinder;
import android.text.InputType;
import android.util.Log;
@@ -38,6 +39,7 @@ public class Keyboard2 extends InputMethodService
private ViewGroup _emojiPane = null;
private ViewGroup _clipboard_pane = null;
public int actionId; // Action performed by the Action key.
+ private Handler _handler;
private Config _config;
@@ -107,7 +109,8 @@ public class Keyboard2 extends InputMethodService
{
super.onCreate();
SharedPreferences prefs = DirectBootAwarePreferences.get_shared_preferences(this);
- _keyeventhandler = new KeyEventHandler(getMainLooper(), this.new Receiver());
+ _handler = new Handler(getMainLooper());
+ _keyeventhandler = new KeyEventHandler(this.new Receiver());
Config.initGlobalConfig(prefs, getResources(), _keyeventhandler);
prefs.registerOnSharedPreferenceChangeListener(this);
_config = Config.globalConfig();
@@ -481,6 +484,11 @@ public class Keyboard2 extends InputMethodService
{
return Keyboard2.this.getCurrentInputConnection();
}
+
+ public Handler getHandler()
+ {
+ return _handler;
+ }
}
private IBinder getConnectionToken()