Fixed unusable hotkeys and typing issues in very specific cases (#258)
* fixed '*', '#', "." and "," not working properly in 123 mode * fixed typing "+" by holding 0-key not working in Dialer fields * fixed Predictive mode not allowing the same key for typing and as a hotkey, when being pressed and held, respectively. * removed EDITING_STRICT_NUMERIC, EDITING_DIALER and deprecated mEditing * added ModeDialer
This commit is contained in:
parent
8949c65f4f
commit
008590bdf8
12 changed files with 142 additions and 71 deletions
|
|
@ -177,6 +177,10 @@ abstract class KeyPadHandler extends InputMethodService {
|
||||||
return onNumber(Key.codeToNumber(settings, keyCode), true, 0);
|
return onNumber(Key.codeToNumber(settings, keyCode), true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Key.isPoundOrStar(keyCode) && onOtherKey(keyCode)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
ignoreNextKeyUp = 0;
|
ignoreNextKeyUp = 0;
|
||||||
return super.onKeyLongPress(keyCode, event);
|
return super.onKeyLongPress(keyCode, event);
|
||||||
}
|
}
|
||||||
|
|
@ -234,7 +238,9 @@ abstract class KeyPadHandler extends InputMethodService {
|
||||||
case KeyEvent.KEYCODE_DPAD_RIGHT: return onRight(keyRepeatCounter > 0);
|
case KeyEvent.KEYCODE_DPAD_RIGHT: return onRight(keyRepeatCounter > 0);
|
||||||
case KeyEvent.KEYCODE_STAR:
|
case KeyEvent.KEYCODE_STAR:
|
||||||
case KeyEvent.KEYCODE_POUND:
|
case KeyEvent.KEYCODE_POUND:
|
||||||
return onOtherKey(keyCode);
|
if (onOtherKey(keyCode)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onKeyUp(keyCode, event);
|
return super.onKeyUp(keyCode, event);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import io.github.sspanak.tt9.Logger;
|
||||||
import io.github.sspanak.tt9.db.DictionaryDb;
|
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputModeValidator;
|
import io.github.sspanak.tt9.ime.helpers.InputModeValidator;
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.ime.helpers.InputType;
|
||||||
import io.github.sspanak.tt9.ime.helpers.Key;
|
|
||||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
@ -34,9 +33,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
// editing mode
|
// editing mode
|
||||||
protected static final int NON_EDIT = 0;
|
protected static final int NON_EDIT = 0;
|
||||||
protected static final int EDITING = 1;
|
protected static final int EDITING = 1;
|
||||||
protected static final int EDITING_STRICT_NUMERIC = 3;
|
@Deprecated protected int mEditing = NON_EDIT; // @todo: migrate to "isActive"
|
||||||
protected static final int EDITING_DIALER = 4; // see: https://github.com/sspanak/tt9/issues/46
|
|
||||||
protected int mEditing = NON_EDIT;
|
|
||||||
|
|
||||||
// input mode
|
// input mode
|
||||||
private ArrayList<Integer> allowedInputModes = new ArrayList<>();
|
private ArrayList<Integer> allowedInputModes = new ArrayList<>();
|
||||||
|
|
@ -185,7 +182,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
// 1. Dialer fields seem to handle backspace on their own and we must ignore it,
|
// 1. Dialer fields seem to handle backspace on their own and we must ignore it,
|
||||||
// otherwise, keyDown race condition occur for all keys.
|
// otherwise, keyDown race condition occur for all keys.
|
||||||
// 2. Allow the assigned key to function normally, when there is no text (e.g. "Back" navigates back)
|
// 2. Allow the assigned key to function normally, when there is no text (e.g. "Back" navigates back)
|
||||||
if (mEditing == EDITING_DIALER || !textField.isThereText()) {
|
if (mInputMode.isDialer() || !textField.isThereText()) {
|
||||||
Logger.d("onBackspace", "backspace ignored");
|
Logger.d("onBackspace", "backspace ignored");
|
||||||
mInputMode.reset();
|
mInputMode.reset();
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -316,21 +313,20 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
|
|
||||||
public boolean onOtherKey(int keyCode) {
|
public boolean onOtherKey(int keyCode) {
|
||||||
if (
|
String acceptedWord = acceptIncompleteSuggestion();
|
||||||
keyCode <= 0 ||
|
if (mInputMode.onOtherKey(keyCode)) {
|
||||||
(mEditing == EDITING_STRICT_NUMERIC || mEditing == EDITING_DIALER) && !Key.isNumber(keyCode)
|
autoCorrectSpace(acceptedWord, false);
|
||||||
) {
|
getSuggestions();
|
||||||
return false;
|
resetKeyRepeat();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
autoCorrectSpace(acceptIncompleteSuggestion(), false);
|
return acceptedWord.length() > 0;
|
||||||
sendDownUpKeyEvents(keyCode);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean onText(String text) {
|
public boolean onText(String text) {
|
||||||
if (mEditing == EDITING_STRICT_NUMERIC || mEditing == EDITING_DIALER || text.length() == 0) {
|
if (mInputMode.isNumeric() || text.length() == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -346,7 +342,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
|
|
||||||
public boolean onKeyAddWord() {
|
public boolean onKeyAddWord() {
|
||||||
if (mEditing == EDITING_STRICT_NUMERIC || mEditing == EDITING_DIALER) {
|
if (!isInputViewShown() || mInputMode.isNumeric()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,14 +372,19 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
public boolean onKeyNextInputMode() {
|
public boolean onKeyNextInputMode() {
|
||||||
nextInputMode();
|
nextInputMode();
|
||||||
|
|
||||||
|
if (allowedInputModes.size() == 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
mainView.render();
|
mainView.render();
|
||||||
forceShowWindowIfHidden();
|
forceShowWindowIfHidden();
|
||||||
return (mEditing != EDITING_STRICT_NUMERIC && mEditing != EDITING_DIALER);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean onKeyShowSettings() {
|
public boolean onKeyShowSettings() {
|
||||||
if (mEditing == EDITING_DIALER) {
|
if (!isInputViewShown()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -393,11 +394,11 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
|
|
||||||
protected boolean shouldTrackUpDown() {
|
protected boolean shouldTrackUpDown() {
|
||||||
return mEditing != EDITING_STRICT_NUMERIC && !isSuggestionViewHidden() && mInputMode.shouldTrackUpDown();
|
return !isSuggestionViewHidden() && mInputMode.shouldTrackUpDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldTrackLeftRight() {
|
protected boolean shouldTrackLeftRight() {
|
||||||
return mEditing != EDITING_STRICT_NUMERIC && !isSuggestionViewHidden() && mInputMode.shouldTrackLeftRight();
|
return !isSuggestionViewHidden() && mInputMode.shouldTrackLeftRight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -474,7 +475,8 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
// key code "suggestions" take priority over words
|
// key code "suggestions" take priority over words
|
||||||
if (mInputMode.getKeyCode() > 0) {
|
if (mInputMode.getKeyCode() > 0) {
|
||||||
sendDownUpKeyEvents(mInputMode.getKeyCode());
|
sendDownUpKeyEvents(mInputMode.getKeyCode());
|
||||||
mInputMode.onAcceptSuggestion(null);
|
mInputMode.onAcceptSuggestion("");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// display the list of suggestions
|
// display the list of suggestions
|
||||||
|
|
@ -522,7 +524,9 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
|
|
||||||
private void nextInputMode() {
|
private void nextInputMode() {
|
||||||
if (mEditing == EDITING_STRICT_NUMERIC || mEditing == EDITING_DIALER) {
|
if (mInputMode.isDialer()) {
|
||||||
|
return;
|
||||||
|
} else if (allowedInputModes.size() == 1 && allowedInputModes.contains(InputMode.MODE_123)) {
|
||||||
mInputMode = !mInputMode.is123() ? InputMode.getInstance(settings, mLanguage, InputMode.MODE_123) : mInputMode;
|
mInputMode = !mInputMode.is123() ? InputMode.getInstance(settings, mLanguage, InputMode.MODE_123) : mInputMode;
|
||||||
}
|
}
|
||||||
// when typing a word or viewing scrolling the suggestions, only change the case
|
// when typing a word or viewing scrolling the suggestions, only change the case
|
||||||
|
|
@ -562,7 +566,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
|
|
||||||
private boolean nextLang() {
|
private boolean nextLang() {
|
||||||
if (mInputMode.is123() || mEnabledLanguages.size() < 2) {
|
if (mInputMode.isNumeric() || mEnabledLanguages.size() < 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -597,19 +601,15 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
int lastInputModeId = settings.getInputMode();
|
int lastInputModeId = settings.getInputMode();
|
||||||
if (allowedInputModes.contains(lastInputModeId)) {
|
if (allowedInputModes.contains(lastInputModeId)) {
|
||||||
mInputMode = InputMode.getInstance(settings, mLanguage, lastInputModeId);
|
mInputMode = InputMode.getInstance(settings, mLanguage, lastInputModeId);
|
||||||
|
} else if (allowedInputModes.size() == 1 && allowedInputModes.get(0) == InputMode.MODE_DIALER) {
|
||||||
|
mInputMode = InputMode.getInstance(settings, mLanguage, InputMode.MODE_DIALER);
|
||||||
} else if (allowedInputModes.contains(InputMode.MODE_ABC)) {
|
} else if (allowedInputModes.contains(InputMode.MODE_ABC)) {
|
||||||
mInputMode = InputMode.getInstance(settings, mLanguage, InputMode.MODE_ABC);
|
mInputMode = InputMode.getInstance(settings, mLanguage, InputMode.MODE_ABC);
|
||||||
} else {
|
} else {
|
||||||
mInputMode = InputMode.getInstance(settings, mLanguage, allowedInputModes.get(0));
|
mInputMode = InputMode.getInstance(settings, mLanguage, allowedInputModes.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputType.isDialer()) {
|
mEditing = EDITING;
|
||||||
mEditing = EDITING_DIALER;
|
|
||||||
} else if (mInputMode.is123() && allowedInputModes.size() == 1) {
|
|
||||||
mEditing = EDITING_STRICT_NUMERIC;
|
|
||||||
} else {
|
|
||||||
mEditing = EDITING;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -721,8 +721,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
*/
|
*/
|
||||||
protected void forceShowWindowIfHidden() {
|
protected void forceShowWindowIfHidden() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
|
||||||
&& mEditing != EDITING_STRICT_NUMERIC
|
&& !mInputMode.isDialer()
|
||||||
&& mEditing != EDITING_DIALER
|
|
||||||
&& !isInputViewShown()
|
&& !isInputViewShown()
|
||||||
) {
|
) {
|
||||||
requestShowSelf(InputMethodManager.SHOW_IMPLICIT);
|
requestShowSelf(InputMethodManager.SHOW_IMPLICIT);
|
||||||
|
|
@ -732,7 +731,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldBeVisible() {
|
protected boolean shouldBeVisible() {
|
||||||
return mEditing != EDITING_DIALER && mEditing != NON_EDIT;
|
return !mInputMode.isDialer() && mEditing != NON_EDIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ public class InputType {
|
||||||
* Special or limited input type means the input connection is not rich,
|
* Special or limited input type means the input connection is not rich,
|
||||||
* or it can not process or show things like candidate text, nor retrieve the current text.
|
* or it can not process or show things like candidate text, nor retrieve the current text.
|
||||||
*
|
*
|
||||||
* <a href="https://developer.android.com/reference/android/text/InputType#TYPE_NULL">...</a>
|
* More info: <a href="https://developer.android.com/reference/android/text/InputType#TYPE_NULL">android docs</a>.
|
||||||
*/
|
*/
|
||||||
public boolean isLimited() {
|
public boolean isLimited() {
|
||||||
return field != null && field.inputType == android.text.InputType.TYPE_NULL;
|
return field != null && field.inputType == android.text.InputType.TYPE_NULL;
|
||||||
|
|
@ -37,7 +37,11 @@ public class InputType {
|
||||||
* Dialer fields seem to take care of numbers and backspace on their own,
|
* Dialer fields seem to take care of numbers and backspace on their own,
|
||||||
* so we need to be aware of them.
|
* so we need to be aware of them.
|
||||||
*
|
*
|
||||||
* NOTE: A Dialer field is not the same as a Phone field in a phone book.
|
* NOTE: A Dialer field is not the same as Phone field. Dialer is where you
|
||||||
|
* actually dial and call a phone number. While the Phone field is a text
|
||||||
|
* field in any app or a webpage, intended for typing phone numbers.
|
||||||
|
*
|
||||||
|
* More info: <a href="https://github.com/sspanak/tt9/issues/46">in this Github issue</a>.
|
||||||
*/
|
*/
|
||||||
public boolean isDialer() {
|
public boolean isDialer() {
|
||||||
if (field == null) {
|
if (field == null) {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,17 @@ public class Key {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isPoundOrStar(int keyCode) {
|
||||||
|
return keyCode == KeyEvent.KEYCODE_POUND || keyCode == KeyEvent.KEYCODE_STAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isDecimalSeparator(int keyCode) {
|
||||||
|
return
|
||||||
|
keyCode == KeyEvent.KEYCODE_COMMA
|
||||||
|
|| keyCode == KeyEvent.KEYCODE_NUMPAD_DOT
|
||||||
|
|| keyCode == KeyEvent.KEYCODE_PERIOD;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isOK(int keyCode) {
|
public static boolean isOK(int keyCode) {
|
||||||
return
|
return
|
||||||
keyCode == KeyEvent.KEYCODE_DPAD_CENTER
|
keyCode == KeyEvent.KEYCODE_DPAD_CENTER
|
||||||
|
|
|
||||||
|
|
@ -90,14 +90,19 @@ public class TextField {
|
||||||
return allowedModes;
|
return allowedModes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dialer field, not to be confused with Phone text field.
|
||||||
|
// It only accepts 0-9, "#" and "*".
|
||||||
|
if (inputType.isDialer()) {
|
||||||
|
allowedModes.add(InputMode.MODE_DIALER);
|
||||||
|
return allowedModes;
|
||||||
|
}
|
||||||
|
|
||||||
switch (field.inputType & android.text.InputType.TYPE_MASK_CLASS) {
|
switch (field.inputType & android.text.InputType.TYPE_MASK_CLASS) {
|
||||||
case android.text.InputType.TYPE_CLASS_NUMBER:
|
case android.text.InputType.TYPE_CLASS_NUMBER:
|
||||||
case android.text.InputType.TYPE_CLASS_DATETIME:
|
case android.text.InputType.TYPE_CLASS_DATETIME:
|
||||||
// Numbers and dates default to the symbols keyboard, with
|
|
||||||
// no extra features.
|
|
||||||
case android.text.InputType.TYPE_CLASS_PHONE:
|
case android.text.InputType.TYPE_CLASS_PHONE:
|
||||||
// Phones will also default to the symbols keyboard, though
|
// Numbers, dates and phone numbers default to the numeric keyboard,
|
||||||
// often you will want to have a dedicated phone keyboard.
|
// with no extra features.
|
||||||
allowedModes.add(InputMode.MODE_123);
|
allowedModes.add(InputMode.MODE_123);
|
||||||
return allowedModes;
|
return allowedModes;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package io.github.sspanak.tt9.ime.modes;
|
package io.github.sspanak.tt9.ime.modes;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.Logger;
|
||||||
|
|
@ -13,6 +15,7 @@ abstract public class InputMode {
|
||||||
public static final int MODE_PREDICTIVE = 0;
|
public static final int MODE_PREDICTIVE = 0;
|
||||||
public static final int MODE_ABC = 1;
|
public static final int MODE_ABC = 1;
|
||||||
public static final int MODE_123 = 2;
|
public static final int MODE_123 = 2;
|
||||||
|
public static final int MODE_DIALER = 4;
|
||||||
|
|
||||||
// text case
|
// text case
|
||||||
public static final int CASE_UNDEFINED = -1;
|
public static final int CASE_UNDEFINED = -1;
|
||||||
|
|
@ -37,6 +40,8 @@ abstract public class InputMode {
|
||||||
return new ModePredictive(settings, language);
|
return new ModePredictive(settings, language);
|
||||||
case MODE_ABC:
|
case MODE_ABC:
|
||||||
return new ModeABC(language);
|
return new ModeABC(language);
|
||||||
|
case MODE_DIALER:
|
||||||
|
return new ModeDialer();
|
||||||
default:
|
default:
|
||||||
Logger.w("tt9/InputMode", "Defaulting to mode: " + Mode123.class.getName() + " for unknown InputMode: " + mode);
|
Logger.w("tt9/InputMode", "Defaulting to mode: " + Mode123.class.getName() + " for unknown InputMode: " + mode);
|
||||||
case MODE_123:
|
case MODE_123:
|
||||||
|
|
@ -47,18 +52,19 @@ abstract public class InputMode {
|
||||||
// Key handlers. Return "true" when handling the key or "false", when is nothing to do.
|
// Key handlers. Return "true" when handling the key or "false", when is nothing to do.
|
||||||
public boolean onBackspace() { return false; }
|
public boolean onBackspace() { return false; }
|
||||||
abstract public boolean onNumber(int number, boolean hold, int repeat);
|
abstract public boolean onNumber(int number, boolean hold, int repeat);
|
||||||
|
abstract public boolean onOtherKey(int key);
|
||||||
|
|
||||||
// Suggestions
|
// Suggestions
|
||||||
public void onAcceptSuggestion(String suggestion) {}
|
public void onAcceptSuggestion(@NonNull String suggestion) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* loadSuggestions
|
* loadSuggestions
|
||||||
* Loads the suggestions based on the current state, with optional "currentWord" filter.
|
* Loads the suggestions based on the current state, with optional "currentWord" filter.
|
||||||
* Once loading is finished the respective InputMode child will call "notification", notifying it
|
* Once loading is finished the respective InputMode child will call "onLoad", notifying it
|
||||||
* the suggestions are available using "getSuggestions()".
|
* the suggestions are available using "getSuggestions()".
|
||||||
*/
|
*/
|
||||||
public void loadSuggestions(Runnable notification, String currentWord) {
|
public void loadSuggestions(Runnable onLoad, String currentWord) {
|
||||||
notification.run();
|
onLoad.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<String> getSuggestions() {
|
public ArrayList<String> getSuggestions() {
|
||||||
|
|
@ -71,9 +77,10 @@ abstract public class InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mode identifiers
|
// Mode identifiers
|
||||||
public boolean isPredictive() { return false; }
|
|
||||||
public boolean isABC() { return false; }
|
public boolean isABC() { return false; }
|
||||||
public boolean is123() { return false; }
|
public boolean is123() { return false; }
|
||||||
|
public boolean isDialer() { return false; }
|
||||||
|
public boolean isNumeric() { return false; }
|
||||||
|
|
||||||
// Utility
|
// Utility
|
||||||
abstract public int getId();
|
abstract public int getId();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package io.github.sspanak.tt9.ime.modes;
|
package io.github.sspanak.tt9.ime.modes;
|
||||||
|
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ime.helpers.Key;
|
import io.github.sspanak.tt9.ime.helpers.Key;
|
||||||
|
|
@ -14,19 +16,23 @@ public class Mode123 extends InputMode {
|
||||||
@Override
|
@Override
|
||||||
public boolean onNumber(int number, boolean hold, int repeat) {
|
public boolean onNumber(int number, boolean hold, int repeat) {
|
||||||
reset();
|
reset();
|
||||||
|
keyCode = (number == 0 && hold) ? KeyEvent.KEYCODE_PLUS : Key.numberToCode(number);
|
||||||
if (number == 0 && hold) {
|
|
||||||
autoAcceptTimeout = 0;
|
|
||||||
suggestions.add("+");
|
|
||||||
} else {
|
|
||||||
keyCode = Key.numberToCode(number);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOtherKey(int key) {
|
||||||
|
reset();
|
||||||
|
if (Key.isDecimalSeparator(key) || Key.isPoundOrStar(key)) {
|
||||||
|
keyCode = key;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override final public boolean is123() { return true; }
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean is123() { return true; }
|
||||||
|
@Override final public boolean isNumeric() { return true; }
|
||||||
@Override public int getSequenceLength() { return 0; }
|
@Override public int getSequenceLength() { return 0; }
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,25 @@ public class ModeABC extends InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOtherKey(int key) {
|
||||||
|
reset();
|
||||||
|
|
||||||
|
if (key > 0) {
|
||||||
|
keyCode = key;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String adjustSuggestionTextCase(String word, int newTextCase) {
|
protected String adjustSuggestionTextCase(String word, int newTextCase) {
|
||||||
return newTextCase == CASE_UPPER ? word.toUpperCase(language.getLocale()) : word.toLowerCase(language.getLocale());
|
return newTextCase == CASE_UPPER ? word.toUpperCase(language.getLocale()) : word.toLowerCase(language.getLocale());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changeLanguage(Language language) {
|
public void changeLanguage(Language language) {
|
||||||
super.changeLanguage(language);
|
super.changeLanguage(language);
|
||||||
|
|
|
||||||
15
src/io/github/sspanak/tt9/ime/modes/ModeDialer.java
Normal file
15
src/io/github/sspanak/tt9/ime/modes/ModeDialer.java
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
package io.github.sspanak.tt9.ime.modes;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.ime.helpers.Key;
|
||||||
|
|
||||||
|
// see: InputType.isDialer()
|
||||||
|
public class ModeDialer extends Mode123 {
|
||||||
|
@Override public int getId() { return MODE_DIALER; }
|
||||||
|
@Override public boolean is123() { return false; }
|
||||||
|
@Override final public boolean isDialer() { return true; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOtherKey(int key) {
|
||||||
|
return !Key.isDecimalSeparator(key) && super.onOtherKey(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -86,6 +86,20 @@ public class ModePredictive extends InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOtherKey(int key) {
|
||||||
|
reset();
|
||||||
|
|
||||||
|
if (key > 0) {
|
||||||
|
disablePredictions = true;
|
||||||
|
keyCode = key;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changeLanguage(Language language) {
|
public void changeLanguage(Language language) {
|
||||||
super.changeLanguage(language);
|
super.changeLanguage(language);
|
||||||
|
|
@ -191,13 +205,13 @@ public class ModePredictive extends InputMode {
|
||||||
* See: Predictions.generatePossibleCompletions()
|
* See: Predictions.generatePossibleCompletions()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void loadSuggestions(Runnable handler, String currentWord) {
|
public void loadSuggestions(Runnable onLoad, String currentWord) {
|
||||||
if (disablePredictions) {
|
if (disablePredictions) {
|
||||||
super.loadSuggestions(handler, currentWord);
|
super.loadSuggestions(onLoad, currentWord);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSuggestionsUpdated = handler;
|
onSuggestionsUpdated = onLoad;
|
||||||
predictions
|
predictions
|
||||||
.setDigitSequence(digitSequence)
|
.setDigitSequence(digitSequence)
|
||||||
.setIsStemFuzzy(isStemFuzzy)
|
.setIsStemFuzzy(isStemFuzzy)
|
||||||
|
|
@ -227,7 +241,7 @@ public class ModePredictive extends InputMode {
|
||||||
* Bring this word up in the suggestions list next time.
|
* Bring this word up in the suggestions list next time.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onAcceptSuggestion(String currentWord) {
|
public void onAcceptSuggestion(@NonNull String currentWord) {
|
||||||
lastAcceptedWord = currentWord;
|
lastAcceptedWord = currentWord;
|
||||||
lastAcceptedSequence = digitSequence;
|
lastAcceptedSequence = digitSequence;
|
||||||
reset();
|
reset();
|
||||||
|
|
@ -314,7 +328,6 @@ public class ModePredictive extends InputMode {
|
||||||
@Override public boolean shouldTrackUpDown() { return true; }
|
@Override public boolean shouldTrackUpDown() { return true; }
|
||||||
@Override public boolean shouldTrackLeftRight() { return true; }
|
@Override public boolean shouldTrackLeftRight() { return true; }
|
||||||
|
|
||||||
@Override final public boolean isPredictive() { return true; }
|
|
||||||
@Override public int getSequenceLength() { return digitSequence.length(); }
|
@Override public int getSequenceLength() { return digitSequence.length(); }
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|
|
||||||
|
|
@ -102,18 +102,9 @@ public class Hotkeys {
|
||||||
*
|
*
|
||||||
* NOTE: Some TT9 functions do not support all keys. Here you just list all possible options.
|
* NOTE: Some TT9 functions do not support all keys. Here you just list all possible options.
|
||||||
* Actual validation and assigning happens in SectionKeymap.populate().
|
* Actual validation and assigning happens in SectionKeymap.populate().
|
||||||
*
|
|
||||||
* NOTE 2: Holding is deliberately skipped for most of the keys.
|
|
||||||
* It's because handling holding requires short press event to be consumed in
|
|
||||||
* KeyPadHandler, as well.
|
|
||||||
*
|
|
||||||
* From user perspective, when holding is assigned to a function,
|
|
||||||
* short press will also stop performing its default system action, which may be confusing.
|
|
||||||
* And in order to avoid lengthy explanations in the documentation (that no one reads),
|
|
||||||
* the problem is avoided by simply not causing it.
|
|
||||||
*/
|
*/
|
||||||
private void generateList() {
|
private void generateList() {
|
||||||
add(KeyEvent.KEYCODE_CALL, R.string.key_call, false);
|
add(KeyEvent.KEYCODE_CALL, R.string.key_call, true);
|
||||||
|
|
||||||
addIfDeviceHasKey(KeyEvent.KEYCODE_BACK, R.string.key_back, false);
|
addIfDeviceHasKey(KeyEvent.KEYCODE_BACK, R.string.key_back, false);
|
||||||
addIfDeviceHasKey(KeyEvent.KEYCODE_CLEAR, R.string.key_clear, false);
|
addIfDeviceHasKey(KeyEvent.KEYCODE_CLEAR, R.string.key_clear, false);
|
||||||
|
|
@ -122,7 +113,7 @@ public class Hotkeys {
|
||||||
addIfDeviceHasKey(KeyEvent.KEYCODE_F2, "F2", true);
|
addIfDeviceHasKey(KeyEvent.KEYCODE_F2, "F2", true);
|
||||||
addIfDeviceHasKey(KeyEvent.KEYCODE_F3, "F3", true);
|
addIfDeviceHasKey(KeyEvent.KEYCODE_F3, "F3", true);
|
||||||
addIfDeviceHasKey(KeyEvent.KEYCODE_F4, "F4", true);
|
addIfDeviceHasKey(KeyEvent.KEYCODE_F4, "F4", true);
|
||||||
addIfDeviceHasKey(KeyEvent.KEYCODE_MENU, R.string.key_menu, false);
|
addIfDeviceHasKey(KeyEvent.KEYCODE_MENU, R.string.key_menu, true);
|
||||||
addIfDeviceHasKey(KeyEvent.KEYCODE_SOFT_LEFT, R.string.key_soft_left, false);
|
addIfDeviceHasKey(KeyEvent.KEYCODE_SOFT_LEFT, R.string.key_soft_left, false);
|
||||||
addIfDeviceHasKey(KeyEvent.KEYCODE_SOFT_RIGHT, R.string.key_soft_right, false);
|
addIfDeviceHasKey(KeyEvent.KEYCODE_SOFT_RIGHT, R.string.key_soft_right, false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ public class SoftPunctuationKey extends SoftKey {
|
||||||
|
|
||||||
preventRepeat();
|
preventRepeat();
|
||||||
int keyId = getId();
|
int keyId = getId();
|
||||||
if (keyId == R.id.soft_key_punctuation_1) return tt9.onText(",");
|
if (keyId == R.id.soft_key_punctuation_1) return tt9.onOtherKey(KeyEvent.KEYCODE_COMMA);
|
||||||
if (keyId == R.id.soft_key_punctuation_2) return tt9.onText(".");
|
if (keyId == R.id.soft_key_punctuation_2) return tt9.onOtherKey(KeyEvent.KEYCODE_PERIOD);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue