Android: Move textfield option handling to QtEditText

Previously QtEditText input method hints, input type and caps mode were
parsed and set inside QtInputDelegate. Given these things are only
relevant for QtEditText and did not use any QtInputDelegate internals,
moved them to QtEditText.

Task-number: QTBUG-118139
Change-Id: I5162e890679f6e14adf42647572c0fb96ad451b9
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
(cherry picked from commit 1ed1122fc3fb2c1cbdc3befec584e4e84754ef01)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Petri Virkkunen 2024-02-01 14:52:11 +02:00 committed by Qt Cherry-pick Bot
parent 9d0137cce1
commit 4247c25b1f
2 changed files with 135 additions and 133 deletions

View File

@ -21,6 +21,32 @@ class QtEditText extends View
int m_inputType = InputType.TYPE_CLASS_TEXT;
boolean m_optionsChanged = false;
QtInputConnection m_inputConnection = null;
// input method hints - must be kept in sync with QTDIR/src/corelib/global/qnamespace.h
private final int ImhHiddenText = 0x1;
private final int ImhSensitiveData = 0x2;
private final int ImhNoAutoUppercase = 0x4;
private final int ImhPreferNumbers = 0x8;
private final int ImhPreferUppercase = 0x10;
private final int ImhPreferLowercase = 0x20;
private final int ImhNoPredictiveText = 0x40;
private final int ImhDate = 0x80;
private final int ImhTime = 0x100;
private final int ImhPreferLatin = 0x200;
private final int ImhMultiLine = 0x400;
private final int ImhDigitsOnly = 0x10000;
private final int ImhFormattedNumbersOnly = 0x20000;
private final int ImhUppercaseOnly = 0x40000;
private final int ImhLowercaseOnly = 0x80000;
private final int ImhDialableCharactersOnly = 0x100000;
private final int ImhEmailCharactersOnly = 0x200000;
private final int ImhUrlCharactersOnly = 0x400000;
private final int ImhLatinOnly = 0x800000;
private QtInputConnectionListener m_qtInputConnectionListener;
public void setQtInputConnectionListener(QtInputConnectionListener listener)
@ -28,7 +54,7 @@ class QtEditText extends View
m_qtInputConnectionListener = listener;
}
public void setImeOptions(int m_imeOptions)
private void setImeOptions(int m_imeOptions)
{
if (m_imeOptions == this.m_imeOptions)
return;
@ -36,7 +62,7 @@ class QtEditText extends View
m_optionsChanged = true;
}
public void setInitialCapsMode(int m_initialCapsMode)
private void setInitialCapsMode(int m_initialCapsMode)
{
if (m_initialCapsMode == this.m_initialCapsMode)
return;
@ -45,7 +71,7 @@ class QtEditText extends View
}
public void setInputType(int m_inputType)
private void setInputType(int m_inputType)
{
if (m_inputType == this.m_inputType)
return;
@ -91,4 +117,109 @@ class QtEditText extends View
// canvas.drawARGB(127, 255, 0, 255);
super.onDraw(canvas);
}
public void setEditTextOptions(int enterKeyType, int inputHints)
{
int initialCapsMode = 0;
int imeOptions = imeOptionsFromEnterKeyType(enterKeyType);
int inputType = android.text.InputType.TYPE_CLASS_TEXT;
if ((inputHints & (ImhPreferNumbers | ImhDigitsOnly | ImhFormattedNumbersOnly)) != 0) {
inputType = android.text.InputType.TYPE_CLASS_NUMBER;
if ((inputHints & ImhFormattedNumbersOnly) != 0) {
inputType |= (android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL
| android.text.InputType.TYPE_NUMBER_FLAG_SIGNED);
}
if ((inputHints & ImhHiddenText) != 0)
inputType |= android.text.InputType.TYPE_NUMBER_VARIATION_PASSWORD;
} else if ((inputHints & ImhDialableCharactersOnly) != 0) {
inputType = android.text.InputType.TYPE_CLASS_PHONE;
} else if ((inputHints & (ImhDate | ImhTime)) != 0) {
inputType = android.text.InputType.TYPE_CLASS_DATETIME;
if ((inputHints & (ImhDate | ImhTime)) != (ImhDate | ImhTime)) {
if ((inputHints & ImhDate) != 0)
inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_DATE;
else
inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_TIME;
} // else { TYPE_DATETIME_VARIATION_NORMAL(0) }
} else { // CLASS_TEXT
if ((inputHints & ImhHiddenText) != 0) {
inputType |= android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
} else if ((inputHints & ImhSensitiveData) != 0 ||
isDisablePredictiveTextWorkaround(inputHints)) {
inputType |= android.text.InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
} else if ((inputHints & ImhUrlCharactersOnly) != 0) {
inputType |= android.text.InputType.TYPE_TEXT_VARIATION_URI;
if (enterKeyType == 0) // not explicitly overridden
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
} else if ((inputHints & ImhEmailCharactersOnly) != 0) {
inputType |= android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
}
if ((inputHints & ImhMultiLine) != 0) {
inputType |= android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE;
// Clear imeOptions for Multi-Line Type
// User should be able to insert new line in such case
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
}
if ((inputHints & (ImhNoPredictiveText | ImhSensitiveData | ImhHiddenText)) != 0)
inputType |= android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
if ((inputHints & ImhUppercaseOnly) != 0) {
initialCapsMode |= android.text.TextUtils.CAP_MODE_CHARACTERS;
inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
} else if ((inputHints & ImhLowercaseOnly) == 0
&& (inputHints & ImhNoAutoUppercase) == 0) {
initialCapsMode |= android.text.TextUtils.CAP_MODE_SENTENCES;
inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
}
}
if (enterKeyType == 0 && (inputHints & ImhMultiLine) != 0)
imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
setInitialCapsMode(initialCapsMode);
setImeOptions(imeOptions);
setInputType(inputType);
}
private int imeOptionsFromEnterKeyType(int enterKeyType)
{
int imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
// enter key type - must be kept in sync with QTDIR/src/corelib/global/qnamespace.h
switch (enterKeyType) {
case 0: // EnterKeyDefault
break;
case 1: // EnterKeyReturn
imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
break;
case 2: // EnterKeyDone
break;
case 3: // EnterKeyGo
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
break;
case 4: // EnterKeySend
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEND;
break;
case 5: // EnterKeySearch
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEARCH;
break;
case 6: // EnterKeyNext
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
break;
case 7: // EnterKeyPrevious
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS;
break;
}
return imeOptions;
}
private boolean isDisablePredictiveTextWorkaround(int inputHints)
{
return (inputHints & ImhNoPredictiveText) != 0 &&
System.getenv("QT_ANDROID_ENABLE_WORKAROUND_TO_DISABLE_PREDICTIVE_TEXT") != null;
}
}

View File

@ -53,31 +53,6 @@ class QtInputDelegate {
private CursorHandle m_rightSelectionHandle;
private EditPopupMenu m_editPopupMenu;
// input method hints - must be kept in sync with QTDIR/src/corelib/global/qnamespace.h
private final int ImhHiddenText = 0x1;
private final int ImhSensitiveData = 0x2;
private final int ImhNoAutoUppercase = 0x4;
private final int ImhPreferNumbers = 0x8;
private final int ImhPreferUppercase = 0x10;
private final int ImhPreferLowercase = 0x20;
private final int ImhNoPredictiveText = 0x40;
private final int ImhDate = 0x80;
private final int ImhTime = 0x100;
private final int ImhPreferLatin = 0x200;
private final int ImhMultiLine = 0x400;
private final int ImhDigitsOnly = 0x10000;
private final int ImhFormattedNumbersOnly = 0x20000;
private final int ImhUppercaseOnly = 0x40000;
private final int ImhLowercaseOnly = 0x80000;
private final int ImhDialableCharactersOnly = 0x100000;
private final int ImhEmailCharactersOnly = 0x200000;
private final int ImhUrlCharactersOnly = 0x400000;
private final int ImhLatinOnly = 0x800000;
private int m_softInputMode = 0;
// Values coming from QAndroidInputContext::CursorHandleShowMode
@ -213,7 +188,7 @@ class QtInputDelegate {
if (updateSoftInputMode(activity, height))
return;
setEditTextOptions(enterKeyType, inputHints);
m_currentEditText.setEditTextOptions(enterKeyType, inputHints);
m_currentEditText.postDelayed(() -> {
m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) {
@ -245,78 +220,6 @@ class QtInputDelegate {
});
}
private void setEditTextOptions(int enterKeyType, int inputHints)
{
int initialCapsMode = 0;
int imeOptions = imeOptionsFromEnterKeyType(enterKeyType);
int inputType = android.text.InputType.TYPE_CLASS_TEXT;
if ((inputHints & (ImhPreferNumbers | ImhDigitsOnly | ImhFormattedNumbersOnly)) != 0) {
inputType = android.text.InputType.TYPE_CLASS_NUMBER;
if ((inputHints & ImhFormattedNumbersOnly) != 0) {
inputType |= (android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL
| android.text.InputType.TYPE_NUMBER_FLAG_SIGNED);
}
if ((inputHints & ImhHiddenText) != 0)
inputType |= android.text.InputType.TYPE_NUMBER_VARIATION_PASSWORD;
} else if ((inputHints & ImhDialableCharactersOnly) != 0) {
inputType = android.text.InputType.TYPE_CLASS_PHONE;
} else if ((inputHints & (ImhDate | ImhTime)) != 0) {
inputType = android.text.InputType.TYPE_CLASS_DATETIME;
if ((inputHints & (ImhDate | ImhTime)) != (ImhDate | ImhTime)) {
if ((inputHints & ImhDate) != 0)
inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_DATE;
else
inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_TIME;
} // else { TYPE_DATETIME_VARIATION_NORMAL(0) }
} else { // CLASS_TEXT
if ((inputHints & ImhHiddenText) != 0) {
inputType |= android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
} else if ((inputHints & ImhSensitiveData) != 0 ||
isDisablePredictiveTextWorkaround(inputHints)) {
inputType |= android.text.InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
} else if ((inputHints & ImhUrlCharactersOnly) != 0) {
inputType |= android.text.InputType.TYPE_TEXT_VARIATION_URI;
if (enterKeyType == 0) // not explicitly overridden
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
} else if ((inputHints & ImhEmailCharactersOnly) != 0) {
inputType |= android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
}
if ((inputHints & ImhMultiLine) != 0) {
inputType |= android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE;
// Clear imeOptions for Multi-Line Type
// User should be able to insert new line in such case
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
}
if ((inputHints & (ImhNoPredictiveText | ImhSensitiveData | ImhHiddenText)) != 0)
inputType |= android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
if ((inputHints & ImhUppercaseOnly) != 0) {
initialCapsMode |= android.text.TextUtils.CAP_MODE_CHARACTERS;
inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
} else if ((inputHints & ImhLowercaseOnly) == 0
&& (inputHints & ImhNoAutoUppercase) == 0) {
initialCapsMode |= android.text.TextUtils.CAP_MODE_SENTENCES;
inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
}
}
if (enterKeyType == 0 && (inputHints & ImhMultiLine) != 0)
imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
m_currentEditText.setInitialCapsMode(initialCapsMode);
m_currentEditText.setImeOptions(imeOptions);
m_currentEditText.setInputType(inputType);
}
private boolean isDisablePredictiveTextWorkaround(int inputHints)
{
return (inputHints & ImhNoPredictiveText) != 0 &&
System.getenv("QT_ANDROID_ENABLE_WORKAROUND_TO_DISABLE_PREDICTIVE_TEXT") != null;
}
private boolean updateSoftInputMode(Activity activity, int height)
{
DisplayMetrics metrics = new DisplayMetrics();
@ -351,38 +254,6 @@ class QtInputDelegate {
return false;
}
private int imeOptionsFromEnterKeyType(int enterKeyType)
{
int imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
// enter key type - must be kept in sync with QTDIR/src/corelib/global/qnamespace.h
switch (enterKeyType) {
case 0: // EnterKeyDefault
break;
case 1: // EnterKeyReturn
imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
break;
case 2: // EnterKeyDone
break;
case 3: // EnterKeyGo
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
break;
case 4: // EnterKeySend
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEND;
break;
case 5: // EnterKeySearch
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEARCH;
break;
case 6: // EnterKeyNext
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
break;
case 7: // EnterKeyPrevious
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS;
break;
}
return imeOptions;
}
private void probeForKeyboardHeight(QtLayout layout, Activity activity, int x, int y,
int width, int height, int inputHints, int enterKeyType)
{