abouttreesummaryrefslogcommitdiff
path: root/srcs/juloo.keyboard2/Keyboard2View.java
diff options
context:
space:
mode:
authorJules Aguillon2022-02-20 13:09:39 +0100
committerJules Aguillon2022-02-20 13:09:39 +0100
commit51ff795be419ff5102b262c90371340f76c74f2c (patch)
tree36bcf5114d8f41a0e05407b8f5aceac493e47c6a /srcs/juloo.keyboard2/Keyboard2View.java
parent632a9ac590b92a52afe57f1f0aaaa919f9dcebdc (diff)
downloadunexpected-keyboard-51ff795be419ff5102b262c90371340f76c74f2c.tar.gz
unexpected-keyboard-51ff795be419ff5102b262c90371340f76c74f2c.zip
Move pointer handling code to its own class
Separate the concerns and have a clearer interface between the two parts of the code.
Diffstat (limited to 'srcs/juloo.keyboard2/Keyboard2View.java')
-rw-r--r--srcs/juloo.keyboard2/Keyboard2View.java358
1 files changed, 91 insertions, 267 deletions
diff --git a/srcs/juloo.keyboard2/Keyboard2View.java b/srcs/juloo.keyboard2/Keyboard2View.java
index 8123144..8584981 100644
--- a/srcs/juloo.keyboard2/Keyboard2View.java
+++ b/srcs/juloo.keyboard2/Keyboard2View.java
@@ -4,32 +4,27 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
-import android.os.Handler;
-import android.os.Message;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
-import android.widget.PopupWindow;
-import java.util.ArrayList;
public class Keyboard2View extends View
- implements View.OnTouchListener, Handler.Callback
+ implements View.OnTouchListener, Pointers.IPointerEventHandler
{
private static final long VIBRATE_MIN_INTERVAL = 100;
private KeyboardData _keyboard;
- private ArrayList<KeyDown> _downKeys = new ArrayList<KeyDown>();
+ private Pointers _pointers;
private int _flags = 0;
private Vibrator _vibratorService;
private long _lastVibration = 0;
- private Handler _handler;
private static int _currentWhat = 0;
private Config _config;
@@ -51,9 +46,9 @@ public class Keyboard2View extends View
{
super(context, attrs);
_vibratorService = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
- _handler = new Handler(this);
_theme = new Theme(getContext(), attrs);
_config = Config.globalConfig();
+ _pointers = new Pointers(this, _config);
setOnTouchListener(this);
reset();
}
@@ -88,33 +83,74 @@ public class Keyboard2View extends View
public void reset()
{
_flags = 0;
- _downKeys.clear();
+ _pointers.clear();
requestLayout();
invalidate();
}
+ public void onPointerDown(KeyValue k)
+ {
+ updateFlags();
+ invalidate();
+ if (k != null)
+ vibrate();
+ }
+
+ public void onPointerSwipe(KeyValue k)
+ {
+ updateFlags();
+ invalidate();
+ if (k != null)
+ vibrate();
+ }
+
+ public void onPointerUp(KeyValue k)
+ {
+ if (k != null && (k.flags & KeyValue.FLAG_NOCHAR) == 0)
+ _config.handler.handleKeyUp(k, _flags);
+ updateFlags();
+ invalidate();
+ }
+
+ public void onPointerHold(KeyValue k)
+ {
+ if (k != null)
+ _config.handler.handleKeyUp(k, _flags);
+ }
+
+ public void onPointerFlagsChanged()
+ {
+ updateFlags();
+ invalidate();
+ }
+
+ private void updateFlags()
+ {
+ _flags = _pointers.getFlags();
+ }
+
@Override
public boolean onTouch(View v, MotionEvent event)
{
- float x;
- float y;
- float keyW;
int p;
-
switch (event.getActionMasked())
{
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
- onTouchUp(event.getPointerId(event.getActionIndex()));
+ _pointers.onTouchUp(event.getPointerId(event.getActionIndex()));
break ;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
p = event.getActionIndex();
- onTouchDown(event.getX(p), event.getY(p), event.getPointerId(p));
+ float tx = event.getX(p);
+ float ty = event.getY(p);
+ KeyboardData.Key key = getKeyAtPosition(tx, ty);
+ if (key != null)
+ _pointers.onTouchDown(tx, ty, event.getPointerId(p), key);
break ;
case MotionEvent.ACTION_MOVE:
for (p = 0; p < event.getPointerCount(); p++)
- onTouchMove(event.getX(p), event.getY(p), event.getPointerId(p));
+ _pointers.onTouchMove(event.getX(p), event.getY(p), event.getPointerId(p));
break ;
default:
return (false);
@@ -122,197 +158,33 @@ public class Keyboard2View extends View
return (true);
}
- private KeyDown getKeyDown(int pointerId)
- {
- for (KeyDown k : _downKeys)
- {
- if (k.pointerId == pointerId)
- return (k);
- }
- return (null);
- }
-
- private KeyDown getKeyDown(KeyboardData.Key key)
- {
- for (KeyDown k : _downKeys)
- {
- if (k.key == key)
- return (k);
- }
- return (null);
- }
-
- private KeyDown getKeyDown(KeyValue kv)
- {
- for (KeyDown k : _downKeys)
- {
- if (k.value == kv)
- return (k);
- }
- return (null);
- }
-
- private void onTouchMove(float moveX, float moveY, int pointerId)
- {
- KeyDown key = getKeyDown(pointerId);
- KeyValue newValue;
-
- if (key != null)
- {
- moveX -= key.downX;
- moveY -= key.downY;
- float absDist = Math.abs(moveX) + Math.abs(moveY);
- key.ptrDist = absDist;
- if (absDist < _config.swipe_dist_px)
- {
- newValue = key.key.key0;
- }
- else if (key.key.edgekeys)
- {
- if (Math.abs(moveY) > Math.abs(moveX)) // vertical swipe
- newValue = (moveY < 0) ? key.key.key1 : key.key.key4;
- else if (moveX < 0) // left swipe
- newValue = key.key.key3;
- else // right swipe
- newValue = key.key.key2;
- }
- else
- {
- if (moveX < 0)
- newValue = (moveY < 0) ? key.key.key1 : key.key.key3;
- else if (moveY < 0)
- newValue = key.key.key2;
- else
- newValue = key.key.key4;
- }
- if (newValue != null && newValue != key.value)
- {
- if (key.timeoutWhat != -1)
- {
- _handler.removeMessages(key.timeoutWhat);
- if ((newValue.flags & KeyValue.FLAG_NOREPEAT) == 0)
- _handler.sendEmptyMessageDelayed(key.timeoutWhat, _config.longPressTimeout);
- }
- key.value = newValue;
- key.flags = newValue.flags;
- updateFlags();
- invalidate();
- handleKeyDown(newValue);
- }
- }
- }
-
- private void onTouchDown(float touchX, float touchY, int pointerId)
+ private KeyboardData.Row getRowAtPosition(float ty)
{
- float y = _config.marginTop - _config.keyHeight;
+ float y = _config.marginTop;
+ if (ty < y)
+ return null;
for (KeyboardData.Row row : _keyboard.rows)
{
- y += _config.keyHeight;
- if (touchY < y || touchY >= (y + _config.keyHeight))
- continue ;
- float x = _config.horizontalMargin;
- for (KeyboardData.Key key : row.keys)
- {
- x += key.shift * _keyWidth;
- float keyW = _keyWidth * key.width;
- if (touchX >= x && touchX < (x + keyW))
- {
- int what = _currentWhat++;
- if (key.key0 != null && (key.key0.flags & KeyValue.FLAG_NOREPEAT) == 0)
- _handler.sendEmptyMessageDelayed(what, _config.longPressTimeout);
- _downKeys.add(new KeyDown(pointerId, key, touchX, touchY, what));
- handleKeyDown(key.key0);
- updateFlags();
- invalidate();
- return ;
- }
- x += keyW;
- }
- }
- }
-
- // Whether a key is already activated (key down but pointer up)
- private KeyDown getActivatedKey(KeyValue kv)
- {
- for (KeyDown k : _downKeys)
- {
- if (k.value == kv && k.pointerId == -1)
- return (k);
+ y += (row.shift + row.height) * _config.keyHeight;
+ if (ty < y)
+ return row;
}
- return (null);
+ return null;
}
- private void onTouchUp(int pointerId)
+ private KeyboardData.Key getKeyAtPosition(float tx, float ty)
{
- KeyDown k = getKeyDown(pointerId);
-
- if (k != null)
+ KeyboardData.Row row = getRowAtPosition(ty);
+ float x = _config.horizontalMargin;
+ if (row == null || tx < x)
+ return null;
+ for (KeyboardData.Key key : row.keys)
{
- // Stop key repeat
- if (k.timeoutWhat != -1)
- {
- _handler.removeMessages(k.timeoutWhat);
- k.timeoutWhat = -1;
- }
- KeyDown k_on = getActivatedKey(k.value);
- if (k_on != null)
- {
- _downKeys.remove(k); // Remove dupplicate
- // Same key with FLAG_LOCK is already on, do lock
- if ((k_on.flags & KeyValue.FLAG_LOCK) != 0)
- {
- k_on.flags ^= KeyValue.FLAG_LOCK; // Next time, disable it
- k_on.flags |= KeyValue.FLAG_LOCKED;
- }
- // Otherwise, toggle it
- else
- {
- _downKeys.remove(k_on);
- }
- }
- // Key stay activated
- else if ((k.flags & KeyValue.FLAG_KEEP_ON) != 0)
- {
- k.pointerId = -1; // Set pointer up
- }
- else // Regular key up
- {
- for (int i = 0; i < _downKeys.size(); i++)
- {
- KeyDown downKey = _downKeys.get(i);
- // Disable other activated keys that aren't locked
- if (downKey.pointerId == -1 && (downKey.flags & KeyValue.FLAG_LOCKED) == 0)
- _downKeys.remove(i--);
- // Other keys currently down won't stay activated
- else if ((downKey.flags & KeyValue.FLAG_KEEP_ON) != 0)
- downKey.flags ^= KeyValue.FLAG_KEEP_ON;
- }
- _downKeys.remove(k);
- handleKeyUp(k);
- }
- updateFlags();
- invalidate();
+ x += (key.shift + key.width) * _keyWidth;
+ if (tx < x)
+ return key;
}
- }
-
- private void handleKeyUp(KeyDown key)
- {
- if (key.value != null && (key.flags & (KeyValue.FLAG_LOCKED | KeyValue.FLAG_NOCHAR)) == 0)
- _config.handler.handleKeyUp(key.value, _flags);
- }
-
- private void handleKeyDown(KeyValue key)
- {
- if (key == null)
- return ;
- vibrate();
- }
-
- private void updateFlags()
- {
- _flags = 0;
- for (KeyDown k : _downKeys)
- _flags |= k.flags;
+ return null;
}
private void vibrate()
@@ -335,28 +207,6 @@ public class Keyboard2View extends View
}
@Override
- public boolean handleMessage(Message msg)
- {
- for (KeyDown key : _downKeys)
- {
- if (key.timeoutWhat == msg.what)
- {
- long nextInterval = _config.longPressInterval;
- if (_config.preciseRepeat && (key.flags & KeyValue.FLAG_PRECISE_REPEAT) != 0)
- {
- // Modulate repeat interval depending on the distance of the pointer
- float accel = Math.min(4.f, Math.max(0.3f, key.ptrDist / (_config.swipe_dist_px * 15.f)));
- nextInterval = (long)((float)nextInterval / accel);
- }
- _handler.sendEmptyMessageDelayed(msg.what, nextInterval);
- _config.handler.handleKeyUp(key.value, _flags);
- return (true);
- }
- }
- return (false);
- }
-
- @Override
public void onMeasure(int wSpec, int hSpec)
{
DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
@@ -382,34 +232,34 @@ public class Keyboard2View extends View
{
x += k.shift * _keyWidth;
float keyW = _keyWidth * k.width - _config.keyHorizontalInterval;
- KeyDown keyDown = getKeyDown(k);
+ boolean isKeyDown = _pointers.isKeyDown(k);
_tmpRect.set(x, y, x + keyW, y + keyH);
canvas.drawRoundRect(_tmpRect, _theme.keyBorderRadius, _theme.keyBorderRadius,
- (keyDown != null) ? _theme.keyDownBgPaint : _theme.keyBgPaint);
+ isKeyDown ? _theme.keyDownBgPaint : _theme.keyBgPaint);
if (k.key0 != null)
- drawLabel(canvas, k.key0, keyW / 2f + x, (keyH + _theme.labelTextSize) / 2f + y, keyDown);
+ drawLabel(canvas, k.key0, keyW / 2f + x, (keyH + _theme.labelTextSize) / 2f + y, isKeyDown);
float subPadding = _config.keyPadding;
if (k.edgekeys)
{
if (k.key1 != null) // top key
- drawSubLabel(canvas, k.key1, x + keyW / 2f, y + subPadding, Paint.Align.CENTER, Vertical.TOP, keyDown);
+ drawSubLabel(canvas, k.key1, x + keyW / 2f, y + subPadding, Paint.Align.CENTER, Vertical.TOP, isKeyDown);
if (k.key3 != null) // left key
- drawSubLabel(canvas, k.key3, x + subPadding, y + keyH / 2f, Paint.Align.LEFT, Vertical.CENTER, keyDown);
+ drawSubLabel(canvas, k.key3, x + subPadding, y + keyH / 2f, Paint.Align.LEFT, Vertical.CENTER, isKeyDown);
if (k.key2 != null) // right key
- drawSubLabel(canvas, k.key2, x + keyW - subPadding, y + keyH / 2f, Paint.Align.RIGHT, Vertical.CENTER, keyDown);
+ drawSubLabel(canvas, k.key2, x + keyW - subPadding, y + keyH / 2f, Paint.Align.RIGHT, Vertical.CENTER, isKeyDown);
if (k.key4 != null) // bottom key
- drawSubLabel(canvas, k.key4, x + keyW / 2f, y + keyH - subPadding, Paint.Align.CENTER, Vertical.BOTTOM, keyDown);
+ drawSubLabel(canvas, k.key4, x + keyW / 2f, y + keyH - subPadding, Paint.Align.CENTER, Vertical.BOTTOM, isKeyDown);
}
else
{
if (k.key1 != null) // top left key
- drawSubLabel(canvas, k.key1, x + subPadding, y + subPadding, Paint.Align.LEFT, Vertical.TOP, keyDown);
+ drawSubLabel(canvas, k.key1, x + subPadding, y + subPadding, Paint.Align.LEFT, Vertical.TOP, isKeyDown);
if (k.key3 != null) // bottom left key
- drawSubLabel(canvas, k.key3, x + subPadding, y + keyH - subPadding, Paint.Align.LEFT, Vertical.BOTTOM, keyDown);
+ drawSubLabel(canvas, k.key3, x + subPadding, y + keyH - subPadding, Paint.Align.LEFT, Vertical.BOTTOM, isKeyDown);
if (k.key2 != null) // top right key
- drawSubLabel(canvas, k.key2, x + keyW - subPadding, y + subPadding, Paint.Align.RIGHT, Vertical.TOP, keyDown);
+ drawSubLabel(canvas, k.key2, x + keyW - subPadding, y + subPadding, Paint.Align.RIGHT, Vertical.TOP, isKeyDown);
if (k.key4 != null) // bottom right key
- drawSubLabel(canvas, k.key4, x + keyW - subPadding, y + keyH - subPadding, Paint.Align.RIGHT, Vertical.BOTTOM, keyDown);
+ drawSubLabel(canvas, k.key4, x + keyW - subPadding, y + keyH - subPadding, Paint.Align.RIGHT, Vertical.BOTTOM, isKeyDown);
}
x += _keyWidth * k.width;
}
@@ -423,36 +273,36 @@ public class Keyboard2View extends View
super.onDetachedFromWindow();
}
- private int labelColor(KeyValue k, KeyDown hasKeyDown, int defaultColor)
+ private int labelColor(KeyValue k, boolean isKeyDown, int defaultColor)
{
- if (hasKeyDown != null)
+ if (isKeyDown && (k.flags & KeyValue.FLAG_LATCH) != 0)
{
- KeyDown kd = getKeyDown(k);
- if (kd != null)
+ int flags = _pointers.getKeyFlags(k);
+ if (flags != -1)
{
- if ((kd.flags & KeyValue.FLAG_LOCKED) != 0)
+ if ((flags & KeyValue.FLAG_LOCKED) != 0)
return _theme.lockedColor;
- if (kd.pointerId == -1)
+ if ((flags & KeyValue.FLAG_LATCH) == 0)
return _theme.activatedColor;
}
}
return defaultColor;
}
- private void drawLabel(Canvas canvas, KeyValue k, float x, float y, KeyDown keyDown)
+ private void drawLabel(Canvas canvas, KeyValue k, float x, float y, boolean isKeyDown)
{
k = KeyModifier.handleFlags(k, _flags);
Paint p = _theme.labelPaint(((k.flags & KeyValue.FLAG_KEY_FONT) != 0));
- p.setColor(labelColor(k, keyDown, _theme.labelColor));
+ p.setColor(labelColor(k, isKeyDown, _theme.labelColor));
p.setTextSize(_theme.labelTextSize * scaleTextSize(k));
canvas.drawText(k.symbol, x, y, p);
}
- private void drawSubLabel(Canvas canvas, KeyValue k, float x, float y, Paint.Align a, Vertical v, KeyDown keyDown)
+ private void drawSubLabel(Canvas canvas, KeyValue k, float x, float y, Paint.Align a, Vertical v, boolean isKeyDown)
{
k = KeyModifier.handleFlags(k, _flags);
Paint p = _theme.subLabelPaint(((k.flags & KeyValue.FLAG_KEY_FONT) != 0), a);
- p.setColor(labelColor(k, keyDown, _theme.subLabelColor));
+ p.setColor(labelColor(k, isKeyDown, _theme.subLabelColor));
p.setTextSize(_theme.sublabelTextSize * scaleTextSize(k));
if (v == Vertical.CENTER)
y -= (p.ascent() + p.descent()) / 2f;
@@ -465,30 +315,4 @@ public class Keyboard2View extends View
{
return ((k.symbol.length() < 2) ? 1.f : 0.8f) * _config.characterSize;
}
-
- private static class KeyDown
- {
- /* -1 if pointer is up. */
- public int pointerId;
- public KeyValue value;
- public KeyboardData.Key key;
- public float downX;
- public float downY;
- /* Manhattan distance of the pointer to the center of the key */
- public float ptrDist;
- public int flags;
- public int timeoutWhat;
-
- public KeyDown(int pointerId, KeyboardData.Key key, float x, float y, int what)
- {
- this.pointerId = pointerId;
- value = key.key0;
- this.key = key;
- downX = x;
- downY = y;
- ptrDist = 0.f;
- flags = (value == null) ? 0 : value.flags;
- timeoutWhat = what;
- }
- }
}