Add keys for entering the current suggestions (#1176)
This adds the new "Stateful" kind of keys, for which the symbol is dynamically computed from the app's state. This is implemented with a hook directly in KeyValue. 3 keys are added for accessing the 3 words on the candidates view.
This commit is contained in:
@@ -192,6 +192,15 @@ Value | Meaning
|
||||
`shareText` | Emit a share Intent for the selected text. **Oddity:** This is in CamelCase.
|
||||
`hide_self` | Hide the keyboard.
|
||||
|
||||
## Suggestions
|
||||
|
||||
Value | Meaning
|
||||
:---- | :------
|
||||
`complete_first` | Enter the best suggestion (the one in the middle)
|
||||
`complete_second` | Enter the second best suggestion (the right one)
|
||||
`complete_third` | Enter the third best suggestion (the left one)
|
||||
`complete_emoji` | Enter the emoji suggestion
|
||||
|
||||
## Unused
|
||||
These keys are known to do nothing.
|
||||
|
||||
|
||||
@@ -36,14 +36,14 @@ public final class KeyEventHandler
|
||||
LastAction _last_action = null;
|
||||
LastAction _next_last_action = null;
|
||||
|
||||
public KeyEventHandler(IReceiver recv, Config config)
|
||||
public KeyEventHandler(IReceiver recv, Suggestions sg)
|
||||
{
|
||||
_recv = recv;
|
||||
Handler handler = recv.getHandler();
|
||||
_autocap = new Autocapitalisation(handler,
|
||||
this.new Autocapitalisation_callback());
|
||||
_mods = Pointers.Modifiers.EMPTY;
|
||||
_suggestions = new Suggestions(recv, config);
|
||||
_suggestions = sg;
|
||||
_typedword = new CurrentlyTypedWord(handler, this);
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@ public final class KeyEventHandler
|
||||
case Compose_pending: _recv.set_compose_pending(true); break;
|
||||
case Slider: handle_slider(key.getSlider(), key.getSliderRepeat(), false); break;
|
||||
case Macro: evaluate_macro(key.getMacro()); break;
|
||||
case Stateful: handle_stateful(key.getStateful()); break;
|
||||
}
|
||||
update_meta_state(old_mods);
|
||||
_last_action = _next_last_action;
|
||||
@@ -334,6 +335,19 @@ public final class KeyEventHandler
|
||||
}
|
||||
}
|
||||
|
||||
void handle_stateful(KeyValue.Stateful st)
|
||||
{
|
||||
switch (st)
|
||||
{
|
||||
case Complete_first:
|
||||
case Complete_second:
|
||||
case Complete_third:
|
||||
case Complete_emoji:
|
||||
suggestion_entered(st.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Move the cursor right or left, if possible without sending key events.
|
||||
Unlike arrow keys, the selection is not removed even if shift is not on.
|
||||
Falls back to sending arrow keys events if the editor do not support
|
||||
|
||||
@@ -105,6 +105,7 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
String, // [_payload] is also the string to output, value is unused.
|
||||
Slider, // [_payload] is a [KeyValue.Slider], value is slider repeatition.
|
||||
Macro, // [_payload] is a [KeyValue.Macro], value is unused.
|
||||
Stateful, // [_payload] is a [KeyValue.Stateful], value is the query.
|
||||
}
|
||||
|
||||
private static final int FLAGS_OFFSET = 20;
|
||||
@@ -239,6 +240,12 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
return ((Macro)_payload).keys;
|
||||
}
|
||||
|
||||
/** Defined only when [getKind() == Kind.Stateful]. */
|
||||
public Stateful getStateful()
|
||||
{
|
||||
return (Stateful)_payload;
|
||||
}
|
||||
|
||||
/* Update the char and the symbol. */
|
||||
public KeyValue withChar(char c)
|
||||
{
|
||||
@@ -423,6 +430,11 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
id.ordinal(), flags | FLAG_KEY_FONT);
|
||||
}
|
||||
|
||||
private static KeyValue statefulKey(Stateful st)
|
||||
{
|
||||
return new KeyValue(st, Kind.Stateful, 0, FLAG_SMALLER_FONT);
|
||||
}
|
||||
|
||||
public static KeyValue makeStringKey(String str)
|
||||
{
|
||||
return makeStringKey(str, 0);
|
||||
@@ -644,6 +656,10 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
case "capslock": return eventKey(0xE012, Event.CAPS_LOCK, 0);
|
||||
case "voice_typing": return eventKey(0xE015, Event.SWITCH_VOICE_TYPING, FLAG_SMALLER_FONT);
|
||||
case "voice_typing_chooser": return VOICE_TYPING_CHOOSER;
|
||||
case "complete_first": return statefulKey(Stateful.Complete_first);
|
||||
case "complete_second": return statefulKey(Stateful.Complete_second);
|
||||
case "complete_third": return statefulKey(Stateful.Complete_third);
|
||||
case "complete_emoji": return statefulKey(Stateful.Complete_emoji);
|
||||
case "hide_self": return eventKey("⊻", Event.HIDE_SELF, FLAG_SMALLER_FONT);
|
||||
|
||||
/* Key events */
|
||||
@@ -914,4 +930,33 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
return _symbol.compareTo(snd._symbol);
|
||||
}
|
||||
};
|
||||
|
||||
/** Stateful keys are keys whose symbol must be constantly computed from the
|
||||
app's state. */
|
||||
public static enum Stateful implements Describe
|
||||
{
|
||||
Complete_first,
|
||||
Complete_second,
|
||||
Complete_third,
|
||||
Complete_emoji;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
if (_handler == null)
|
||||
return "";
|
||||
String s = _handler.provide_stateful_key_symbol(this);
|
||||
return (s == null) ? "" : s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String describe() { return name(); }
|
||||
|
||||
public static Symbol_provider _handler = null;
|
||||
|
||||
public static interface Symbol_provider
|
||||
{
|
||||
public String provide_stateful_key_symbol(Stateful q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ public class Keyboard2 extends InputMethodService
|
||||
private ViewGroup _keyboard_container_view;
|
||||
private Keyboard2View _keyboard_layout_view;
|
||||
private CandidatesView _candidates_view;
|
||||
private Suggestions _suggestions;
|
||||
private KeyEventHandler _keyeventhandler;
|
||||
/** If not 'null', the layout to use instead of [_config.current_layout]. */
|
||||
private KeyboardData _currentSpecialLayout;
|
||||
@@ -126,7 +127,10 @@ public class Keyboard2 extends InputMethodService
|
||||
Config.initGlobalConfig(prefs, getResources(),
|
||||
_foldStateTracker.isUnfolded(), _dictionaries);
|
||||
_config = Config.globalConfig();
|
||||
_keyeventhandler = new KeyEventHandler(this.new Receiver(), _config);
|
||||
Receiver recvr = this.new Receiver();
|
||||
_suggestions = new Suggestions(recvr, _config);
|
||||
_keyeventhandler = new KeyEventHandler(recvr, _suggestions);
|
||||
KeyValue.Stateful._handler = recvr;
|
||||
_config.handler = _keyeventhandler;
|
||||
prefs.registerOnSharedPreferenceChangeListener(this);
|
||||
Logs.set_debug_logs(getResources().getBoolean(R.bool.debug_logs));
|
||||
@@ -391,7 +395,8 @@ public class Keyboard2 extends InputMethodService
|
||||
}
|
||||
|
||||
/** Not static */
|
||||
public class Receiver implements KeyEventHandler.IReceiver
|
||||
public class Receiver implements KeyEventHandler.IReceiver,
|
||||
KeyValue.Stateful.Symbol_provider
|
||||
{
|
||||
public void handle_event_key(KeyValue.Event ev)
|
||||
{
|
||||
@@ -512,6 +517,18 @@ public class Keyboard2 extends InputMethodService
|
||||
{
|
||||
_candidates_view.set_candidates(suggestions);
|
||||
}
|
||||
|
||||
public String provide_stateful_key_symbol(KeyValue.Stateful q)
|
||||
{
|
||||
switch (q)
|
||||
{
|
||||
case Complete_first: return _suggestions.suggestions[0];
|
||||
case Complete_second: return _suggestions.suggestions[1];
|
||||
case Complete_third: return _suggestions.suggestions[2];
|
||||
case Complete_emoji: return _suggestions.emoji_suggestion;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private IBinder getConnectionToken()
|
||||
|
||||
Reference in New Issue
Block a user