Compare commits

..

2 Commits

Author SHA1 Message Date
Jules Aguillon
3d1383adfa 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.
2025-03-08 13:52:56 +01:00
Jules Aguillon
80bc21c4af Construct a single handler 2025-03-08 13:47:55 +01:00
6 changed files with 14 additions and 118 deletions

View File

@@ -242,7 +242,6 @@ public final class KeyEventHandler
case AUTOFILL: send_context_menu_action(android.R.id.autofill); break; case AUTOFILL: send_context_menu_action(android.R.id.autofill); break;
case DELETE_WORD: send_key_down_up(KeyEvent.KEYCODE_DEL, KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON); break; case DELETE_WORD: send_key_down_up(KeyEvent.KEYCODE_DEL, KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON); break;
case FORWARD_DELETE_WORD: send_key_down_up(KeyEvent.KEYCODE_FORWARD_DEL, KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON); break; case FORWARD_DELETE_WORD: send_key_down_up(KeyEvent.KEYCODE_FORWARD_DEL, KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON); break;
case SELECTION_CANCEL: cancel_selection(); break;
} }
} }
@@ -260,17 +259,15 @@ public final class KeyEventHandler
return conn.getExtractedText(_move_cursor_req, 0); return conn.getExtractedText(_move_cursor_req, 0);
} }
/** [r] might be negative, in which case the direction is reversed. */ /** [repeatition] might be negative, in which case the direction is reversed. */
void handle_slider(KeyValue.Slider s, int r) void handle_slider(KeyValue.Slider s, int repeatition)
{ {
switch (s) switch (s)
{ {
case Cursor_left: move_cursor(-r); break; case Cursor_left: move_cursor(-repeatition); break;
case Cursor_right: move_cursor(r); break; case Cursor_right: move_cursor(repeatition); break;
case Cursor_up: move_cursor_vertical(-r); break; case Cursor_up: move_cursor_vertical(-repeatition); break;
case Cursor_down: move_cursor_vertical(r); break; case Cursor_down: move_cursor_vertical(repeatition); break;
case Selection_cursor_left: move_cursor_sel(r, true); break;
case Selection_cursor_right: move_cursor_sel(r, false); break;
} }
} }
@@ -284,7 +281,12 @@ public final class KeyEventHandler
if (conn == null) if (conn == null)
return; return;
ExtractedText et = get_cursor_pos(conn); ExtractedText et = get_cursor_pos(conn);
if (et != null && can_set_selection(conn)) int system_mods =
KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON | KeyEvent.META_META_ON;
// Fallback to sending key events if system modifiers are activated or
// ExtractedText is not supported, for example on Termux.
if (!_move_cursor_force_fallback && et != null
&& (_meta_state & system_mods) == 0)
{ {
int sel_start = et.selectionStart; int sel_start = et.selectionStart;
int sel_end = et.selectionEnd; int sel_end = et.selectionEnd;
@@ -303,45 +305,8 @@ public final class KeyEventHandler
sel_start = sel_end; sel_start = sel_end;
} }
if (conn.setSelection(sel_start, sel_end)) if (conn.setSelection(sel_start, sel_end))
return; // Fallback to sending key events if [setSelection] failed return; // [setSelection] succeeded, don't fallback to key events
} }
move_cursor_fallback(d);
}
/** Move one of the two side of a selection. If [sel_left] is true, the left
position is moved, otherwise the right position is moved. */
void move_cursor_sel(int d, boolean sel_left)
{
InputConnection conn = _recv.getCurrentInputConnection();
if (conn == null)
return;
ExtractedText et = get_cursor_pos(conn);
if (et != null && can_set_selection(conn))
{
int sel_start = et.selectionStart;
int sel_end = et.selectionEnd;
if (sel_left == (sel_start <= sel_end))
sel_start += d;
else
sel_end += d;
if (conn.setSelection(sel_start, sel_end))
return; // Fallback to sending key events if [setSelection] failed
}
move_cursor_fallback(d);
}
/** Returns whether the selection can be set using [conn.setSelection()].
This can happen on Termux or when system modifiers are activated for
example. */
boolean can_set_selection(InputConnection conn)
{
final int system_mods =
KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON | KeyEvent.META_META_ON;
return !_move_cursor_force_fallback && (_meta_state & system_mods) == 0;
}
void move_cursor_fallback(int d)
{
if (d < 0) if (d < 0)
send_key_down_up_repeat(KeyEvent.KEYCODE_DPAD_LEFT, -d); send_key_down_up_repeat(KeyEvent.KEYCODE_DPAD_LEFT, -d);
else else
@@ -435,25 +400,11 @@ public final class KeyEventHandler
send_key_down_up(event_code); send_key_down_up(event_code);
} }
void cancel_selection()
{
InputConnection conn = _recv.getCurrentInputConnection();
if (conn == null)
return;
ExtractedText et = get_cursor_pos(conn);
if (et == null) return;
final int curs = et.selectionStart;
// Notify the receiver as Android's [onUpdateSelection] is not triggered.
if (conn.setSelection(curs, curs));
_recv.selection_state_changed(false);
}
public static interface IReceiver public static interface IReceiver
{ {
public void handle_event_key(KeyValue.Event ev); public void handle_event_key(KeyValue.Event ev);
public void set_shift_state(boolean state, boolean lock); public void set_shift_state(boolean state, boolean lock);
public void set_compose_pending(boolean pending); public void set_compose_pending(boolean pending);
public void selection_state_changed(boolean selection_is_ongoing);
public InputConnection getCurrentInputConnection(); public InputConnection getCurrentInputConnection();
public Handler getHandler(); public Handler getHandler();
} }

View File

@@ -82,7 +82,6 @@ public final class KeyModifier
case HOOK_ABOVE: return apply_compose(k, ComposeKeyData.accent_hook_above); case HOOK_ABOVE: return apply_compose(k, ComposeKeyData.accent_hook_above);
case DOUBLE_GRAVE: return apply_compose(k, ComposeKeyData.accent_double_grave); case DOUBLE_GRAVE: return apply_compose(k, ComposeKeyData.accent_double_grave);
case ARROW_RIGHT: return apply_combining_char(k, "\u20D7"); case ARROW_RIGHT: return apply_combining_char(k, "\u20D7");
case SELECTION_MODE: return apply_selection_mode(k);
default: return k; default: return k;
} }
} }
@@ -393,34 +392,6 @@ public final class KeyModifier
return (name == null) ? k : KeyValue.getKeyByName(name); return (name == null) ? k : KeyValue.getKeyByName(name);
} }
private static KeyValue apply_selection_mode(KeyValue k)
{
String name = null;
switch (k.getKind())
{
case Char:
switch (k.getChar())
{
case ' ': name = "selection_cancel"; break;
}
break;
case Slider:
switch (k.getSlider())
{
case Cursor_left: name = "selection_cursor_left"; break;
case Cursor_right: name = "selection_cursor_right"; break;
}
break;
case Keyevent:
switch (k.getKeyevent())
{
case KeyEvent.KEYCODE_ESCAPE: name = "selection_cancel"; break;
}
break;
}
return (name == null) ? k : KeyValue.getKeyByName(name);
}
/** Compose the precomposed initial with the medial [kv]. */ /** Compose the precomposed initial with the medial [kv]. */
private static KeyValue combine_hangul_initial(KeyValue kv, int precomposed) private static KeyValue combine_hangul_initial(KeyValue kv, int precomposed)
{ {

View File

@@ -59,7 +59,6 @@ public final class KeyValue implements Comparable<KeyValue>
BREVE, BREVE,
BAR, BAR,
FN, FN,
SELECTION_MODE,
} // Last is be applied first } // Last is be applied first
public static enum Editing public static enum Editing
@@ -78,7 +77,6 @@ public final class KeyValue implements Comparable<KeyValue>
AUTOFILL, AUTOFILL,
DELETE_WORD, DELETE_WORD,
FORWARD_DELETE_WORD, FORWARD_DELETE_WORD,
SELECTION_CANCEL,
} }
public static enum Placeholder public static enum Placeholder
@@ -717,9 +715,6 @@ public final class KeyValue implements Comparable<KeyValue>
case "cursor_right": return sliderKey(Slider.Cursor_right, 1); case "cursor_right": return sliderKey(Slider.Cursor_right, 1);
case "cursor_up": return sliderKey(Slider.Cursor_up, 1); case "cursor_up": return sliderKey(Slider.Cursor_up, 1);
case "cursor_down": return sliderKey(Slider.Cursor_down, 1); case "cursor_down": return sliderKey(Slider.Cursor_down, 1);
case "selection_cancel": return editingKey("Esc", Editing.SELECTION_CANCEL, FLAG_SMALLER_FONT);
case "selection_cursor_left": return sliderKey(Slider.Selection_cursor_left, -1); // Move the left side of the selection
case "selection_cursor_right": return sliderKey(Slider.Selection_cursor_right, 1);
// These keys are not used // These keys are not used
case "replaceText": return editingKey("repl", Editing.REPLACE); case "replaceText": return editingKey("repl", Editing.REPLACE);
case "textAssist": return editingKey(0xE038, Editing.ASSIST); case "textAssist": return editingKey(0xE038, Editing.ASSIST);
@@ -769,9 +764,6 @@ public final class KeyValue implements Comparable<KeyValue>
case "": case "": case "": case "":
return makeStringKey(name, FLAG_SMALLER_FONT); return makeStringKey(name, FLAG_SMALLER_FONT);
/* Internal keys */
case "selection_mode": return makeInternalModifier(Modifier.SELECTION_MODE);
default: return null; default: return null;
} }
} }
@@ -788,9 +780,7 @@ public final class KeyValue implements Comparable<KeyValue>
Cursor_left(0xE008), Cursor_left(0xE008),
Cursor_right(0xE006), Cursor_right(0xE006),
Cursor_up(0xE005), Cursor_up(0xE005),
Cursor_down(0xE007), Cursor_down(0xE007);
Selection_cursor_left(0xE008),
Selection_cursor_right(0xE006);
final String symbol; final String symbol;

View File

@@ -362,8 +362,6 @@ public class Keyboard2 extends InputMethodService
{ {
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd); super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd);
_keyeventhandler.selection_updated(oldSelStart, newSelStart); _keyeventhandler.selection_updated(oldSelStart, newSelStart);
if ((oldSelStart == oldSelEnd) != (newSelStart == newSelEnd))
_keyboardView.set_selection_state(newSelStart != newSelEnd);
} }
@Override @Override
@@ -482,11 +480,6 @@ public class Keyboard2 extends InputMethodService
_keyboardView.set_compose_pending(pending); _keyboardView.set_compose_pending(pending);
} }
public void selection_state_changed(boolean selection_is_ongoing)
{
_keyboardView.set_selection_state(selection_is_ongoing);
}
public InputConnection getCurrentInputConnection() public InputConnection getCurrentInputConnection()
{ {
return Keyboard2.this.getCurrentInputConnection(); return Keyboard2.this.getCurrentInputConnection();

View File

@@ -139,13 +139,6 @@ public class Keyboard2View extends View
set_fake_ptr_latched(_compose_key, _compose_kv, pending, false); set_fake_ptr_latched(_compose_key, _compose_kv, pending, false);
} }
/** Called from [Keybard2.onUpdateSelection]. */
public void set_selection_state(boolean selection_state)
{
set_fake_ptr_latched(KeyboardData.Key.EMPTY,
KeyValue.getKeyByName("selection_mode"), selection_state, true);
}
public KeyValue modifyKey(KeyValue k, Pointers.Modifiers mods) public KeyValue modifyKey(KeyValue k, Pointers.Modifiers mods)
{ {
return KeyModifier.modify(k, mods); return KeyModifier.modify(k, mods);

View File

@@ -422,8 +422,6 @@ public final class KeyboardData
indication = i; indication = i;
} }
static final Key EMPTY = new Key(new KeyValue[9], null, 0, 1.f, 1.f, null);
/** Read a key value attribute that have a synonym. Having both synonyms /** Read a key value attribute that have a synonym. Having both synonyms
present at the same time is an error. present at the same time is an error.
Returns [null] if the attributes are not present. */ Returns [null] if the attributes are not present. */