abouttreesummaryrefslogcommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/xml/qwerty.xml21
-rw-r--r--srcs/juloo.keyboard2/KeyValue.java9
-rw-r--r--srcs/juloo.keyboard2/Keyboard2View.java40
-rw-r--r--srcs/juloo.keyboard2/KeyboardData.java177
-rw-r--r--srcs/juloo.keyboard2/Pointers.java83
5 files changed, 166 insertions, 164 deletions
diff --git a/res/xml/qwerty.xml b/res/xml/qwerty.xml
index 87b56f5..4f5245b 100644
--- a/res/xml/qwerty.xml
+++ b/res/xml/qwerty.xml
@@ -1,4 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- This file defines the QWERTY layout.
+
+A layout is made of keys arranged into rows. Keys can be made bigger with the
+'width' attribute and blank space can be added on the left of a key with the
+'shift' attribute.
+
+'key0' assigns the symbol on the middle of the key. 'key1', 'key2', etc..
+assign symbols to the corners of a key, they are arranged like this:
+
+ 1 7 2
+ 5 0 6
+ 3 8 4
+
+Keys prefixed with 'loc ' are not visible on the keyboard. They are used to
+specify a place for a key, if it needed to be added to the layout later.
+(for example, by the "Add keys to keyboard" option)
+
+See bottom_row.xml for the definition of the bottom row and neo2.xml for a
+layout that re-defines it.
+See srcs/juloo.keyboard2/KeyValue.java for the keys that have a special meaning.
+-->
<keyboard>
<row>
<key key0="q" key2="1" key4="esc"/>
diff --git a/srcs/juloo.keyboard2/KeyValue.java b/srcs/juloo.keyboard2/KeyValue.java
index c4bd069..3e84ce8 100644
--- a/srcs/juloo.keyboard2/KeyValue.java
+++ b/srcs/juloo.keyboard2/KeyValue.java
@@ -202,7 +202,14 @@ final class KeyValue
@Override
public boolean equals(Object obj)
{
- KeyValue snd = (KeyValue)obj;
+ return sameKey((KeyValue)obj);
+ }
+
+ /** Type-safe alternative to [equals]. */
+ public boolean sameKey(KeyValue snd)
+ {
+ if (snd == null)
+ return false;
return _symbol.equals(snd._symbol) && _code == snd._code;
}
diff --git a/srcs/juloo.keyboard2/Keyboard2View.java b/srcs/juloo.keyboard2/Keyboard2View.java
index 3c642f0..0a75529 100644
--- a/srcs/juloo.keyboard2/Keyboard2View.java
+++ b/srcs/juloo.keyboard2/Keyboard2View.java
@@ -260,6 +260,19 @@ public class Keyboard2View extends View
}
}
+ /** Horizontal and vertical position of the 9 indexes. */
+ static final Paint.Align[] LABEL_POSITION_H = new Paint.Align[]{
+ Paint.Align.CENTER, Paint.Align.LEFT, Paint.Align.RIGHT, Paint.Align.LEFT,
+ Paint.Align.RIGHT, Paint.Align.LEFT, Paint.Align.RIGHT,
+ Paint.Align.CENTER, Paint.Align.CENTER
+ };
+
+ static final Vertical[] LABEL_POSITION_V = new Vertical[]{
+ Vertical.CENTER, Vertical.TOP, Vertical.TOP, Vertical.BOTTOM,
+ Vertical.BOTTOM, Vertical.CENTER, Vertical.CENTER, Vertical.TOP,
+ Vertical.BOTTOM
+ };
+
@Override
protected void onDraw(Canvas canvas)
{
@@ -282,20 +295,12 @@ public class Keyboard2View extends View
float keyW = _keyWidth * k.width - _config.keyHorizontalInterval;
boolean isKeyDown = _pointers.isKeyDown(k);
drawKeyFrame(canvas, x, y, keyW, keyH, isKeyDown);
- drawLabel(canvas, k.key0, keyW / 2f + x, y, keyH, isKeyDown);
- if (k.edgekeys)
- {
- drawSubLabel(canvas, k.key1, x, y, keyW, keyH, Paint.Align.CENTER, Vertical.TOP, isKeyDown);
- drawSubLabel(canvas, k.key3, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.CENTER, isKeyDown);
- drawSubLabel(canvas, k.key2, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.CENTER, isKeyDown);
- drawSubLabel(canvas, k.key4, x, y, keyW, keyH, Paint.Align.CENTER, Vertical.BOTTOM, isKeyDown);
- }
- else
+ if (k.keys[0] != null)
+ drawLabel(canvas, k.keys[0], keyW / 2f + x, y, keyH, isKeyDown);
+ for (int i = 1; i < 9; i++)
{
- drawSubLabel(canvas, k.key1, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.TOP, isKeyDown);
- drawSubLabel(canvas, k.key3, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.BOTTOM, isKeyDown);
- drawSubLabel(canvas, k.key2, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.TOP, isKeyDown);
- drawSubLabel(canvas, k.key4, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.BOTTOM, isKeyDown);
+ if (k.keys[i] != null)
+ drawSubLabel(canvas, k.keys[i], x, y, keyW, keyH, i, isKeyDown);
}
if (k.indication != null)
{
@@ -367,8 +372,6 @@ public class Keyboard2View extends View
private void drawLabel(Canvas canvas, KeyboardData.Corner k, float x, float y, float keyH, boolean isKeyDown)
{
- if (k == null)
- return;
KeyValue kv = KeyModifier.modify(k.kv, _mods);
if (kv == null)
return;
@@ -381,11 +384,10 @@ public class Keyboard2View extends View
}
private void drawSubLabel(Canvas canvas, KeyboardData.Corner k, float x,
- float y, float keyW, float keyH, Paint.Align a, Vertical v,
- boolean isKeyDown)
+ float y, float keyW, float keyH, int sub_index, boolean isKeyDown)
{
- if (k == null)
- return;
+ Paint.Align a = LABEL_POSITION_H[sub_index];
+ Vertical v = LABEL_POSITION_V[sub_index];
KeyValue kv = KeyModifier.modify(k.kv, _mods);
if (kv == null)
return;
diff --git a/srcs/juloo.keyboard2/KeyboardData.java b/srcs/juloo.keyboard2/KeyboardData.java
index 1c5de76..aa215db 100644
--- a/srcs/juloo.keyboard2/KeyboardData.java
+++ b/srcs/juloo.keyboard2/KeyboardData.java
@@ -5,6 +5,7 @@ import android.content.res.XmlResourceParser;
import android.util.Xml;
import java.io.StringReader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -278,50 +279,44 @@ class KeyboardData
public static class Key
{
- /*
- ** 1 2
- ** 0
- ** 3 4
+ /**
+ * 1 7 2
+ * 5 0 6
+ * 3 8 4
*/
- public final Corner key0;
- public final Corner key1;
- public final Corner key2;
- public final Corner key3;
- public final Corner key4;
+ public final Corner[] keys;
/** Key width in relative unit. */
public final float width;
/** Extra empty space on the left of the key. */
public final float shift;
- /** Put keys 1 to 4 on the edges instead of the corners. */
- public final boolean edgekeys;
/** Keys 2 and 3 are repeated as the finger moves laterally on the key.
Used for the left and right arrow keys on the space bar. */
public final boolean slider;
/** String printed on the keys. It has no other effect. */
public final String indication;
- protected Key(Corner k0, Corner k1, Corner k2, Corner k3, Corner k4, float w, float s, boolean e, boolean sl, String i)
+ protected Key(Corner[] ks, float w, float s, boolean sl, String i)
{
- key0 = k0;
- key1 = k1;
- key2 = k2;
- key3 = k3;
- key4 = k4;
+ keys = ks;
width = w;
shift = s;
- edgekeys = e;
slider = sl;
indication = i;
}
public static Key parse(XmlPullParser parser) throws Exception
{
- Corner k0 = Corner.parse_of_attr(parser, "key0");
- Corner k1 = Corner.parse_of_attr(parser, "key1");
- Corner k2 = Corner.parse_of_attr(parser, "key2");
- Corner k3 = Corner.parse_of_attr(parser, "key3");
- Corner k4 = Corner.parse_of_attr(parser, "key4");
+ Corner[] ks = new Corner[9];
+ ks[0] = Corner.parse_of_attr(parser, "key0");
+ ks[1] = Corner.parse_of_attr(parser, "key1");
+ ks[2] = Corner.parse_of_attr(parser, "key2");
+ ks[3] = Corner.parse_of_attr(parser, "key3");
+ ks[4] = Corner.parse_of_attr(parser, "key4");
+ ks[5] = Corner.parse_of_attr(parser, "key5");
+ ks[6] = Corner.parse_of_attr(parser, "key6");
+ ks[7] = Corner.parse_of_attr(parser, "key7");
+ ks[8] = Corner.parse_of_attr(parser, "key8");
float width = attribute_float(parser, "width", 1f);
float shift = attribute_float(parser, "shift", 0.f);
boolean edgekeys = attribute_bool(parser, "edgekeys", false);
@@ -329,112 +324,86 @@ class KeyboardData
String indication = parser.getAttributeValue(null, "indication");
while (parser.next() != XmlPullParser.END_TAG)
continue ;
- return new Key(k0, k1, k2, k3, k4, width, shift, edgekeys, slider, indication);
+ if (edgekeys)
+ ks = rearange_edgekeys(ks);
+ return new Key(ks, width, shift, slider, indication);
}
/** New key with the width multiplied by 's'. */
public Key scaleWidth(float s)
{
- return new Key(key0, key1, key2, key3, key4, width * s, shift, edgekeys,
- slider, indication);
+ return new Key(keys, width * s, shift, slider, indication);
}
public void getKeys(Set<KeyValue> dst)
{
- getCorner(dst, key0);
- getCorner(dst, key1);
- getCorner(dst, key2);
- getCorner(dst, key3);
- getCorner(dst, key4);
+ for (int i = 0; i < keys.length; i++)
+ if (keys[i] != null)
+ dst.add(keys[i].kv);
}
- void getCorner(Set<KeyValue> dst, Corner k) { if (k != null) dst.add(k.kv); }
-
public KeyValue getKeyValue(int i)
{
- Corner c;
- switch (i)
- {
- case 0: c = key0; break;
- case 1: c = key1; break;
- case 2: c = key2; break;
- case 3: c = key3; break;
- case 4: c = key4; break;
- default: c = null; break;
- }
- return (c == null) ? null : c.kv;
+ if (keys[i] == null)
+ return null;
+ return keys[i].kv;
}
public Key withKeyValue(int i, KeyValue kv)
{
- Corner k0 = key0, k1 = key1, k2 = key2, k3 = key3, k4 = key4;
- Corner k = Corner.of_kv(kv);
- switch (i)
- {
- case 0: k0 = k; break;
- case 1: k1 = k; break;
- case 2: k2 = k; break;
- case 3: k3 = k; break;
- case 4: k4 = k; break;
- }
- return new Key(k0, k1, k2, k3, k4, width, shift, edgekeys, slider,
- indication);
+ Corner[] ks = Arrays.copyOf(keys, keys.length);
+ ks[i] = Corner.of_kv(kv);
+ return new Key(ks, width, shift, slider, indication);
}
public Key withShift(float s)
{
- return new Key(key0, key1, key2, key3, key4, width, s, edgekeys, slider,
- indication);
+ return new Key(keys, width, s, slider, indication);
}
- /**
- * See Pointers.onTouchMove() for the represented direction.
- */
- public KeyValue getAtDirection(int direction)
+ public boolean hasValue(KeyValue kv)
{
- Corner c = null;
- if (edgekeys)
- {
- // \ 1 /
- // \ /
- // 3 0 2
- // / \
- // / 4 \
- switch (direction)
- {
- case 2: case 3: c = key1; break;
- case 4: case 5: c = key2; break;
- case 6: case 7: c = key4; break;
- case 8: case 1: c = key3; break;
- }
- }
- else
- {
- // 1 | 2
- // |
- // --0--
- // |
- // 3 | 4
- switch (direction)
- {
- case 1: case 2: c = key1; break;
- case 3: case 4: c = key2; break;
- case 5: case 6: c = key4; break;
- case 7: case 8: c = key3; break;
- }
- }
- return (c == null) ? null : c.kv;
+ for (int i = 0; i < keys.length; i++)
+ if (keys[i] != null && keys[i].kv.equals(kv))
+ return true;
+ return false;
}
- public boolean hasValue(KeyValue kv)
+ public boolean hasValue(KeyValue kv, int i)
{
- return (hasValue(key0, kv) || hasValue(key1, kv) || hasValue(key2, kv) ||
- hasValue(key3, kv) || hasValue(key4, kv));
+ if (keys[i] == null)
+ return false;
+ return kv.equals(keys[i].kv);
}
- private static boolean hasValue(Corner c, KeyValue kv)
+ /** Transform the key index for edgekeys.
+ * This option is no longer useful but is used by some layouts.
+ * 1 7 2 5 1 7
+ * 5 0 6 → 3 0 2
+ * 3 8 4 8 4 6
+ */
+ static Corner[] rearange_edgekeys(Corner[] ks)
{
- return (c != null && c.kv.equals(kv));
+ Corner[] edge_ks = new Corner[ks.length];
+ for (int i = 0; i < ks.length; i++)
+ edge_ks[edgekey_index(i)] = ks[i];
+ return edge_ks;
+ }
+
+ static int edgekey_index(int i)
+ {
+ switch (i)
+ {
+ case 5: return 1;
+ case 1: return 7;
+ case 7: return 2;
+ case 3: return 5;
+ case 2: return 6;
+ case 8: return 3;
+ case 4: return 8;
+ case 6: return 4;
+ default: return i;
+ }
}
}
@@ -491,15 +460,15 @@ class KeyboardData
public Key apply(Key k)
{
- return new Key(apply(k.key0), apply(k.key1), apply(k.key2),
- apply(k.key3), apply(k.key4), k.width, k.shift, k.edgekeys,
- k.slider, k.indication);
+ Corner[] ks = new Corner[k.keys.length];
+ for (int i = 0; i < ks.length; i++)
+ if (k.keys[i] != null)
+ ks[i] = apply(k.keys[i]);
+ return new Key(ks, k.width, k.shift, k.slider, k.indication);
}
protected Corner apply(Corner c)
{
- if (c == null)
- return null;
KeyValue kv = apply(c.kv, c.localized);
return (kv == null) ? null : new Corner(kv, c.localized);
}
diff --git a/srcs/juloo.keyboard2/Pointers.java b/srcs/juloo.keyboard2/Pointers.java
index 51319ca..b9e4d07 100644
--- a/srcs/juloo.keyboard2/Pointers.java
+++ b/srcs/juloo.keyboard2/Pointers.java
@@ -167,32 +167,49 @@ public final class Pointers implements Handler.Callback
// 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 = handleKV(key.key0, mods);
+ KeyValue value = handleKV(key.keys[0], mods);
Pointer ptr = new Pointer(pointerId, key, value, x, y, mods);
_ptrs.add(ptr);
startKeyRepeat(ptr);
_handler.onPointerDown(false);
}
+ static final int[] DIRECTION_TO_INDEX = new int[]{
+ 7, 2, 2, 6, 6, 4, 4, 8, 8, 3, 3, 5, 5, 1, 1, 7
+ };
+
+ /**
+ * [direction] is an int between [0] and [15] that represent 16 sections of a
+ * circle, clockwise, starting at the top.
+ */
+ KeyValue getKeyAtDirection(KeyboardData.Key k, int direction)
+ {
+ int i = DIRECTION_TO_INDEX[direction];
+ if (k.keys[i] == null)
+ return null;
+ return k.keys[i].kv;
+ }
+
/*
- * Get the KeyValue at the given direction. In case of swipe (!= 0), get the
- * nearest KeyValue that is not key0.
+ * Get the KeyValue at the given direction. In case of swipe (direction !=
+ * null), 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)
+ private KeyValue getNearestKeyAtDirection(Pointer ptr, Integer direction)
{
- if (direction == 0)
- return handleKV(ptr.key.key0, ptr.modifiers);
+ if (direction == null)
+ return handleKV(ptr.key.keys[0], ptr.modifiers);
KeyValue k;
- for (int i = 0; i > -3; i = (~i>>31) - i)
+ // [i] is [0, -1, 1, -2, 2, ...]
+ for (int i = 0; i > -4; i = (~i>>31) - i)
{
- int d = (direction + i + 8 - 1) % 8 + 1;
+ int d = (direction + i + 16 - 1) % 16;
// 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.modifiers);
+ k = _handler.modifyKey(getKeyAtDirection(ptr.key, d), ptr.modifiers);
if (k != null)
return k;
}
@@ -225,45 +242,32 @@ public final class Pointers implements Handler.Callback
}
float dist = Math.abs(dx) + Math.abs(dy);
- int direction;
+ Integer direction;
if (dist < _config.swipe_dist_px)
{
- direction = 0;
+ direction = null;
}
else
{
- // One of the 8 directions:
- // |\2|3/|
- // |1\|/4|
- // |-----|
- // |8/|\5|
- // |/7|6\|
- direction = 1;
- if (dx > 0) direction += 2;
- if (dx > Math.abs(dy) || (dx < 0 && dx > -Math.abs(dy))) direction += 1;
- if (dy > 0) direction = 9 - direction;
+ // See [getKeyAtDirection()] for the meaning. The starting point on the
+ // circle is the top direction.
+ double a = Math.atan2(dy, dx); // between -pi and +pi, 0 is to the right
+ direction = ((int)(a * 16 / (Math.PI * 2)) + 21) % 16;
}
if (direction != ptr.selected_direction)
{
ptr.selected_direction = direction;
- KeyValue newValue = getKeyAtDirection(ptr, direction);
- if (newValue != null && (ptr.value == null || !newValue.equals(ptr.value)))
+ KeyValue newValue = getNearestKeyAtDirection(ptr, direction);
+ if (newValue != null && !newValue.equals(ptr.value))
{
ptr.value = newValue;
ptr.flags = newValue.getFlags();
- // Sliding mode is entered when key2 or key3 is down on a slider key.
- if (ptr.key.slider)
+ // Sliding mode is entered when key5 or key6 is down on a slider key.
+ if (ptr.key.slider &&
+ (ptr.key.hasValue(newValue, 5) || ptr.key.hasValue(newValue, 6)))
{
- switch (direction)
- {
- case 1:
- case 8:
- case 4:
- case 5:
- startSliding(ptr, dy);
- break;
- }
+ startSliding(ptr, dy);
}
_handler.onPointerDown(true);
}
@@ -419,9 +423,8 @@ public final class Pointers implements Handler.Callback
int count = (int)(dx / _config.slide_step_px);
if (count == ptr.sliding_count)
return;
- KeyValue newValue = handleKV(
- (count < ptr.sliding_count) ? ptr.key.key3 : ptr.key.key2,
- ptr.modifiers);
+ int key_index = (count < ptr.sliding_count) ? 5 : 6;
+ KeyValue newValue = handleKV(ptr.key.keys[key_index], ptr.modifiers);
ptr.sliding_count = count;
ptr.value = newValue;
if (newValue != null)
@@ -434,8 +437,8 @@ public final class Pointers implements Handler.Callback
public int pointerId;
/** The Key pressed by this Pointer */
public final KeyboardData.Key key;
- /** Current direction. */
- public int selected_direction;
+ /** Current direction. [null] means not swiping. */
+ public Integer selected_direction;
/** Selected value with [modifiers] applied. */
public KeyValue value;
public float downX;
@@ -455,7 +458,7 @@ public final class Pointers implements Handler.Callback
{
pointerId = p;
key = k;
- selected_direction = 0;
+ selected_direction = null;
value = v;
downX = x;
downY = y;