From 6012edec287cf081a1aacafd55aac1adfbd90b19 Mon Sep 17 00:00:00 2001 From: George Mount Date: Tue, 28 Feb 2012 15:19:33 -0800 Subject: Add support for maxlength text fields to WebViewInputConnection. Bug 6083776 While WebKit limits the length of a field with maxlength, the InputConnection can get out of sync with it when it doesn't recognize that the characters haven't been changed. Adds maximum field length to WebViewInputConnection to limit the characters typed. WebKit Change: Ie02f82a3f5b3527c378938d93bac2dece802af26 Change-Id: I135871db7809e8dc28a3ad8d3aa852976a274555 --- core/java/android/webkit/WebView.java | 56 +++++++++++++++++++++++-------- core/java/android/webkit/WebViewCore.java | 9 +++-- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index e7ab826f2757..b69bf53d39ad 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -378,6 +378,7 @@ public class WebView extends AbsoluteLayout private int mInputType; private int mImeOptions; private String mHint; + private int mMaxLength; public WebViewInputConnection() { super(WebView.this, true); @@ -412,13 +413,9 @@ public class WebView extends AbsoluteLayout Editable editable = getEditable(); int selectionStart = Selection.getSelectionStart(editable); int selectionEnd = Selection.getSelectionEnd(editable); + text = limitReplaceTextByMaxLength(text, editable.length()); editable.replace(0, editable.length(), text); - InputMethodManager imm = InputMethodManager.peekInstance(); - if (imm != null) { - // Since the text has changed, do not allow the IME to replace the - // existing text as though it were a completion. - imm.restartInput(WebView.this); - } + restartInput(); // Keep the previous selection. selectionStart = Math.min(selectionStart, editable.length()); selectionEnd = Math.min(selectionEnd, editable.length()); @@ -429,14 +426,10 @@ public class WebView extends AbsoluteLayout Editable editable = getEditable(); int selectionStart = Selection.getSelectionStart(editable); int selectionEnd = Selection.getSelectionEnd(editable); + text = limitReplaceTextByMaxLength(text, selectionEnd - selectionStart); setNewText(selectionStart, selectionEnd, text); editable.replace(selectionStart, selectionEnd, text); - InputMethodManager imm = InputMethodManager.peekInstance(); - if (imm != null) { - // Since the text has changed, do not allow the IME to replace the - // existing text as though it were a completion. - imm.restartInput(WebView.this); - } + restartInput(); // Move caret to the end of the new text int newCaret = selectionStart + text.length(); setSelection(newCaret, newCaret); @@ -456,8 +449,19 @@ public class WebView extends AbsoluteLayout end = start; start = temp; } - setNewText(start, end, text); - return super.setComposingText(text, newCursorPosition); + CharSequence limitedText = limitReplaceTextByMaxLength(text, end - start); + setNewText(start, end, limitedText); + if (limitedText != text) { + newCursorPosition -= text.length() - limitedText.length(); + } + super.setComposingText(limitedText, newCursorPosition); + if (limitedText != text) { + restartInput(); + int lastCaret = start + limitedText.length(); + finishComposingText(); + setSelection(lastCaret, lastCaret); + } + return true; } @Override @@ -541,6 +545,7 @@ public class WebView extends AbsoluteLayout mHint = initData.mLabel; mInputType = inputType; mImeOptions = imeOptions; + mMaxLength = initData.mMaxLength; } public void setupEditorInfo(EditorInfo outAttrs) { @@ -626,6 +631,29 @@ public class WebView extends AbsoluteLayout KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD)); } + + private CharSequence limitReplaceTextByMaxLength(CharSequence text, + int numReplaced) { + if (mMaxLength > 0) { + Editable editable = getEditable(); + int maxReplace = mMaxLength - editable.length() + numReplaced; + if (maxReplace < text.length()) { + maxReplace = Math.max(maxReplace, 0); + // New length is greater than the maximum. trim it down. + text = text.subSequence(0, maxReplace); + } + } + return text; + } + + private void restartInput() { + InputMethodManager imm = InputMethodManager.peekInstance(); + if (imm != null) { + // Since the text has changed, do not allow the IME to replace the + // existing text as though it were a completion. + imm.restartInput(WebView.this); + } + } } private class PastePopupWindow extends PopupWindow implements OnClickListener { diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index e7da1a8c40e7..93fd92ba240c 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -923,13 +923,14 @@ public final class WebViewCore { static class TextFieldInitData { public TextFieldInitData(int fieldPointer, String text, int type, boolean isSpellCheckEnabled, - boolean isTextFieldNext, String label) { + boolean isTextFieldNext, String label, int maxLength) { mFieldPointer = fieldPointer; mText = text; mType = type; mIsSpellCheckEnabled = isSpellCheckEnabled; mIsTextFieldNext = isTextFieldNext; mLabel = label; + mMaxLength = maxLength; } int mFieldPointer; String mText; @@ -937,6 +938,7 @@ public final class WebViewCore { boolean mIsSpellCheckEnabled; boolean mIsTextFieldNext; String mLabel; + int mMaxLength; } // mAction of TouchEventData can be MotionEvent.getAction() which uses the @@ -2826,12 +2828,13 @@ public final class WebViewCore { // called by JNI private void initEditField(int pointer, String text, int inputType, boolean isSpellCheckEnabled, boolean nextFieldIsText, - String label, int start, int end, int selectionPtr) { + String label, int start, int end, int selectionPtr, int maxLength) { if (mWebView == null) { return; } TextFieldInitData initData = new TextFieldInitData(pointer, - text, inputType, isSpellCheckEnabled, nextFieldIsText, label); + text, inputType, isSpellCheckEnabled, nextFieldIsText, label, + maxLength); Message.obtain(mWebView.mPrivateHandler, WebView.INIT_EDIT_FIELD, initData).sendToTarget(); Message.obtain(mWebView.mPrivateHandler, -- cgit v1.2.3-59-g8ed1b