forked from extern/Unexpected-Keyboard
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.
This commit is contained in:
parent
4f9375373e
commit
4127aa6f03
@ -36,7 +36,7 @@ final class Config
|
||||
public float keyVerticalInterval;
|
||||
public float keyHorizontalInterval;
|
||||
public boolean preciseRepeat;
|
||||
public int lockable_modifiers;
|
||||
public Set<Integer> lockable_modifiers = new HashSet<Integer>();
|
||||
public float characterSize; // Ratio
|
||||
public int accents; // Values are R.values.pref_accents_v_*
|
||||
public int theme; // Values are R.style.*
|
||||
@ -127,15 +127,15 @@ final class Config
|
||||
keyHeight = dm.heightPixels * keyboardHeightPercent / 100 / 4;
|
||||
horizontalMargin = getDipPref(dm, prefs, "horizontal_margin", horizontalMargin) + res.getDimension(R.dimen.extra_horizontal_margin);
|
||||
preciseRepeat = prefs.getBoolean("precise_repeat", preciseRepeat);
|
||||
lockable_modifiers =
|
||||
(prefs.getBoolean("lockable_shift", true) ? KeyValue.FLAG_SHIFT : 0)
|
||||
| (prefs.getBoolean("lockable_ctrl", false) ? KeyValue.FLAG_CTRL : 0)
|
||||
| (prefs.getBoolean("lockable_alt", false) ? KeyValue.FLAG_ALT : 0)
|
||||
| (prefs.getBoolean("lockable_fn", false) ? KeyValue.FLAG_FN : 0)
|
||||
| (prefs.getBoolean("lockable_meta", false) ? KeyValue.FLAG_META : 0)
|
||||
| (prefs.getBoolean("lockable_sup", false) ? KeyValue.FLAG_ACCENT_SUPERSCRIPT : 0)
|
||||
| (prefs.getBoolean("lockable_sub", false) ? KeyValue.FLAG_ACCENT_SUBSCRIPT : 0)
|
||||
| (prefs.getBoolean("lockable_box", false) ? KeyValue.FLAG_ACCENT_BOX : 0);
|
||||
lockable_modifiers.clear();
|
||||
if (prefs.getBoolean("lockable_shift", true)) lockable_modifiers.add(KeyValue.MOD_SHIFT);
|
||||
if (prefs.getBoolean("lockable_ctrl", false)) lockable_modifiers.add(KeyValue.MOD_CTRL);
|
||||
if (prefs.getBoolean("lockable_alt", false)) lockable_modifiers.add(KeyValue.MOD_ALT);
|
||||
if (prefs.getBoolean("lockable_fn", false)) lockable_modifiers.add(KeyValue.MOD_FN);
|
||||
if (prefs.getBoolean("lockable_meta", false)) lockable_modifiers.add(KeyValue.MOD_META);
|
||||
if (prefs.getBoolean("lockable_sup", false)) lockable_modifiers.add(KeyValue.MOD_SUPERSCRIPT);
|
||||
if (prefs.getBoolean("lockable_sub", false)) lockable_modifiers.add(KeyValue.MOD_SUBSCRIPT);
|
||||
if (prefs.getBoolean("lockable_box", false)) lockable_modifiers.add(KeyValue.MOD_BOX);
|
||||
characterSize = prefs.getFloat("character_size", characterSize);
|
||||
accents = Integer.valueOf(prefs.getString("accents", "1"));
|
||||
theme = getThemeId(res, prefs.getString("theme", ""));
|
||||
@ -163,7 +163,7 @@ final class Config
|
||||
boolean is_extra_key = extra_keys.contains(key.name);
|
||||
if (is_extra_key)
|
||||
extra_keys.remove(key.name);
|
||||
switch (key.eventCode)
|
||||
switch (key.code)
|
||||
{
|
||||
case KeyValue.EVENT_CHANGE_METHOD:
|
||||
return shouldOfferSwitchingToNextInputMethod ? key : null;
|
||||
@ -179,7 +179,8 @@ final class Config
|
||||
{
|
||||
if ((key.flags & KeyValue.FLAG_LOCALIZED) != 0 && !is_extra_key)
|
||||
return null;
|
||||
if ((key.flags & lockable_modifiers) != 0)
|
||||
if ((key.flags & KeyValue.FLAG_MODIFIER) != 0
|
||||
&& lockable_modifiers.contains(key.code))
|
||||
return key.withFlags(key.flags | KeyValue.FLAG_LOCK);
|
||||
}
|
||||
return key;
|
||||
@ -275,6 +276,6 @@ final class Config
|
||||
|
||||
public static interface IKeyEventHandler
|
||||
{
|
||||
public void handleKeyUp(KeyValue value, int flags);
|
||||
public void handleKeyUp(KeyValue value, Pointers.Modifiers flags);
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public class EmojiGridView extends GridView
|
||||
Config config = Config.globalConfig();
|
||||
Integer used = _lastUsed.get(_emojiArray[pos]);
|
||||
_lastUsed.put(_emojiArray[pos], (used == null) ? 1 : used.intValue() + 1);
|
||||
config.handler.handleKeyUp(_emojiArray[pos], 0);
|
||||
config.handler.handleKeyUp(_emojiArray[pos], Pointers.Modifiers.EMPTY);
|
||||
saveLastUsed(); // TODO: opti
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,6 @@ public class EmojiKeyButton extends Button
|
||||
public void onClick(View v)
|
||||
{
|
||||
Config config = Config.globalConfig();
|
||||
config.handler.handleKeyUp(_key, 0);
|
||||
config.handler.handleKeyUp(_key, Pointers.Modifiers.EMPTY);
|
||||
}
|
||||
}
|
||||
|
@ -11,11 +11,11 @@ class KeyEventHandler implements Config.IKeyEventHandler
|
||||
_recv = recv;
|
||||
}
|
||||
|
||||
public void handleKeyUp(KeyValue key, int flags)
|
||||
public void handleKeyUp(KeyValue key, Pointers.Modifiers mods)
|
||||
{
|
||||
if (key == null || (key.flags & KeyValue.FLAG_NOCHAR) != 0)
|
||||
if (key == null || (key.flags & KeyValue.FLAG_MODIFIER) != 0)
|
||||
return;
|
||||
switch (key.eventCode)
|
||||
switch (key.code)
|
||||
{
|
||||
case KeyValue.EVENT_CONFIG: _recv.showKeyboardConfig(); return;
|
||||
case KeyValue.EVENT_SWITCH_TEXT: _recv.switchMain(); return;
|
||||
@ -26,12 +26,10 @@ class KeyEventHandler implements Config.IKeyEventHandler
|
||||
case KeyValue.EVENT_ACTION: _recv.performAction(); return;
|
||||
case KeyValue.EVENT_SWITCH_PROGRAMMING: _recv.switchProgramming(); return;
|
||||
default:
|
||||
if ((flags & (KeyValue.FLAG_CTRL | KeyValue.FLAG_ALT | KeyValue.FLAG_META)) != 0)
|
||||
handleKeyUpWithModifier(key, flags);
|
||||
if (shouldSendEvents(key, mods))
|
||||
handleKeyUpWithModifier(key, mods);
|
||||
else if (key.char_ != KeyValue.CHAR_NONE)
|
||||
_recv.commitChar(key.char_);
|
||||
else if (key.eventCode != KeyValue.EVENT_NONE)
|
||||
handleKeyUpWithModifier(key, flags);
|
||||
else
|
||||
_recv.commitText(key.symbol);
|
||||
}
|
||||
@ -57,31 +55,56 @@ class KeyEventHandler implements Config.IKeyEventHandler
|
||||
return updatedMetaState;
|
||||
}
|
||||
|
||||
/* Send key events corresponding to pressed modifier keys. */
|
||||
private int sendMetaKeys(int flags, int metaState, boolean down)
|
||||
private int sendMetaKeyForModifier(int mod, int metaState, boolean down)
|
||||
{
|
||||
if ((flags & KeyValue.FLAG_CTRL) != 0)
|
||||
metaState = sendMetaKey(KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON, metaState, down);
|
||||
if ((flags & KeyValue.FLAG_ALT) != 0)
|
||||
metaState = sendMetaKey(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_ON, metaState, down);
|
||||
if ((flags & KeyValue.FLAG_SHIFT) != 0)
|
||||
metaState = sendMetaKey(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON, metaState, down);
|
||||
if ((flags & KeyValue.FLAG_META) != 0)
|
||||
metaState = sendMetaKey(KeyEvent.KEYCODE_META_LEFT, KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_ON, metaState, down);
|
||||
return metaState;
|
||||
switch (mod)
|
||||
{
|
||||
case KeyValue.MOD_CTRL:
|
||||
return sendMetaKey(KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON, metaState, down);
|
||||
case KeyValue.MOD_ALT:
|
||||
return sendMetaKey(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_ON, metaState, down);
|
||||
case KeyValue.MOD_SHIFT:
|
||||
return sendMetaKey(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON, metaState, down);
|
||||
case KeyValue.MOD_META:
|
||||
return sendMetaKey(KeyEvent.KEYCODE_META_LEFT, KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_ON, metaState, down);
|
||||
default: return metaState;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't set KeyEvent.FLAG_SOFT_KEYBOARD.
|
||||
*/
|
||||
private void handleKeyUpWithModifier(KeyValue key, int flags)
|
||||
private void handleKeyUpWithModifier(KeyValue key, Pointers.Modifiers mods)
|
||||
{
|
||||
if (key.eventCode == KeyValue.EVENT_NONE)
|
||||
if (key.code == KeyValue.EVENT_NONE)
|
||||
return ;
|
||||
int metaState = sendMetaKeys(flags, 0, true);
|
||||
_recv.sendKeyEvent(KeyEvent.ACTION_DOWN, key.eventCode, metaState);
|
||||
_recv.sendKeyEvent(KeyEvent.ACTION_UP, key.eventCode, metaState);
|
||||
sendMetaKeys(flags, metaState, false);
|
||||
int metaState = 0;
|
||||
for (int i = 0; i < mods.size(); i++)
|
||||
metaState = sendMetaKeyForModifier(mods.get(i), metaState, true);
|
||||
_recv.sendKeyEvent(KeyEvent.ACTION_DOWN, key.code, metaState);
|
||||
_recv.sendKeyEvent(KeyEvent.ACTION_UP, key.code, metaState);
|
||||
for (int i = mods.size() - 1; i >= 0; i--)
|
||||
metaState = sendMetaKeyForModifier(mods.get(i), metaState, false);
|
||||
}
|
||||
|
||||
/** Whether to send up and down events (true) or commit the text (false). */
|
||||
private boolean shouldSendEvents(KeyValue key, Pointers.Modifiers mods)
|
||||
{
|
||||
// Check for modifiers
|
||||
for (int i = 0; i < mods.size(); i++)
|
||||
{
|
||||
switch (mods.get(i))
|
||||
{
|
||||
case KeyValue.MOD_CTRL:
|
||||
case KeyValue.MOD_ALT:
|
||||
case KeyValue.MOD_META: return true;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
// Key has no char but has a key event
|
||||
if (key.char_ == KeyValue.CHAR_NONE && key.code >= 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static interface IReceiver
|
||||
|
@ -1,6 +1,5 @@
|
||||
package juloo.keyboard2;
|
||||
|
||||
import android.util.SparseArray;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
import java.util.HashMap;
|
||||
@ -8,234 +7,86 @@ import java.util.HashMap;
|
||||
class KeyModifier
|
||||
{
|
||||
/** Cache key is KeyValue's name */
|
||||
private static HashMap<String, SparseArray<KeyValue>> _cache =
|
||||
new HashMap<String, SparseArray<KeyValue>>();
|
||||
private static HashMap<String, HashMap<Pointers.Modifiers, KeyValue>> _cache =
|
||||
new HashMap<String, HashMap<Pointers.Modifiers, KeyValue>>();
|
||||
|
||||
/** Represents a removed key, because a cache entry can't be [null]. */
|
||||
private static final KeyValue removed_key = KeyValue.getKeyByName("removed");
|
||||
|
||||
/** Modify a key according to modifiers. */
|
||||
public static KeyValue handleFlags(KeyValue k, int flags)
|
||||
public static KeyValue modify(KeyValue k, Pointers.Modifiers mods)
|
||||
{
|
||||
if (k == null)
|
||||
return null;
|
||||
SparseArray<KeyValue> ks = cacheEntry(k);
|
||||
KeyValue r = ks.get(flags);
|
||||
if (r == null) // Cold cache
|
||||
int n_mods = mods.size();
|
||||
HashMap<Pointers.Modifiers, KeyValue> ks = cacheEntry(k);
|
||||
KeyValue r = ks.get(mods);
|
||||
if (r == null)
|
||||
{
|
||||
r = k;
|
||||
r = handleFn(r, flags);
|
||||
r = handleShift(r, flags);
|
||||
r = handleAccents(r, flags);
|
||||
ks.put(flags, r);
|
||||
/* Order: Fn, Shift, accents */
|
||||
for (int i = 0; i < n_mods; i++)
|
||||
r = modify(r, mods.get(i));
|
||||
r = remove_placeholders(r);
|
||||
ks.put(mods, r);
|
||||
}
|
||||
return (r == removed_key) ? null : r;
|
||||
}
|
||||
|
||||
private static KeyValue handleAccents(KeyValue k, int flags)
|
||||
public static KeyValue modify(KeyValue k, int mod)
|
||||
{
|
||||
if (k.char_ == KeyValue.CHAR_NONE || (flags & KeyValue.FLAGS_ACCENTS) == 0)
|
||||
return k;
|
||||
char c = handleAccentChar(k.char_, flags);
|
||||
if (c == 0 || c == k.char_)
|
||||
return k;
|
||||
return k.withCharAndSymbol(c);
|
||||
}
|
||||
|
||||
private static KeyValue handleShift(KeyValue k, int flags)
|
||||
switch (mod)
|
||||
{
|
||||
if ((flags & KeyValue.FLAG_SHIFT) == 0)
|
||||
return k;
|
||||
char c = k.char_;
|
||||
if (k.char_ != KeyValue.CHAR_NONE)
|
||||
c = Character.toUpperCase(c);
|
||||
if (c == k.char_) // Used to have more rules if toUpperCase() did nothing
|
||||
return k;
|
||||
return k.withCharAndSymbol(c);
|
||||
}
|
||||
|
||||
private static char handleAccentChar(char c, int flags)
|
||||
{
|
||||
switch ((flags & KeyValue.FLAGS_ACCENTS))
|
||||
{
|
||||
case KeyValue.FLAG_ACCENT1:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02CB', c);
|
||||
case KeyValue.FLAG_ACCENT2:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u00B4', c);
|
||||
case KeyValue.FLAG_ACCENT3:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02C6', c);
|
||||
case KeyValue.FLAG_ACCENT4:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02DC', c);
|
||||
case KeyValue.FLAG_ACCENT5:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u00B8', c);
|
||||
case KeyValue.FLAG_ACCENT6:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u00A8', c);
|
||||
case KeyValue.FLAG_ACCENT_CARON:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02C7', c);
|
||||
case KeyValue.FLAG_ACCENT_RING:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02DA', c);
|
||||
case KeyValue.FLAG_ACCENT_MACRON:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u00AF', c);
|
||||
case KeyValue.FLAG_ACCENT_OGONEK:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02DB', c);
|
||||
case KeyValue.FLAG_ACCENT_DOT_ABOVE:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02D9', c);
|
||||
case KeyValue.FLAG_ACCENT_DOUBLE_AIGU:
|
||||
switch (c)
|
||||
{
|
||||
// Composite characters: a̋ e̋ i̋ m̋ ӳ
|
||||
case 'o': return 'ő';
|
||||
case 'u': return 'ű';
|
||||
case ' ': return '˝';
|
||||
default: return c;
|
||||
}
|
||||
case KeyValue.FLAG_ACCENT_ORDINAL:
|
||||
switch (c)
|
||||
{
|
||||
case 'a': return 'ª';
|
||||
case 'o': return 'º';
|
||||
case '1': return 'ª';
|
||||
case '2': return 'º';
|
||||
case '3': return 'ⁿ';
|
||||
case '4': return 'ᵈ';
|
||||
case '5': return 'ᵉ';
|
||||
case '6': return 'ʳ';
|
||||
case '7': return 'ˢ';
|
||||
case '8': return 'ᵗ';
|
||||
case '9': return 'ʰ';
|
||||
case '*': return '°';
|
||||
default: return c;
|
||||
}
|
||||
case KeyValue.FLAG_ACCENT_SUPERSCRIPT:
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '¹';
|
||||
case '2': return '²';
|
||||
case '3': return '³';
|
||||
case '4': return '⁴';
|
||||
case '5': return '⁵';
|
||||
case '6': return '⁶';
|
||||
case '7': return '⁷';
|
||||
case '8': return '⁸';
|
||||
case '9': return '⁹';
|
||||
case '0': return '⁰';
|
||||
case 'i': return 'ⁱ';
|
||||
case '+': return '⁺';
|
||||
case '-': return '⁻';
|
||||
case '=': return '⁼';
|
||||
case '(': return '⁽';
|
||||
case ')': return '⁾';
|
||||
case 'n': return 'ⁿ';
|
||||
default: return c;
|
||||
}
|
||||
case KeyValue.FLAG_ACCENT_SUBSCRIPT:
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '₁';
|
||||
case '2': return '₂';
|
||||
case '3': return '₃';
|
||||
case '4': return '₄';
|
||||
case '5': return '₅';
|
||||
case '6': return '₆';
|
||||
case '7': return '₇';
|
||||
case '8': return '₈';
|
||||
case '9': return '₉';
|
||||
case '0': return '₀';
|
||||
case '+': return '₊';
|
||||
case '-': return '₋';
|
||||
case '=': return '₌';
|
||||
case '(': return '₍';
|
||||
case ')': return '₎';
|
||||
case 'e': return 'ₑ';
|
||||
case 'a': return 'ₐ';
|
||||
case 'x': return 'ₓ';
|
||||
case 'o': return 'ₒ';
|
||||
default: return c;
|
||||
}
|
||||
case KeyValue.FLAG_ACCENT_ARROWS:
|
||||
if ((flags & KeyValue.FLAG_SHIFT) == 0)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '↙';
|
||||
case '2': return '↓';
|
||||
case '3': return '↘';
|
||||
case '4': return '←';
|
||||
case '6': return '→';
|
||||
case '7': return '↖';
|
||||
case '8': return '↑';
|
||||
case '9': return '↗';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '⇙';
|
||||
case '2': return '⇓';
|
||||
case '3': return '⇘';
|
||||
case '4': return '⇐';
|
||||
case '6': return '⇒';
|
||||
case '7': return '⇖';
|
||||
case '8': return '⇑';
|
||||
case '9': return '⇗';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
case KeyValue.FLAG_ACCENT_BOX:
|
||||
if ((flags & KeyValue.FLAG_SHIFT) == 0)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '└';
|
||||
case '2': return '┴';
|
||||
case '3': return '┘';
|
||||
case '4': return '├';
|
||||
case '5': return '┼';
|
||||
case '6': return '┤';
|
||||
case '7': return '┌';
|
||||
case '8': return '┬';
|
||||
case '9': return '┐';
|
||||
case '0': return '─';
|
||||
case '.': return '│';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '╚';
|
||||
case '2': return '╩';
|
||||
case '3': return '╝';
|
||||
case '4': return '╠';
|
||||
case '5': return '╬';
|
||||
case '6': return '╣';
|
||||
case '7': return '╔';
|
||||
case '8': return '╦';
|
||||
case '9': return '╗';
|
||||
case '0': return '═';
|
||||
case '.': return '║';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
default: return c; // Can't happen
|
||||
}
|
||||
}
|
||||
|
||||
private static KeyValue handleFn(KeyValue k, int flags)
|
||||
{
|
||||
if ((flags & KeyValue.FLAG_FN) == 0)
|
||||
{
|
||||
switch (k.name)
|
||||
{
|
||||
// Remove some keys when Fn is *not* activated
|
||||
case "f11_placeholder":
|
||||
case "f12_placeholder": return removed_key;
|
||||
case KeyValue.MOD_FN: return apply_fn(k);
|
||||
case KeyValue.MOD_SHIFT: return apply_shift(k);
|
||||
case KeyValue.MOD_GRAVE: return apply_dead_char(k, '\u02CB');
|
||||
case KeyValue.MOD_AIGU: return apply_dead_char(k, '\u00B4');
|
||||
case KeyValue.MOD_CIRCONFLEXE: return apply_dead_char(k, '\u02C6');
|
||||
case KeyValue.MOD_TILDE: return apply_dead_char(k, '\u02DC');
|
||||
case KeyValue.MOD_CEDILLE: return apply_dead_char(k, '\u00B8');
|
||||
case KeyValue.MOD_TREMA: return apply_dead_char(k, '\u00A8');
|
||||
case KeyValue.MOD_CARON: return apply_dead_char(k, '\u02C7');
|
||||
case KeyValue.MOD_RING: return apply_dead_char(k, '\u02DA');
|
||||
case KeyValue.MOD_MACRON: return apply_dead_char(k, '\u00AF');
|
||||
case KeyValue.MOD_OGONEK: return apply_dead_char(k, '\u02DB');
|
||||
case KeyValue.MOD_DOT_ABOVE: return apply_dead_char(k, '\u02D9');
|
||||
case KeyValue.MOD_DOUBLE_AIGU:
|
||||
return maybe_modify_char(k, map_char_double_aigu(k.char_));
|
||||
case KeyValue.MOD_ORDINAL:
|
||||
return maybe_modify_char(k, map_char_ordinal(k.char_));
|
||||
case KeyValue.MOD_SUPERSCRIPT:
|
||||
return maybe_modify_char(k, map_char_superscript(k.char_));
|
||||
case KeyValue.MOD_SUBSCRIPT:
|
||||
return maybe_modify_char(k, map_char_subscript(k.char_));
|
||||
case KeyValue.MOD_ARROWS:
|
||||
return maybe_modify_char(k, map_char_arrows(k.char_));
|
||||
case KeyValue.MOD_BOX:
|
||||
return maybe_modify_char(k, map_char_box(k.char_));
|
||||
default: return k;
|
||||
}
|
||||
}
|
||||
|
||||
private static KeyValue apply_dead_char(KeyValue k, char dead_char)
|
||||
{
|
||||
char c = k.char_;
|
||||
if (c != KeyValue.CHAR_NONE)
|
||||
c = (char)KeyCharacterMap.getDeadChar(dead_char, c);
|
||||
return maybe_modify_char(k, c);
|
||||
}
|
||||
|
||||
private static KeyValue apply_shift(KeyValue k)
|
||||
{
|
||||
char c = k.char_;
|
||||
if (c == KeyValue.CHAR_NONE)
|
||||
return k;
|
||||
c = map_char_shift(c);
|
||||
if (c == k.char_)
|
||||
c = Character.toUpperCase(c);
|
||||
return maybe_modify_char(k, c);
|
||||
}
|
||||
|
||||
private static KeyValue apply_fn(KeyValue k)
|
||||
{
|
||||
String name;
|
||||
switch (k.name)
|
||||
{
|
||||
@ -302,15 +153,180 @@ class KeyModifier
|
||||
return KeyValue.getKeyByName(name);
|
||||
}
|
||||
|
||||
/* Lookup the cache entry for a key. Create it needed. */
|
||||
private static SparseArray<KeyValue> cacheEntry(KeyValue k)
|
||||
/** Remove placeholder keys that haven't been modified into something. */
|
||||
private static KeyValue remove_placeholders(KeyValue k)
|
||||
{
|
||||
SparseArray<KeyValue> ks = _cache.get(k.name);
|
||||
switch (k.name)
|
||||
{
|
||||
case "f11_placeholder":
|
||||
case "f12_placeholder": return removed_key;
|
||||
default: return k;
|
||||
}
|
||||
}
|
||||
|
||||
/** Helper, update [k] with the char [c] if it's not [0]. */
|
||||
private static KeyValue maybe_modify_char(KeyValue k, char c)
|
||||
{
|
||||
if (c == 0 || c == KeyValue.CHAR_NONE || c == k.char_)
|
||||
return k;
|
||||
return k.withCharAndSymbol(c);
|
||||
}
|
||||
|
||||
/* Lookup the cache entry for a key. Create it needed. */
|
||||
private static HashMap<Pointers.Modifiers, KeyValue> cacheEntry(KeyValue k)
|
||||
{
|
||||
HashMap<Pointers.Modifiers, KeyValue> ks = _cache.get(k.name);
|
||||
if (ks == null)
|
||||
{
|
||||
ks = new SparseArray<KeyValue>();
|
||||
ks = new HashMap<Pointers.Modifiers, KeyValue>();
|
||||
_cache.put(k.name, ks);
|
||||
}
|
||||
return ks;
|
||||
}
|
||||
|
||||
private static char map_char_shift(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '↙': return '⇙';
|
||||
case '↓': return '⇓';
|
||||
case '↘': return '⇘';
|
||||
case '←': return '⇐';
|
||||
case '→': return '⇒';
|
||||
case '↖': return '⇖';
|
||||
case '↑': return '⇑';
|
||||
case '↗': return '⇗';
|
||||
case '└': return '╚';
|
||||
case '┴': return '╩';
|
||||
case '┘': return '╝';
|
||||
case '├': return '╠';
|
||||
case '┼': return '╬';
|
||||
case '┤': return '╣';
|
||||
case '┌': return '╔';
|
||||
case '┬': return '╦';
|
||||
case '┐': return '╗';
|
||||
case '─': return '═';
|
||||
case '│': return '║';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
|
||||
private static char map_char_double_aigu(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
// Composite characters: a̋ e̋ i̋ m̋ ӳ
|
||||
case 'o': return 'ő';
|
||||
case 'u': return 'ű';
|
||||
case ' ': return '˝';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
|
||||
private static char map_char_ordinal(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'a': return 'ª';
|
||||
case 'o': return 'º';
|
||||
case '1': return 'ª';
|
||||
case '2': return 'º';
|
||||
case '3': return 'ⁿ';
|
||||
case '4': return 'ᵈ';
|
||||
case '5': return 'ᵉ';
|
||||
case '6': return 'ʳ';
|
||||
case '7': return 'ˢ';
|
||||
case '8': return 'ᵗ';
|
||||
case '9': return 'ʰ';
|
||||
case '*': return '°';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
|
||||
private static char map_char_superscript(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '¹';
|
||||
case '2': return '²';
|
||||
case '3': return '³';
|
||||
case '4': return '⁴';
|
||||
case '5': return '⁵';
|
||||
case '6': return '⁶';
|
||||
case '7': return '⁷';
|
||||
case '8': return '⁸';
|
||||
case '9': return '⁹';
|
||||
case '0': return '⁰';
|
||||
case 'i': return 'ⁱ';
|
||||
case '+': return '⁺';
|
||||
case '-': return '⁻';
|
||||
case '=': return '⁼';
|
||||
case '(': return '⁽';
|
||||
case ')': return '⁾';
|
||||
case 'n': return 'ⁿ';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
|
||||
private static char map_char_subscript(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '₁';
|
||||
case '2': return '₂';
|
||||
case '3': return '₃';
|
||||
case '4': return '₄';
|
||||
case '5': return '₅';
|
||||
case '6': return '₆';
|
||||
case '7': return '₇';
|
||||
case '8': return '₈';
|
||||
case '9': return '₉';
|
||||
case '0': return '₀';
|
||||
case '+': return '₊';
|
||||
case '-': return '₋';
|
||||
case '=': return '₌';
|
||||
case '(': return '₍';
|
||||
case ')': return '₎';
|
||||
case 'e': return 'ₑ';
|
||||
case 'a': return 'ₐ';
|
||||
case 'x': return 'ₓ';
|
||||
case 'o': return 'ₒ';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
|
||||
private static char map_char_arrows(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '↙';
|
||||
case '2': return '↓';
|
||||
case '3': return '↘';
|
||||
case '4': return '←';
|
||||
case '6': return '→';
|
||||
case '7': return '↖';
|
||||
case '8': return '↑';
|
||||
case '9': return '↗';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
|
||||
private static char map_char_box(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '└';
|
||||
case '2': return '┴';
|
||||
case '3': return '┘';
|
||||
case '4': return '├';
|
||||
case '5': return '┼';
|
||||
case '6': return '┤';
|
||||
case '7': return '┌';
|
||||
case '8': return '┬';
|
||||
case '9': return '┐';
|
||||
case '0': return '─';
|
||||
case '.': return '│';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import java.util.HashMap;
|
||||
|
||||
class KeyValue
|
||||
{
|
||||
/** Values for the [code] field. */
|
||||
|
||||
public static final int EVENT_NONE = -1;
|
||||
public static final int EVENT_CONFIG = -2;
|
||||
public static final int EVENT_SWITCH_TEXT = -3;
|
||||
@ -15,6 +17,35 @@ class KeyValue
|
||||
public static final int EVENT_CHANGE_METHOD = -7;
|
||||
public static final int EVENT_ACTION = -8;
|
||||
public static final int EVENT_SWITCH_PROGRAMMING = -9;
|
||||
|
||||
// Modifiers
|
||||
// Must be evaluated in the reverse order of their values.
|
||||
public static final int MOD_SHIFT = -100;
|
||||
public static final int MOD_FN = -101;
|
||||
public static final int MOD_CTRL = -102;
|
||||
public static final int MOD_ALT = -103;
|
||||
public static final int MOD_META = -104;
|
||||
|
||||
// Dead-keys
|
||||
public static final int MOD_DOUBLE_AIGU = -200;
|
||||
public static final int MOD_DOT_ABOVE = -201;
|
||||
public static final int MOD_GRAVE = -202;
|
||||
public static final int MOD_AIGU = -203;
|
||||
public static final int MOD_CIRCONFLEXE = -204;
|
||||
public static final int MOD_TILDE = -205;
|
||||
public static final int MOD_CEDILLE = -206;
|
||||
public static final int MOD_TREMA = -207;
|
||||
public static final int MOD_SUPERSCRIPT = -208;
|
||||
public static final int MOD_SUBSCRIPT = -209;
|
||||
public static final int MOD_RING = -210;
|
||||
public static final int MOD_CARON = -211;
|
||||
public static final int MOD_MACRON = -212;
|
||||
public static final int MOD_ORDINAL = -213;
|
||||
public static final int MOD_ARROWS = -214;
|
||||
public static final int MOD_BOX = -215;
|
||||
public static final int MOD_OGONEK = -216;
|
||||
|
||||
/** Special value for the [char_] field. */
|
||||
public static final char CHAR_NONE = '\0';
|
||||
|
||||
// Behavior flags
|
||||
@ -22,7 +53,7 @@ class KeyValue
|
||||
public static final int FLAG_LOCK = (1 << 1);
|
||||
// Special keys are not repeated and don't clear latched modifiers
|
||||
public static final int FLAG_SPECIAL = (1 << 2);
|
||||
public static final int FLAG_NOCHAR = (1 << 3);
|
||||
public static final int FLAG_MODIFIER = (1 << 3);
|
||||
public static final int FLAG_PRECISE_REPEAT = (1 << 4);
|
||||
|
||||
// Rendering flags
|
||||
@ -30,48 +61,25 @@ class KeyValue
|
||||
public static final int FLAG_SMALLER_FONT = (1 << 6);
|
||||
|
||||
// Internal flags
|
||||
public static final int FLAG_LOCKED = (1 << 8);
|
||||
|
||||
// Modifier flags
|
||||
public static final int FLAG_CTRL = (1 << 10);
|
||||
public static final int FLAG_SHIFT = (1 << 11);
|
||||
public static final int FLAG_ALT = (1 << 12);
|
||||
public static final int FLAG_FN = (1 << 13);
|
||||
public static final int FLAG_META = (1 << 14);
|
||||
|
||||
// Accent flags
|
||||
public static final int FLAG_ACCENT_DOUBLE_AIGU = (1 << 9);
|
||||
public static final int FLAG_ACCENT_DOT_ABOVE = (1 << 15);
|
||||
public static final int FLAG_ACCENT1 = (1 << 16); // Grave
|
||||
public static final int FLAG_ACCENT2 = (1 << 17); // Aigu
|
||||
public static final int FLAG_ACCENT3 = (1 << 18); // Circonflexe
|
||||
public static final int FLAG_ACCENT4 = (1 << 19); // Tilde
|
||||
public static final int FLAG_ACCENT5 = (1 << 20); // Cédille
|
||||
public static final int FLAG_ACCENT6 = (1 << 21); // Tréma
|
||||
public static final int FLAG_ACCENT_SUPERSCRIPT = (1 << 22);
|
||||
public static final int FLAG_ACCENT_SUBSCRIPT = (1 << 23);
|
||||
public static final int FLAG_ACCENT_RING = (1 << 24);
|
||||
public static final int FLAG_ACCENT_CARON = (1 << 26);
|
||||
public static final int FLAG_ACCENT_MACRON = (1 << 27);
|
||||
public static final int FLAG_ACCENT_ORDINAL = (1 << 28);
|
||||
public static final int FLAG_ACCENT_ARROWS = (1 << 29);
|
||||
public static final int FLAG_ACCENT_BOX = (1 << 30);
|
||||
public static final int FLAG_ACCENT_OGONEK = (1 << 31);
|
||||
|
||||
public static final int FLAGS_ACCENTS = FLAG_ACCENT1 | FLAG_ACCENT2 |
|
||||
FLAG_ACCENT3 | FLAG_ACCENT4 | FLAG_ACCENT5 | FLAG_ACCENT6 |
|
||||
FLAG_ACCENT_CARON | FLAG_ACCENT_MACRON | FLAG_ACCENT_SUPERSCRIPT |
|
||||
FLAG_ACCENT_SUBSCRIPT | FLAG_ACCENT_ORDINAL | FLAG_ACCENT_ARROWS |
|
||||
FLAG_ACCENT_BOX | FLAG_ACCENT_RING | FLAG_ACCENT_OGONEK |
|
||||
FLAG_ACCENT_DOT_ABOVE | FLAG_ACCENT_DOUBLE_AIGU;
|
||||
public static final int FLAG_LOCKED = (1 << 7);
|
||||
|
||||
// Language specific keys that are removed from the keyboard by default
|
||||
public static final int FLAG_LOCALIZED = (1 << 25);
|
||||
public static final int FLAG_LOCALIZED = (1 << 8);
|
||||
|
||||
public final String name;
|
||||
public final String symbol;
|
||||
public final char char_;
|
||||
public final int eventCode;
|
||||
|
||||
/** Describe what the key does when it isn't a simple character.
|
||||
Can be one of:
|
||||
- When [FLAG_MODIFIER] is set, a modifier. See [KeyModifier].
|
||||
- [EVENT_NONE], no event is associated with the key.
|
||||
- A positive integer, an Android [KeyEvent].
|
||||
- One of the [EVENT_*] constants, an action performed in [KeyEventHandler].
|
||||
A key can have both a character and a key event associated, the key event
|
||||
is used when certain modifiers are active, the character is used
|
||||
otherwise. See [KeyEventHandler]. */
|
||||
public final int code;
|
||||
public final int flags;
|
||||
|
||||
/* Update the char and the symbol. */
|
||||
@ -82,17 +90,17 @@ class KeyValue
|
||||
|
||||
public KeyValue withCharAndSymbol(String s, char c)
|
||||
{
|
||||
return new KeyValue(name, s, c, eventCode, flags);
|
||||
return new KeyValue(name, s, c, code, flags);
|
||||
}
|
||||
|
||||
public KeyValue withNameAndSymbol(String n, String s)
|
||||
{
|
||||
return new KeyValue(n, s, char_, eventCode, flags);
|
||||
return new KeyValue(n, s, char_, code, flags);
|
||||
}
|
||||
|
||||
public KeyValue withFlags(int f)
|
||||
{
|
||||
return new KeyValue(name, symbol, char_, eventCode, f);
|
||||
return new KeyValue(name, symbol, char_, code, f);
|
||||
}
|
||||
|
||||
private static HashMap<String, KeyValue> keys = new HashMap<String, KeyValue>();
|
||||
@ -102,7 +110,7 @@ class KeyValue
|
||||
name = n;
|
||||
symbol = s;
|
||||
char_ = c;
|
||||
eventCode = e;
|
||||
code = e;
|
||||
flags = f;
|
||||
}
|
||||
|
||||
@ -136,26 +144,17 @@ class KeyValue
|
||||
keys.put(name, new KeyValue(name, symbol, c, event, flags));
|
||||
}
|
||||
|
||||
private static void addCharKey(char c, int event, int flags)
|
||||
{
|
||||
String name = String.valueOf(c);
|
||||
addKey(name, name, c, event, flags);
|
||||
}
|
||||
|
||||
private static void addCharKey(char c, int event)
|
||||
{
|
||||
addCharKey(c, event, 0);
|
||||
String name = String.valueOf(c);
|
||||
addKey(name, name, c, event, 0);
|
||||
}
|
||||
|
||||
private static void addModifierKey(String name, String symbol, int extra_flags)
|
||||
private static void addModifierKey(String name, String symbol, int code, int extra_flags)
|
||||
{
|
||||
addKey(name, symbol, CHAR_NONE, EVENT_NONE,
|
||||
FLAG_LATCH | FLAG_NOCHAR | FLAG_SPECIAL | extra_flags);
|
||||
}
|
||||
|
||||
private static void addSpecialKey(String name, String symbol, int event)
|
||||
{
|
||||
addSpecialKey(name, symbol, event, 0);
|
||||
assert(code >= 100 && code < 300);
|
||||
addKey(name, symbol, CHAR_NONE, code,
|
||||
FLAG_LATCH | FLAG_MODIFIER | FLAG_SPECIAL | extra_flags);
|
||||
}
|
||||
|
||||
private static void addSpecialKey(String name, String symbol, int event, int flags)
|
||||
@ -163,11 +162,6 @@ class KeyValue
|
||||
addKey(name, symbol, CHAR_NONE, event, flags | FLAG_SPECIAL);
|
||||
}
|
||||
|
||||
private static void addEventKey(String name, String symbol, int event)
|
||||
{
|
||||
addEventKey(name, symbol, event, 0);
|
||||
}
|
||||
|
||||
private static void addEventKey(String name, String symbol, int event, int flags)
|
||||
{
|
||||
addKey(name, symbol, CHAR_NONE, event, flags);
|
||||
@ -176,28 +170,28 @@ class KeyValue
|
||||
static
|
||||
{
|
||||
addModifierKey("shift", "\n", // Can't write u000A because Java is stupid
|
||||
FLAG_SHIFT | FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
addModifierKey("ctrl", "Ctrl", FLAG_CTRL | FLAG_SMALLER_FONT);
|
||||
addModifierKey("alt", "Alt", FLAG_ALT | FLAG_SMALLER_FONT);
|
||||
addModifierKey("accent_aigu", "\u0050", FLAG_ACCENT2 | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_caron", "\u0051", FLAG_ACCENT_CARON | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_cedille", "\u0052", FLAG_ACCENT5 | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_circonflexe", "\u0053", FLAG_ACCENT3 | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_grave", "\u0054", FLAG_ACCENT1 | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_macron", "\u0055", FLAG_ACCENT_MACRON | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_ring", "\u0056", FLAG_ACCENT_RING | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_tilde", "\u0057", FLAG_ACCENT4 | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_trema", "\u0058", FLAG_ACCENT6 | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_ogonek", "\u0059", FLAG_ACCENT_OGONEK | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_dot_above", "\u005a", FLAG_ACCENT_DOT_ABOVE | FLAG_KEY_FONT);
|
||||
addModifierKey("accent_double_aigu", "\u005b", FLAG_ACCENT_DOUBLE_AIGU | FLAG_KEY_FONT);
|
||||
addModifierKey("superscript", "Sup", FLAG_ACCENT_SUPERSCRIPT | FLAG_SMALLER_FONT);
|
||||
addModifierKey("subscript", "Sub", FLAG_ACCENT_SUBSCRIPT | FLAG_SMALLER_FONT);
|
||||
addModifierKey("ordinal", "Ord", FLAG_ACCENT_ORDINAL | FLAG_SMALLER_FONT);
|
||||
addModifierKey("arrows", "Arr", FLAG_ACCENT_ARROWS | FLAG_SMALLER_FONT);
|
||||
addModifierKey("box", "Box", FLAG_ACCENT_BOX | FLAG_SMALLER_FONT);
|
||||
addModifierKey("fn", "Fn", FLAG_FN | FLAG_SMALLER_FONT);
|
||||
addModifierKey("meta", "Meta", FLAG_META | FLAG_SMALLER_FONT);
|
||||
MOD_SHIFT, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
addModifierKey("ctrl", "Ctrl", MOD_CTRL, FLAG_SMALLER_FONT);
|
||||
addModifierKey("alt", "Alt", MOD_ALT, FLAG_SMALLER_FONT);
|
||||
addModifierKey("accent_aigu", "\u0050", MOD_AIGU, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_caron", "\u0051", MOD_CARON, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_cedille", "\u0052", MOD_CEDILLE, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_circonflexe", "\u0053", MOD_CIRCONFLEXE, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_grave", "\u0054", MOD_GRAVE, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_macron", "\u0055", MOD_MACRON, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_ring", "\u0056", MOD_RING, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_tilde", "\u0057", MOD_TILDE, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_trema", "\u0058", MOD_TREMA, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_ogonek", "\u0059", MOD_OGONEK, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_dot_above", "\u005a", MOD_DOT_ABOVE, FLAG_KEY_FONT);
|
||||
addModifierKey("accent_double_aigu", "\u005b", MOD_DOUBLE_AIGU, FLAG_KEY_FONT);
|
||||
addModifierKey("superscript", "Sup", MOD_SUPERSCRIPT, FLAG_SMALLER_FONT);
|
||||
addModifierKey("subscript", "Sub", MOD_SUBSCRIPT, FLAG_SMALLER_FONT);
|
||||
addModifierKey("ordinal", "Ord", MOD_ORDINAL, FLAG_SMALLER_FONT);
|
||||
addModifierKey("arrows", "Arr", MOD_ARROWS, FLAG_SMALLER_FONT);
|
||||
addModifierKey("box", "Box", MOD_BOX, FLAG_SMALLER_FONT);
|
||||
addModifierKey("fn", "Fn", MOD_FN, FLAG_SMALLER_FONT);
|
||||
addModifierKey("meta", "Meta", MOD_META, FLAG_SMALLER_FONT);
|
||||
|
||||
addCharKey('a', KeyEvent.KEYCODE_A);
|
||||
addCharKey('b', KeyEvent.KEYCODE_B);
|
||||
@ -257,7 +251,7 @@ class KeyValue
|
||||
addSpecialKey("switch_text", "ABC", EVENT_SWITCH_TEXT, FLAG_SMALLER_FONT);
|
||||
addSpecialKey("switch_numeric", "123+", EVENT_SWITCH_NUMERIC, FLAG_SMALLER_FONT);
|
||||
addSpecialKey("switch_emoji", "\u0001" , EVENT_SWITCH_EMOJI, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
addSpecialKey("switch_back_emoji", "ABC", EVENT_SWITCH_BACK_EMOJI);
|
||||
addSpecialKey("switch_back_emoji", "ABC", EVENT_SWITCH_BACK_EMOJI, 0);
|
||||
addSpecialKey("switch_programming", "Prog", EVENT_SWITCH_PROGRAMMING, FLAG_SMALLER_FONT);
|
||||
addSpecialKey("change_method", "\u0009", EVENT_CHANGE_METHOD, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
addSpecialKey("action", "Action", EVENT_ACTION, FLAG_SMALLER_FONT); // Will always be replaced
|
||||
@ -275,16 +269,16 @@ class KeyValue
|
||||
addEventKey("backspace", "\u0011", KeyEvent.KEYCODE_DEL, FLAG_KEY_FONT);
|
||||
addEventKey("delete", "\u0010", KeyEvent.KEYCODE_FORWARD_DEL, FLAG_KEY_FONT);
|
||||
addEventKey("insert", "Ins", KeyEvent.KEYCODE_INSERT, FLAG_SMALLER_FONT);
|
||||
addEventKey("f1", "F1", KeyEvent.KEYCODE_F1);
|
||||
addEventKey("f2", "F2", KeyEvent.KEYCODE_F2);
|
||||
addEventKey("f3", "F3", KeyEvent.KEYCODE_F3);
|
||||
addEventKey("f4", "F4", KeyEvent.KEYCODE_F4);
|
||||
addEventKey("f5", "F5", KeyEvent.KEYCODE_F5);
|
||||
addEventKey("f6", "F6", KeyEvent.KEYCODE_F6);
|
||||
addEventKey("f7", "F7", KeyEvent.KEYCODE_F7);
|
||||
addEventKey("f8", "F8", KeyEvent.KEYCODE_F8);
|
||||
addEventKey("f9", "F9", KeyEvent.KEYCODE_F9);
|
||||
addEventKey("f10", "F10", KeyEvent.KEYCODE_F10);
|
||||
addEventKey("f1", "F1", KeyEvent.KEYCODE_F1, 0);
|
||||
addEventKey("f2", "F2", KeyEvent.KEYCODE_F2, 0);
|
||||
addEventKey("f3", "F3", KeyEvent.KEYCODE_F3, 0);
|
||||
addEventKey("f4", "F4", KeyEvent.KEYCODE_F4, 0);
|
||||
addEventKey("f5", "F5", KeyEvent.KEYCODE_F5, 0);
|
||||
addEventKey("f6", "F6", KeyEvent.KEYCODE_F6, 0);
|
||||
addEventKey("f7", "F7", KeyEvent.KEYCODE_F7, 0);
|
||||
addEventKey("f8", "F8", KeyEvent.KEYCODE_F8, 0);
|
||||
addEventKey("f9", "F9", KeyEvent.KEYCODE_F9, 0);
|
||||
addEventKey("f10", "F10", KeyEvent.KEYCODE_F10, 0);
|
||||
addEventKey("f11", "F11", KeyEvent.KEYCODE_F11, FLAG_SMALLER_FONT);
|
||||
addEventKey("f12", "F12", KeyEvent.KEYCODE_F12, FLAG_SMALLER_FONT);
|
||||
addEventKey("tab", "\u000F", KeyEvent.KEYCODE_TAB, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
|
@ -298,7 +298,7 @@ public class Keyboard2 extends InputMethodService
|
||||
getLayout(_config.programming_layout).mapKeys(new KeyboardData.MapKeyValues() {
|
||||
public KeyValue apply(KeyValue key)
|
||||
{
|
||||
if (key != null && key.eventCode == KeyValue.EVENT_SWITCH_PROGRAMMING)
|
||||
if (key != null && key.code == KeyValue.EVENT_SWITCH_PROGRAMMING)
|
||||
return KeyValue.getKeyByName("switch_text");
|
||||
return key;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class Keyboard2View extends View
|
||||
|
||||
private Pointers _pointers;
|
||||
|
||||
private int _flags = 0;
|
||||
private Pointers.Modifiers _mods;
|
||||
|
||||
private Vibrator _vibratorService;
|
||||
private long _lastVibration = 0;
|
||||
@ -90,15 +90,15 @@ public class Keyboard2View extends View
|
||||
|
||||
public void reset()
|
||||
{
|
||||
_flags = 0;
|
||||
_mods = Pointers.Modifiers.EMPTY;
|
||||
_pointers.clear();
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public KeyValue modifyKey(KeyValue k, int flags)
|
||||
public KeyValue modifyKey(KeyValue k, Pointers.Modifiers mods)
|
||||
{
|
||||
return KeyModifier.handleFlags(k, flags);
|
||||
return KeyModifier.modify(k, mods);
|
||||
}
|
||||
|
||||
public void onPointerDown(boolean isSwipe)
|
||||
@ -107,15 +107,15 @@ public class Keyboard2View extends View
|
||||
vibrate();
|
||||
}
|
||||
|
||||
public void onPointerUp(KeyValue k, int flags)
|
||||
public void onPointerUp(KeyValue k, Pointers.Modifiers mods)
|
||||
{
|
||||
_config.handler.handleKeyUp(k, flags);
|
||||
_config.handler.handleKeyUp(k, mods);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void onPointerHold(KeyValue k, int flags)
|
||||
public void onPointerHold(KeyValue k, Pointers.Modifiers mods)
|
||||
{
|
||||
_config.handler.handleKeyUp(k, flags);
|
||||
_config.handler.handleKeyUp(k, mods);
|
||||
}
|
||||
|
||||
public void onPointerFlagsChanged()
|
||||
@ -125,7 +125,7 @@ public class Keyboard2View extends View
|
||||
|
||||
private void updateFlags()
|
||||
{
|
||||
_flags = _pointers.getFlags();
|
||||
_mods = _pointers.getModifiers();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -284,7 +284,7 @@ public class Keyboard2View extends View
|
||||
|
||||
private void drawLabel(Canvas canvas, KeyValue k, float x, float y, float keyH, boolean isKeyDown)
|
||||
{
|
||||
k = KeyModifier.handleFlags(k, _flags);
|
||||
k = KeyModifier.modify(k, _mods);
|
||||
if (k == null)
|
||||
return;
|
||||
float textSize = scaleTextSize(k, _config.labelTextSize, keyH);
|
||||
@ -296,7 +296,7 @@ public class Keyboard2View extends View
|
||||
|
||||
private void drawSubLabel(Canvas canvas, KeyValue k, float x, float y, float keyW, float keyH, Paint.Align a, Vertical v, boolean isKeyDown)
|
||||
{
|
||||
k = KeyModifier.handleFlags(k, _flags);
|
||||
k = KeyModifier.modify(k, _mods);
|
||||
if (k == null)
|
||||
return;
|
||||
float textSize = scaleTextSize(k, _config.sublabelTextSize, keyH);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user