mirror of
https://github.com/Julow/Unexpected-Keyboard.git
synced 2024-12-23 22:48:54 +01:00
Add the Action key
It is placed on the top-right of the enter key on every layouts. It sends a special event (performEditorAction) instead of writing a newline. The "actionId" is passed through the EditorInfo object in an obfuscated way so it's not clear whether it's using the right one.
This commit is contained in:
parent
4b43645c4b
commit
53113cadd9
@ -39,6 +39,6 @@
|
||||
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/>
|
||||
<key width="4.0" key0="space"/>
|
||||
<key width="1.2" key1="up" key2="right" key3="left" key4="down"/>
|
||||
<key width="1.8" key0="enter"/>
|
||||
<key width="1.8" key0="enter" key2="action"/>
|
||||
</row>
|
||||
</keyboard>
|
||||
|
@ -30,6 +30,6 @@
|
||||
<key width="1.5" key0="0"/>
|
||||
<key width="0.75" key0="." key2=","/>
|
||||
<key width="0.75" key0="space" key1=""" key2="'" key4="_"/>
|
||||
<key width="1.5" key0="enter" key2="±" key3="="/>
|
||||
<key width="1.5" key0="enter" key1="±" key2="action" key3="="/>
|
||||
</row>
|
||||
</keyboard>
|
||||
|
@ -39,6 +39,6 @@
|
||||
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/>
|
||||
<key width="4.0" key0="space"/>
|
||||
<key width="1.2" key1="up" key2="right" key3="left" key4="down"/>
|
||||
<key width="1.8" key0="enter"/>
|
||||
<key width="1.8" key0="enter" key2="action"/>
|
||||
</row>
|
||||
</keyboard>
|
||||
|
@ -34,6 +34,8 @@ final class Config
|
||||
// Dynamically set
|
||||
public boolean shouldOfferSwitchingToNextInputMethod;
|
||||
public int key_flags_to_remove;
|
||||
public String actionLabel; // Might be 'null'
|
||||
public int actionId; // Meaningful only when 'actionLabel' isn't 'null'
|
||||
|
||||
public final IKeyEventHandler handler;
|
||||
|
||||
@ -62,6 +64,8 @@ final class Config
|
||||
// initialized later
|
||||
shouldOfferSwitchingToNextInputMethod = false;
|
||||
key_flags_to_remove = 0;
|
||||
actionLabel = null;
|
||||
actionId = 0;
|
||||
handler = h;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ class KeyEventHandler implements Config.IKeyEventHandler
|
||||
case KeyValue.EVENT_SWITCH_EMOJI: _recv.setPane_emoji(); return;
|
||||
case KeyValue.EVENT_SWITCH_BACK_EMOJI: _recv.setPane_normal(); return;
|
||||
case KeyValue.EVENT_CHANGE_METHOD: _recv.switchToNextInputMethod(); return;
|
||||
case KeyValue.EVENT_ACTION: _recv.performAction(); return;
|
||||
default:
|
||||
if ((flags & (KeyValue.FLAG_CTRL | KeyValue.FLAG_ALT)) != 0)
|
||||
handleMetaKeyUp(key, flags);
|
||||
@ -64,6 +65,7 @@ class KeyEventHandler implements Config.IKeyEventHandler
|
||||
public void setPane_emoji();
|
||||
public void setPane_normal();
|
||||
public void showKeyboardConfig();
|
||||
public void performAction();
|
||||
|
||||
/** 'res_id' is '-1' for the currently selected layout. */
|
||||
public void setLayout(int res_id);
|
||||
|
@ -13,6 +13,7 @@ class KeyValue
|
||||
public static final int EVENT_SWITCH_EMOJI = -5;
|
||||
public static final int EVENT_SWITCH_BACK_EMOJI = -6;
|
||||
public static final int EVENT_CHANGE_METHOD = -7;
|
||||
public static final int EVENT_ACTION = -8;
|
||||
public static final char CHAR_NONE = '\0';
|
||||
|
||||
// Behavior flags
|
||||
@ -214,6 +215,7 @@ class KeyValue
|
||||
addSpecialKey("switch_emoji", ":)", EVENT_SWITCH_EMOJI);
|
||||
addSpecialKey("switch_back_emoji", "ABC", EVENT_SWITCH_BACK_EMOJI);
|
||||
addSpecialKey("change_method", "⊞", EVENT_CHANGE_METHOD);
|
||||
addSpecialKey("action", "Action", EVENT_ACTION); // Will always be replaced
|
||||
|
||||
addEventKey("esc", "Esc", KeyEvent.KEYCODE_ESCAPE);
|
||||
addEventKey("enter", "\uE800", KeyEvent.KEYCODE_ENTER, FLAG_KEY_FONT);
|
||||
|
@ -138,10 +138,45 @@ public class Keyboard2 extends InputMethodService
|
||||
}
|
||||
}
|
||||
|
||||
private String actionLabel_of_imeAction(int action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case EditorInfo.IME_ACTION_UNSPECIFIED:
|
||||
case EditorInfo.IME_ACTION_NEXT: return "Next";
|
||||
case EditorInfo.IME_ACTION_DONE: return "Done";
|
||||
case EditorInfo.IME_ACTION_GO: return "Go";
|
||||
case EditorInfo.IME_ACTION_PREVIOUS: return "Prev";
|
||||
case EditorInfo.IME_ACTION_SEARCH: return "Search";
|
||||
case EditorInfo.IME_ACTION_SEND: return "Send";
|
||||
case EditorInfo.IME_ACTION_NONE:
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshEditorInfo(EditorInfo info)
|
||||
{
|
||||
// First try to look at 'info.actionLabel', if it isn't set, look at
|
||||
// 'imeOptions'.
|
||||
if (info.actionLabel != null)
|
||||
{
|
||||
_config.actionLabel = info.actionLabel.toString();
|
||||
_config.actionId = info.actionId;
|
||||
}
|
||||
else
|
||||
{
|
||||
int action = info.imeOptions & EditorInfo.IME_MASK_ACTION;
|
||||
_config.actionLabel = actionLabel_of_imeAction(action); // Might be null
|
||||
_config.actionId = action;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartInputView(EditorInfo info, boolean restarting)
|
||||
{
|
||||
// Update '_config' before calling 'KeyboardView.setKeyboard'
|
||||
refreshSubtypeImm();
|
||||
refreshEditorInfo(info);
|
||||
if ((info.inputType & InputType.TYPE_CLASS_NUMBER) != 0)
|
||||
_keyboardView.setKeyboard(getLayout(R.xml.numeric));
|
||||
else
|
||||
@ -200,6 +235,14 @@ public class Keyboard2 extends InputMethodService
|
||||
setInputView(_keyboardView);
|
||||
}
|
||||
|
||||
public void performAction()
|
||||
{
|
||||
InputConnection conn = getCurrentInputConnection();
|
||||
if (conn == null)
|
||||
return;
|
||||
conn.performEditorAction(_config.actionId);
|
||||
}
|
||||
|
||||
public void setLayout(int res_id)
|
||||
{
|
||||
if (res_id == -1)
|
||||
|
@ -60,9 +60,18 @@ public class Keyboard2View extends View
|
||||
public void setKeyboard(KeyboardData kw)
|
||||
{
|
||||
if (!_config.shouldOfferSwitchingToNextInputMethod)
|
||||
kw = kw.removeKeys(new KeyboardData.RemoveKeysByEvent(KeyValue.EVENT_CHANGE_METHOD));
|
||||
kw = kw.replaceKeys(
|
||||
new KeyboardData.ReplaceKeysByEvent(KeyValue.EVENT_CHANGE_METHOD, null));
|
||||
if (_config.key_flags_to_remove != 0)
|
||||
kw = kw.removeKeys(new KeyboardData.RemoveKeysByFlags(_config.key_flags_to_remove));
|
||||
kw = kw.replaceKeys(
|
||||
new KeyboardData.ReplaceKeysByFlags(_config.key_flags_to_remove, null));
|
||||
// Replace the action key to show the right label.
|
||||
KeyValue action_key = null;
|
||||
if (_config.actionLabel != null)
|
||||
action_key = new KeyValue(_config.actionLabel, _config.actionLabel,
|
||||
KeyValue.CHAR_NONE, KeyValue.EVENT_ACTION, KeyValue.FLAG_NOREPEAT);
|
||||
kw = kw.replaceKeys(
|
||||
new KeyboardData.ReplaceKeysByEvent(KeyValue.EVENT_ACTION, action_key));
|
||||
_keyboard = kw;
|
||||
reset();
|
||||
}
|
||||
|
@ -57,11 +57,11 @@ class KeyboardData
|
||||
return new KeyboardData(rows);
|
||||
}
|
||||
|
||||
public KeyboardData removeKeys(MapKeys f)
|
||||
public KeyboardData replaceKeys(MapKeys f)
|
||||
{
|
||||
ArrayList<Row> rows_ = new ArrayList<Row>();
|
||||
for (Row r : rows)
|
||||
rows_.add(r.removeKeys(f));
|
||||
rows_.add(r.replaceKeys(f));
|
||||
return new KeyboardData(rows_);
|
||||
}
|
||||
|
||||
@ -105,11 +105,11 @@ class KeyboardData
|
||||
return new Row(keys, h, shift);
|
||||
}
|
||||
|
||||
public Row removeKeys(MapKeys f)
|
||||
public Row replaceKeys(MapKeys f)
|
||||
{
|
||||
ArrayList<Key> keys_ = new ArrayList<Key>();
|
||||
for (Key k : keys)
|
||||
keys_.add(k.removeKeys(f));
|
||||
keys_.add(k.replaceKeys(f));
|
||||
return new Row(keys_, height, shift);
|
||||
}
|
||||
}
|
||||
@ -157,7 +157,7 @@ class KeyboardData
|
||||
return new Key(k0, k1, k2, k3, k4, width, shift);
|
||||
}
|
||||
|
||||
public Key removeKeys(MapKeys f)
|
||||
public Key replaceKeys(MapKeys f)
|
||||
{
|
||||
return new Key(f.map(key0), f.map(key1), f.map(key2), f.map(key3), f.map(key4), width, shift);
|
||||
}
|
||||
@ -168,27 +168,37 @@ class KeyboardData
|
||||
public abstract KeyValue map(KeyValue k);
|
||||
}
|
||||
|
||||
public static class RemoveKeysByFlags implements MapKeys
|
||||
public static class ReplaceKeysByFlags implements MapKeys
|
||||
{
|
||||
private final int _flags;
|
||||
private final KeyValue _replacement;
|
||||
|
||||
public RemoveKeysByFlags(int flags) { _flags = flags; }
|
||||
public ReplaceKeysByFlags(int flags, KeyValue r)
|
||||
{
|
||||
_flags = flags;
|
||||
_replacement = r;
|
||||
}
|
||||
|
||||
public KeyValue map(KeyValue k)
|
||||
{
|
||||
return (k == null || (k.flags & _flags) != 0) ? null : k;
|
||||
return (k != null && (k.flags & _flags) != 0) ? _replacement : k;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RemoveKeysByEvent implements MapKeys
|
||||
public static class ReplaceKeysByEvent implements MapKeys
|
||||
{
|
||||
private final int _eventCode;
|
||||
private final KeyValue _replacement;
|
||||
|
||||
public RemoveKeysByEvent(int ev) { _eventCode = ev; }
|
||||
public ReplaceKeysByEvent(int ev, KeyValue r)
|
||||
{
|
||||
_eventCode = ev;
|
||||
_replacement = r;
|
||||
}
|
||||
|
||||
public KeyValue map(KeyValue k)
|
||||
{
|
||||
return (k == null || k.eventCode == _eventCode) ? null : k;
|
||||
return (k != null && k.eventCode == _eventCode) ? _replacement : k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user