fixed invalid input mode state, causing invalid composing text popping up and invlalid status icon being displayed, when focusing different inputs of the same application
This commit is contained in:
parent
74909aeb7e
commit
0f028cc572
5 changed files with 71 additions and 25 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
package io.github.sspanak.tt9.ime;
|
package io.github.sspanak.tt9.ime;
|
||||||
|
|
||||||
import android.inputmethodservice.InputMethodService;
|
import android.inputmethodservice.InputMethodService;
|
||||||
import android.text.InputType;
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
|
@ -84,22 +83,24 @@ abstract class KeyPadHandler extends InputMethodService {
|
||||||
public void onStartInput(EditorInfo inputField, boolean restarting) {
|
public void onStartInput(EditorInfo inputField, boolean restarting) {
|
||||||
currentInputConnection = getCurrentInputConnection();
|
currentInputConnection = getCurrentInputConnection();
|
||||||
// Logger.d("T9.onStartInput", "inputType: " + inputField.inputType + " fieldId: " + inputField.fieldId + " fieldName: " + inputField.fieldName + " packageName: " + inputField.packageName);
|
// Logger.d("T9.onStartInput", "inputType: " + inputField.inputType + " fieldId: " + inputField.fieldId + " fieldName: " + inputField.fieldName + " packageName: " + inputField.packageName);
|
||||||
|
|
||||||
mEditing = NON_EDIT;
|
|
||||||
|
|
||||||
// https://developer.android.com/reference/android/text/InputType#TYPE_NULL
|
|
||||||
// Special or limited input type. This means the input connection is not rich,
|
|
||||||
// or it can not process or show things like candidate text, nor retrieve the current text.
|
|
||||||
// We just let Android handle this input.
|
|
||||||
if (currentInputConnection == null || inputField == null || inputField.inputType == InputType.TYPE_NULL) {
|
|
||||||
onFinish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
onStart(inputField);
|
onStart(inputField);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartInputView(EditorInfo inputField, boolean restarting) {
|
||||||
|
onRestart(inputField);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinishInputView(boolean finishingInput) {
|
||||||
|
super.onFinishInputView(finishingInput);
|
||||||
|
if (mEditing == EDITING || mEditing == EDITING_NOSHOW) {
|
||||||
|
onFinishTyping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is called when the user is done editing a field. We can use this to
|
* This is called when the user is done editing a field. We can use this to
|
||||||
* reset our state.
|
* reset our state.
|
||||||
|
|
@ -109,7 +110,7 @@ abstract class KeyPadHandler extends InputMethodService {
|
||||||
super.onFinishInput();
|
super.onFinishInput();
|
||||||
// Logger.d("onFinishInput", "When is this called?");
|
// Logger.d("onFinishInput", "When is this called?");
|
||||||
if (mEditing == EDITING || mEditing == EDITING_NOSHOW) {
|
if (mEditing == EDITING || mEditing == EDITING_NOSHOW) {
|
||||||
onFinish();
|
onStop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,6 +334,8 @@ abstract class KeyPadHandler extends InputMethodService {
|
||||||
// helpers
|
// helpers
|
||||||
abstract protected void onInit();
|
abstract protected void onInit();
|
||||||
abstract protected void onStart(EditorInfo inputField);
|
abstract protected void onStart(EditorInfo inputField);
|
||||||
abstract protected void onFinish();
|
abstract protected void onRestart(EditorInfo inputField);
|
||||||
|
abstract protected void onFinishTyping();
|
||||||
|
abstract protected void onStop();
|
||||||
abstract protected View createSoftKeyView();
|
abstract protected View createSoftKeyView();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import io.github.sspanak.tt9.ui.UI;
|
||||||
|
|
||||||
public class TraditionalT9 extends KeyPadHandler {
|
public class TraditionalT9 extends KeyPadHandler {
|
||||||
// internal settings/data
|
// internal settings/data
|
||||||
|
private boolean isActive = false;
|
||||||
private EditorInfo inputField;
|
private EditorInfo inputField;
|
||||||
|
|
||||||
// input mode
|
// input mode
|
||||||
|
|
@ -87,13 +88,12 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void onStart(EditorInfo inputField) {
|
private void initTyping() {
|
||||||
this.inputField = inputField;
|
|
||||||
// in case we are back from Settings screen, update the language list
|
// in case we are back from Settings screen, update the language list
|
||||||
mEnabledLanguages = settings.getEnabledLanguageIds();
|
mEnabledLanguages = settings.getEnabledLanguageIds();
|
||||||
validateLanguages();
|
validateLanguages();
|
||||||
|
|
||||||
// some input fields support only numbers or do not accept predictions
|
// some input fields support only numbers or are not suited for predictions (e.g. password fields)
|
||||||
determineAllowedInputModes();
|
determineAllowedInputModes();
|
||||||
mInputMode = InputModeValidator.validateMode(settings, mInputMode, allowedInputModes);
|
mInputMode = InputModeValidator.validateMode(settings, mInputMode, allowedInputModes);
|
||||||
|
|
||||||
|
|
@ -101,8 +101,10 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
// Some modes may want to change the default text case based on grammar rules.
|
// Some modes may want to change the default text case based on grammar rules.
|
||||||
determineNextTextCase();
|
determineNextTextCase();
|
||||||
InputModeValidator.validateTextCase(settings, mInputMode, settings.getTextCase());
|
InputModeValidator.validateTextCase(settings, mInputMode, settings.getTextCase());
|
||||||
|
}
|
||||||
|
|
||||||
// build the UI
|
|
||||||
|
private void initUi() {
|
||||||
UI.updateStatusIcon(this, mLanguage, mInputMode);
|
UI.updateStatusIcon(this, mLanguage, mInputMode);
|
||||||
|
|
||||||
clearSuggestions();
|
clearSuggestions();
|
||||||
|
|
@ -118,15 +120,43 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && mEditing != EDITING_STRICT_NUMERIC && mEditing != EDITING_DIALER) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && mEditing != EDITING_STRICT_NUMERIC && mEditing != EDITING_DIALER) {
|
||||||
requestShowSelf(1);
|
requestShowSelf(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreAddedWordIfAny();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void onFinish() {
|
protected void onStart(EditorInfo input) {
|
||||||
clearSuggestions();
|
this.inputField = input;
|
||||||
|
if (currentInputConnection == null || inputField == null || InputFieldHelper.isLimitedField(inputField)) {
|
||||||
|
// When the input is invalid or simple, let Android handle it.
|
||||||
|
onStop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
initTyping();
|
||||||
|
initUi();
|
||||||
|
restoreAddedWordIfAny();
|
||||||
|
|
||||||
|
isActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void onRestart(EditorInfo inputField) {
|
||||||
|
if (!isActive) {
|
||||||
|
onStart(inputField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void onFinishTyping() {
|
||||||
|
isActive = false;
|
||||||
|
|
||||||
hideStatusIcon();
|
hideStatusIcon();
|
||||||
|
mEditing = NON_EDIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void onStop() {
|
||||||
|
onFinishTyping();
|
||||||
|
clearSuggestions();
|
||||||
hideWindow();
|
hideWindow();
|
||||||
|
|
||||||
softKeyHandler.hide();
|
softKeyHandler.hide();
|
||||||
|
|
@ -337,7 +367,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
|
|
||||||
private boolean isSuggestionViewHidden() {
|
private boolean isSuggestionViewHidden() {
|
||||||
return mSuggestionView == null || !mSuggestionView.isShown();
|
return mSuggestionView == null || !mSuggestionView.hasElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,18 @@ public class InputFieldHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isLimitedField
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://developer.android.com/reference/android/text/InputType#TYPE_NULL
|
||||||
|
*/
|
||||||
|
public static boolean isLimitedField(EditorInfo inputField) {
|
||||||
|
return inputField != null && inputField.inputType == InputType.TYPE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* isDialerField
|
* isDialerField
|
||||||
* 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,
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ public class InputModeValidator {
|
||||||
|
|
||||||
public static InputMode validateMode(SettingsStore settings, InputMode inputMode, ArrayList<Integer> allowedModes) {
|
public static InputMode validateMode(SettingsStore settings, InputMode inputMode, ArrayList<Integer> allowedModes) {
|
||||||
if (allowedModes.size() > 0 && allowedModes.contains(inputMode.getId())) {
|
if (allowedModes.size() > 0 && allowedModes.contains(inputMode.getId())) {
|
||||||
|
inputMode.reset();
|
||||||
return inputMode;
|
return inputMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ public class SuggestionsView {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isShown() {
|
public boolean hasElements() {
|
||||||
return suggestions.size() > 0;
|
return suggestions.size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue