abouttreesummaryrefslogcommitdiff
path: root/srcs/juloo.keyboard2/Pointers.java
diff options
context:
space:
mode:
authorJules Aguillon2022-06-05 01:38:42 +0200
committerJules Aguillon2022-06-05 01:43:58 +0200
commit4127aa6f033a258aa89ff3704a952505c8c056cb (patch)
tree5a1dcada711e1ed85c28d626abf0b2e484f7fcff /srcs/juloo.keyboard2/Pointers.java
parent4f9375373e3ce9514550fa0470b40ae7f0ff19b2 (diff)
downloadunexpected-keyboard-4127aa6f033a258aa89ff3704a952505c8c056cb.tar.gz
unexpected-keyboard-4127aa6f033a258aa89ff3704a952505c8c056cb.zip
Stop using flags for modifiers
There was no free bits left to add new modifiers. Instead of increasing the width of the 'flags' field, refactor the way modifiers are represented and used. Modifers are now represented as independent values and stored in the 'code' field. A flag is added to distinguish between modifiers and keys with a key event. The most notable change is that modifiers can no longer be or-ed into a single value but have to be represented as an array.
Diffstat (limited to 'srcs/juloo.keyboard2/Pointers.java')
-rw-r--r--srcs/juloo.keyboard2/Pointers.java106
1 files changed, 80 insertions, 26 deletions
diff --git a/srcs/juloo.keyboard2/Pointers.java b/srcs/juloo.keyboard2/Pointers.java
index 1011271..f6db9ac 100644
--- a/srcs/juloo.keyboard2/Pointers.java
+++ b/srcs/juloo.keyboard2/Pointers.java
@@ -2,6 +2,7 @@ package juloo.keyboard2;
import android.os.Handler;
import android.os.Message;
+import java.util.Arrays;
import java.util.ArrayList;
/**
@@ -22,21 +23,27 @@ public final class Pointers implements Handler.Callback
_config = c;
}
- public int getFlags()
+ /** Return the list of modifiers currently activated. */
+ public Modifiers getModifiers()
{
- return getFlags(false);
+ return getModifiers(false);
}
- /* When [skip_latched] is true, don't take flags of latched keys into account. */
- private int getFlags(boolean skip_latched)
+ /** When [skip_latched] is true, don't take flags of latched keys into account. */
+ private Modifiers getModifiers(boolean skip_latched)
{
- int flags = 0;
- for (Pointer p : _ptrs)
+ int size = _ptrs.size();
+ int[] mods = new int[size];
+ for (int i = 0; i < size; i++)
{
- if (!(skip_latched && p.pointerId == -1 && (p.flags & KeyValue.FLAG_LOCKED) == 0))
- flags |= p.flags;
+ Pointer p = _ptrs.get(i);
+ mods[i] =
+ ((skip_latched && p.pointerId == -1
+ && (p.flags & KeyValue.FLAG_LOCKED) == 0)
+ || p.value == null)
+ ? 0 : p.value.code;
}
- return flags;
+ return Modifiers.ofArray(mods);
}
public void clear()
@@ -90,7 +97,7 @@ public final class Pointers implements Handler.Callback
else // Otherwise, unlatch
{
removePtr(latched);
- _handler.onPointerUp(ptr.value, ptr.modifier_flags);
+ _handler.onPointerUp(ptr.value, ptr.modifiers);
}
}
else if ((ptr.flags & KeyValue.FLAG_LATCH) != 0)
@@ -103,7 +110,7 @@ public final class Pointers implements Handler.Callback
{
clearLatched();
removePtr(ptr);
- _handler.onPointerUp(ptr.value, ptr.modifier_flags);
+ _handler.onPointerUp(ptr.value, ptr.modifiers);
}
}
@@ -133,9 +140,11 @@ public final class Pointers implements Handler.Callback
// keys.
if (isModulatedKeyPressed())
return;
- int mflags = getFlags(isOtherPointerDown());
- KeyValue value = _handler.modifyKey(key.key0, mflags);
- Pointer ptr = new Pointer(pointerId, key, value, x, y, mflags);
+ // Don't take latched modifiers into account if an other key is pressed.
+ // The other key already "own" the latched modifiers and will clear them.
+ Modifiers mods = getModifiers(isOtherPointerDown());
+ KeyValue value = _handler.modifyKey(key.key0, mods);
+ Pointer ptr = new Pointer(pointerId, key, value, x, y, mods);
_ptrs.add(ptr);
if (value != null && (value.flags & KeyValue.FLAG_SPECIAL) == 0)
startKeyRepeat(ptr);
@@ -153,14 +162,14 @@ public final class Pointers implements Handler.Callback
private KeyValue getKeyAtDirection(Pointer ptr, int direction)
{
if (direction == 0)
- return _handler.modifyKey(ptr.key.key0, ptr.modifier_flags);
+ return _handler.modifyKey(ptr.key.key0, ptr.modifiers);
KeyValue k;
for (int i = 0; i > -3; i = (~i>>31) - i)
{
int d = Math.floorMod(direction + i - 1, 8) + 1;
// Don't make the difference between a key that doesn't exist and a key
// that is removed by [_handler]. Triggers side effects.
- k = _handler.modifyKey(ptr.key.getAtDirection(d), ptr.modifier_flags);
+ k = _handler.modifyKey(ptr.key.getAtDirection(d), ptr.modifiers);
if (k != null)
return k;
}
@@ -292,7 +301,7 @@ public final class Pointers implements Handler.Callback
nextInterval = (long)((float)nextInterval / modulatePreciseRepeat(ptr));
}
_keyrepeat_handler.sendEmptyMessageDelayed(msg.what, nextInterval);
- _handler.onPointerHold(ptr.value, ptr.modifier_flags);
+ _handler.onPointerHold(ptr.value, ptr.modifiers);
return (true);
}
}
@@ -333,7 +342,7 @@ public final class Pointers implements Handler.Callback
return Math.min(8.f, Math.max(0.1f, accel));
}
- private final class Pointer
+ private static final class Pointer
{
/** -1 when latched. */
public int pointerId;
@@ -341,14 +350,14 @@ public final class Pointers implements Handler.Callback
public final KeyboardData.Key key;
/** Current direction. */
public int selected_direction;
- /** Selected value with [modifier_flags] applied. */
+ /** Selected value with [modifiers] applied. */
public KeyValue value;
public float downX;
public float downY;
/** Distance of the pointer to the initial press. */
public float ptrDist;
/** Modifier flags at the time the key was pressed. */
- public int modifier_flags;
+ public Modifiers modifiers;
/** Flags of the value. Latch, lock and locked flags are updated. */
public int flags;
/** Identify timeout messages. */
@@ -356,7 +365,7 @@ public final class Pointers implements Handler.Callback
/** ptrDist at the first repeat, -1 otherwise. */
public float repeatingPtrDist;
- public Pointer(int p, KeyboardData.Key k, KeyValue v, float x, float y, int mflags)
+ public Pointer(int p, KeyboardData.Key k, KeyValue v, float x, float y, Modifiers m)
{
pointerId = p;
key = k;
@@ -365,30 +374,75 @@ public final class Pointers implements Handler.Callback
downX = x;
downY = y;
ptrDist = 0.f;
- modifier_flags = mflags;
+ modifiers = m;
flags = (v == null) ? 0 : v.flags;
timeoutWhat = -1;
repeatingPtrDist = -1.f;
}
}
+ /** Represent modifiers currently activated.
+ Sorted in the order they should be evaluated. */
+ public static final class Modifiers
+ {
+ private final int[] _mods;
+ private final int _size;
+
+ private Modifiers(int[] m, int s) { _mods = m; _size = s; }
+
+ public int get(int i) { return _mods[i]; }
+ public int size() { return _size; }
+
+ @Override
+ public int hashCode() { return Arrays.hashCode(_mods); }
+ @Override
+ public boolean equals(Object obj)
+ {
+ return Arrays.equals(_mods, ((Modifiers)obj)._mods);
+ }
+
+ public static final Modifiers EMPTY = new Modifiers(new int[0], 0);
+
+ protected static Modifiers ofArray(int[] mods)
+ {
+ int size = mods.length;
+ // Sort and remove duplicates and [EVENT_NONE]s.
+ if (size > 1)
+ {
+ Arrays.sort(mods);
+ int j = 0;
+ for (int i = 0; i < size; i++)
+ {
+ int m = mods[i];
+ if (m != 0 && (i + 1 >= size || m != mods[i + 1]))
+ {
+ mods[j] = m;
+ j++;
+ }
+ }
+ size = j;
+ }
+ return new Modifiers(mods, size);
+ }
+ }
+
public interface IPointerEventHandler
{
/** Key can be modified or removed by returning [null]. */
- public KeyValue modifyKey(KeyValue k, int flags);
+ public KeyValue modifyKey(KeyValue k, Modifiers flags);
- /** A key is pressed. [getFlags()] is uptodate. Might be called after a
+ /** A key is pressed. [getModifiers()] is uptodate. Might be called after a
press or a swipe to a different value. */
public void onPointerDown(boolean isSwipe);
/** Key is released. [k] is the key that was returned by
[modifySelectedKey] or [modifySelectedKey]. */
- public void onPointerUp(KeyValue k, int flags);
+ public void onPointerUp(KeyValue k, Modifiers flags);
/** Flags changed because latched or locked keys or cancelled pointers. */
public void onPointerFlagsChanged();
/** Key is repeating. */
- public void onPointerHold(KeyValue k, int flags);
+ public void onPointerHold(KeyValue k, Modifiers flags);
}
}