OSDN Git Service

Add support for maxlength text fields to WebViewInputConnection.
authorGeorge Mount <mount@google.com>
Tue, 28 Feb 2012 23:19:33 +0000 (15:19 -0800)
committerGeorge Mount <mount@google.com>
Tue, 28 Feb 2012 23:27:26 +0000 (15:27 -0800)
 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
core/java/android/webkit/WebViewCore.java

index e7ab826..b69bf53 100644 (file)
@@ -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 {
index e7da1a8..93fd92b 100644 (file)
@@ -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,