forked from extern/Unexpected-Keyboard
refactor: Implement Compose without global state
Thanks to the previous commit, a modifier key can now be more complex than just a KeyValue.Modifier. This allows a more elegant implementation of the compose key, that could be taken as a base for other features (eg. unicode hex entry, hangul) The COMPOSE_PENDING modifier is removed as keys of kind Compose_pending can act as a modifier. This has the advantage of highlighting the key that was last pressed in the sequence. Rules are added to Pointers: Non-special but latchable keys must clear latches and cannot be locked with a long press. These rules were not needed before but were intended.
This commit is contained in:
parent
dc3a303af1
commit
e604f6fd57
@ -4,31 +4,26 @@ import java.util.Arrays;
|
||||
|
||||
public final class ComposeKey
|
||||
{
|
||||
/** Apply the pending compose sequence to [kv]. Returns [null] if [kv] is not
|
||||
part of the pending sequence. */
|
||||
/** Apply the pending compose sequence to [kv]. */
|
||||
public static KeyValue apply(int state, KeyValue kv)
|
||||
{
|
||||
switch (kv.getKind())
|
||||
{
|
||||
case Char:
|
||||
KeyValue res = apply(state, kv.getChar());
|
||||
// Dim characters not part of any sequence instead of removing them.
|
||||
// Grey-out characters not part of any sequence.
|
||||
if (res == null)
|
||||
return kv.withFlags(kv.getFlags() | KeyValue.FLAG_GREYED);
|
||||
return res;
|
||||
/* These keys must not be removed. */
|
||||
/* These keys are not greyed. */
|
||||
case Event:
|
||||
case Modifier:
|
||||
case Compose_pending:
|
||||
return kv;
|
||||
/* These keys cannot be part of sequences. */
|
||||
case String:
|
||||
case Keyevent:
|
||||
case Editing:
|
||||
case Placeholder:
|
||||
/* Other keys cannot be part of sequences. */
|
||||
default:
|
||||
return kv.withFlags(kv.getFlags() | KeyValue.FLAG_GREYED);
|
||||
case Compose_pending: return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Apply the pending compose sequence to char [c]. */
|
||||
|
@ -69,9 +69,6 @@ public final class KeyEventHandler implements Config.IKeyEventHandler
|
||||
case META:
|
||||
_autocap.stop();
|
||||
break;
|
||||
case COMPOSE_PENDING:
|
||||
KeyModifier.set_compose_pending(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
@ -95,7 +92,6 @@ public final class KeyEventHandler implements Config.IKeyEventHandler
|
||||
case Modifier: break;
|
||||
case Editing: handle_editing_key(key.getEditing()); break;
|
||||
case Compose_pending:
|
||||
KeyModifier.set_compose_pending(key.getPendingCompose());
|
||||
_recv.set_compose_pending(true);
|
||||
break;
|
||||
}
|
||||
|
@ -10,10 +10,6 @@ public final class KeyModifier
|
||||
private static HashMap<KeyValue, HashMap<Pointers.Modifiers, KeyValue>> _cache =
|
||||
new HashMap<KeyValue, HashMap<Pointers.Modifiers, KeyValue>>();
|
||||
|
||||
/** The current compose state. Whether a compose is pending is signaled by
|
||||
the [COMPOSE_PENDING] modifier. */
|
||||
static int _compose_pending = -1;
|
||||
|
||||
/** Modify a key according to modifiers. */
|
||||
public static KeyValue modify(KeyValue k, Pointers.Modifiers mods)
|
||||
{
|
||||
@ -33,8 +29,6 @@ public final class KeyModifier
|
||||
/* Keys with an empty string are placeholder keys. */
|
||||
if (r.getString().length() == 0)
|
||||
return null;
|
||||
if (mods.has(KeyValue.Modifier.COMPOSE_PENDING))
|
||||
r = ComposeKey.apply(_compose_pending, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -44,6 +38,8 @@ public final class KeyModifier
|
||||
{
|
||||
case Modifier:
|
||||
return modify(k, mod.getModifier());
|
||||
case Compose_pending:
|
||||
return ComposeKey.apply(mod.getPendingCompose(), k);
|
||||
}
|
||||
return k;
|
||||
}
|
||||
@ -118,11 +114,6 @@ public final class KeyModifier
|
||||
}
|
||||
}
|
||||
|
||||
public static void set_compose_pending(int state)
|
||||
{
|
||||
_compose_pending = state;
|
||||
}
|
||||
|
||||
private static KeyValue apply_map_char(KeyValue k, Map_char map)
|
||||
{
|
||||
switch (k.getKind())
|
||||
|
@ -26,7 +26,6 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
// Must be evaluated in the reverse order of their values.
|
||||
public static enum Modifier
|
||||
{
|
||||
COMPOSE_PENDING,
|
||||
SHIFT,
|
||||
CTRL,
|
||||
ALT,
|
||||
@ -89,8 +88,8 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
|
||||
public static enum Kind
|
||||
{
|
||||
Char, String, Keyevent, Event, Modifier, Editing, Placeholder,
|
||||
Compose_pending
|
||||
Char, String, Keyevent, Event, Compose_pending, Modifier, Editing,
|
||||
Placeholder
|
||||
}
|
||||
|
||||
private static final int FLAGS_OFFSET = 19;
|
||||
@ -340,7 +339,13 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
public static KeyValue makeComposePending(String symbol, int state, int flags)
|
||||
{
|
||||
return new KeyValue(symbol, Kind.Compose_pending, state,
|
||||
flags | FLAG_SPECIAL);
|
||||
flags | FLAG_LATCH);
|
||||
}
|
||||
|
||||
public static KeyValue makeComposePending(int symbol, int state, int flags)
|
||||
{
|
||||
return makeComposePending(String.valueOf((char)symbol), state,
|
||||
flags | FLAG_KEY_FONT);
|
||||
}
|
||||
|
||||
/** Make a key that types a string. A char key is returned for a string of
|
||||
@ -505,7 +510,7 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
case "autofill": return editingKey("auto", Editing.AUTOFILL);
|
||||
|
||||
/* The compose key */
|
||||
case "compose": return modifierKey(0xE016, Modifier.COMPOSE_PENDING, FLAG_SECONDARY | FLAG_SMALLER_FONT);
|
||||
case "compose": return makeComposePending(0xE016, 0, FLAG_SECONDARY | FLAG_SMALLER_FONT | FLAG_SPECIAL);
|
||||
|
||||
/* Placeholder keys */
|
||||
case "removed": return placeholderKey(Placeholder.REMOVED);
|
||||
|
@ -19,6 +19,10 @@ public final class Pointers implements Handler.Callback
|
||||
public static final int FLAG_P_LOCKABLE = (1 << 3);
|
||||
public static final int FLAG_P_LOCKED = (1 << 4);
|
||||
public static final int FLAG_P_SLIDING = (1 << 5);
|
||||
/** Clear latched (only if also FLAG_P_LATCHABLE set). */
|
||||
public static final int FLAG_P_CLEAR_LATCHED = (1 << 6);
|
||||
/** Can't be locked, even when long pressing. */
|
||||
public static final int FLAG_P_CANT_LOCK = (1 << 7);
|
||||
|
||||
private Handler _keyrepeat_handler;
|
||||
private ArrayList<Pointer> _ptrs = new ArrayList<Pointer>();
|
||||
@ -153,6 +157,9 @@ public final class Pointers implements Handler.Callback
|
||||
}
|
||||
else if ((ptr.flags & FLAG_P_LATCHABLE) != 0)
|
||||
{
|
||||
// Latchable but non-special keys must clear latched.
|
||||
if ((ptr.flags & FLAG_P_CLEAR_LATCHED) != 0)
|
||||
clearLatched();
|
||||
ptr.flags |= FLAG_P_LATCHED;
|
||||
ptr.pointerId = -1;
|
||||
_handler.onPointerFlagsChanged(false);
|
||||
@ -395,6 +402,7 @@ public final class Pointers implements Handler.Callback
|
||||
// Long press toggle lock on modifiers
|
||||
if ((ptr.flags & FLAG_P_LATCHABLE) != 0)
|
||||
{
|
||||
if (!ptr.hasFlagsAny(FLAG_P_CANT_LOCK))
|
||||
lockPointer(ptr, true);
|
||||
return false;
|
||||
}
|
||||
@ -452,7 +460,12 @@ public final class Pointers implements Handler.Callback
|
||||
{
|
||||
int flags = 0;
|
||||
if (kv.hasFlagsAny(KeyValue.FLAG_LATCH))
|
||||
{
|
||||
// Non-special latchable key must clear modifiers and can't be locked
|
||||
if (!kv.hasFlagsAny(KeyValue.FLAG_SPECIAL))
|
||||
flags |= FLAG_P_CLEAR_LATCHED | FLAG_P_CANT_LOCK;
|
||||
flags |= FLAG_P_LATCHABLE;
|
||||
}
|
||||
if (kv.hasFlagsAny(KeyValue.FLAG_LOCK))
|
||||
flags |= FLAG_P_LOCKABLE;
|
||||
return flags;
|
||||
|
Loading…
Reference in New Issue
Block a user