Better handling of removed keys and swipe geture

The "closest key" logic must be careful not to reveal keys removed by a
modifier.

Must check [_handler.onPointerSwipe] for every candidate values.
[selected_value] is changed back to [selected_direction].

This adds a new bug: When the direction change, the selected value might
not change but a vibration will be triggered anyway.
This commit is contained in:
Jules Aguillon 2022-05-08 16:38:44 +02:00
parent 9a48acfe3e
commit b15ca662c2
3 changed files with 42 additions and 34 deletions

View File

@ -108,9 +108,11 @@ public class Keyboard2View extends View
public KeyValue onPointerSwipe(KeyValue k, int flags) public KeyValue onPointerSwipe(KeyValue k, int flags)
{ {
k = KeyModifier.handleFlags(k, flags); k = KeyModifier.handleFlags(k, flags);
invalidate();
if (k != null) if (k != null)
{
invalidate();
vibrate(); vibrate();
}
return k; return k;
} }

View File

@ -195,7 +195,10 @@ class KeyboardData
return new Key(key0, key1, key2, key3, key4, width * s, shift, edgekeys); return new Key(key0, key1, key2, key3, key4, width * s, shift, edgekeys);
} }
private KeyValue getAtDirectionExact(int direction) /*
* See Pointers.onTouchMove() for the represented direction.
*/
public KeyValue getAtDirection(int direction)
{ {
if (edgekeys) if (edgekeys)
{ {
@ -229,25 +232,6 @@ class KeyboardData
} }
return null; return null;
} }
/*
* Get the KeyValue at the given direction. In case of swipe (!= 0), get the
* nearest KeyValue that is not key0. See Pointers.onTouchMove() for the
* represented direction.
*/
public KeyValue getAtDirection(int direction)
{
if (direction == 0)
return key0;
KeyValue k;
for (int i = 0; i > -2; i = (~i>>31) - i)
{
k = getAtDirectionExact(Math.floorMod(direction + i - 1, 8) + 1);
if (k != null)
return k;
}
return null;
}
} }
// Not using Function<KeyValue, KeyValue> to keep compatibility with Android 6. // Not using Function<KeyValue, KeyValue> to keep compatibility with Android 6.

View File

@ -135,12 +135,37 @@ public final class Pointers implements Handler.Callback
return; return;
int mflags = getFlags(isOtherPointerDown()); int mflags = getFlags(isOtherPointerDown());
KeyValue value = _handler.onPointerDown(key.key0, mflags); KeyValue value = _handler.onPointerDown(key.key0, mflags);
Pointer ptr = new Pointer(pointerId, key, key.key0, value, x, y, mflags); Pointer ptr = new Pointer(pointerId, key, value, x, y, mflags);
_ptrs.add(ptr); _ptrs.add(ptr);
if (value != null && (value.flags & KeyValue.FLAG_SPECIAL) == 0) if (value != null && (value.flags & KeyValue.FLAG_SPECIAL) == 0)
startKeyRepeat(ptr); startKeyRepeat(ptr);
} }
/*
* Get the KeyValue at the given direction. In case of swipe (!= 0), get the
* nearest KeyValue that is not key0.
* Take care of applying [_handler.onPointerSwipe] to the selected key, this
* must be done at the same time to be sure to treat removed keys correctly.
* Return [null] if no key could be found in the given direction or if the
* selected key didn't change.
*/
private KeyValue getKeyAtDirection(Pointer ptr, int direction)
{
if (direction == 0)
return _handler.onPointerSwipe(ptr.key.key0, ptr.modifier_flags);
KeyValue k;
for (int i = 0; i > -2; 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.onPointerSwipe(ptr.key.getAtDirection(d), ptr.modifier_flags);
if (k != null)
return k;
}
return null;
}
public void onTouchMove(float x, float y, int pointerId) public void onTouchMove(float x, float y, int pointerId)
{ {
Pointer ptr = getPtr(pointerId); Pointer ptr = getPtr(pointerId);
@ -175,14 +200,11 @@ public final class Pointers implements Handler.Callback
if (dy > 0) direction = 9 - direction; if (dy > 0) direction = 9 - direction;
} }
KeyValue newSelectedValue = ptr.key.getAtDirection(direction); if (direction != ptr.selected_direction)
if (newSelectedValue != ptr.selected_value)
{ {
ptr.selected_value = newSelectedValue; ptr.selected_direction = direction;
// apply modifier flags and trigger vibration. KeyValue newValue = getKeyAtDirection(ptr, direction);
KeyValue newValue = if (newValue != null && (ptr.value == null || newValue.name != ptr.value.name))
_handler.onPointerSwipe(ptr.selected_value, ptr.modifier_flags);
if (newValue != null)
{ {
int old_flags = ptr.flags; int old_flags = ptr.flags;
ptr.value = newValue; ptr.value = newValue;
@ -315,9 +337,9 @@ public final class Pointers implements Handler.Callback
public int pointerId; public int pointerId;
/** The Key pressed by this Pointer */ /** The Key pressed by this Pointer */
public final KeyboardData.Key key; public final KeyboardData.Key key;
/** The current seletected KeyValue in key (any one of key0 to key4). */ /** Current direction. */
public KeyValue selected_value; public int selected_direction;
/** selected_value with modifier_flags applied. */ /** Selected value with [modifier_flags] applied. */
public KeyValue value; public KeyValue value;
public float downX; public float downX;
public float downY; public float downY;
@ -332,11 +354,11 @@ public final class Pointers implements Handler.Callback
/** ptrDist at the first repeat, -1 otherwise. */ /** ptrDist at the first repeat, -1 otherwise. */
public float repeatingPtrDist; public float repeatingPtrDist;
public Pointer(int p, KeyboardData.Key k, KeyValue sv, KeyValue v, float x, float y, int mflags) public Pointer(int p, KeyboardData.Key k, KeyValue v, float x, float y, int mflags)
{ {
pointerId = p; pointerId = p;
key = k; key = k;
selected_value = sv; selected_direction = 0;
value = v; value = v;
downX = x; downX = x;
downY = y; downY = y;