| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.content.browser.input; | 5 package org.chromium.content.browser.input; |
| 6 | 6 |
| 7 import android.os.Handler; | 7 import android.os.Handler; |
| 8 import android.os.ResultReceiver; | 8 import android.os.ResultReceiver; |
| 9 import android.os.SystemClock; | 9 import android.os.SystemClock; |
| 10 import android.text.Editable; | 10 import android.text.Editable; |
| 11 import android.text.SpannableString; | 11 import android.text.SpannableString; |
| 12 import android.text.style.BackgroundColorSpan; | 12 import android.text.style.BackgroundColorSpan; |
| 13 import android.text.style.CharacterStyle; | 13 import android.text.style.CharacterStyle; |
| 14 import android.text.style.UnderlineSpan; | 14 import android.text.style.UnderlineSpan; |
| 15 import android.view.KeyCharacterMap; | 15 import android.view.KeyCharacterMap; |
| 16 import android.view.KeyEvent; | 16 import android.view.KeyEvent; |
| 17 import android.view.View; | 17 import android.view.View; |
| 18 import android.view.inputmethod.EditorInfo; | 18 import android.view.inputmethod.EditorInfo; |
| 19 | 19 |
| 20 import org.chromium.base.CalledByNative; | 20 import org.chromium.base.CalledByNative; |
| 21 import org.chromium.base.JNINamespace; | 21 import org.chromium.base.JNINamespace; |
| 22 import org.chromium.base.VisibleForTesting; | 22 import org.chromium.base.VisibleForTesting; |
| 23 import org.chromium.blink_public.web.WebInputEventModifier; |
| 24 import org.chromium.blink_public.web.WebInputEventType; |
| 25 import org.chromium.blink_public.web.WebTextInputFlags; |
| 23 import org.chromium.ui.base.ime.TextInputType; | 26 import org.chromium.ui.base.ime.TextInputType; |
| 24 import org.chromium.ui.picker.InputDialogContainer; | 27 import org.chromium.ui.picker.InputDialogContainer; |
| 25 | 28 |
| 26 import java.lang.CharSequence; | 29 import java.lang.CharSequence; |
| 27 | 30 |
| 28 /** | 31 /** |
| 29 * Adapts and plumbs android IME service onto the chrome text input API. | 32 * Adapts and plumbs android IME service onto the chrome text input API. |
| 30 * ImeAdapter provides an interface in both ways native <-> java: | 33 * ImeAdapter provides an interface in both ways native <-> java: |
| 31 * 1. InputConnectionAdapter notifies native code of text composition state and | 34 * 1. InputConnectionAdapter notifies native code of text composition state and |
| 32 * dispatch key events from java -> WebKit. | 35 * dispatch key events from java -> WebKit. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 } | 85 } |
| 83 | 86 |
| 84 // http://crbug.com/413744 | 87 // http://crbug.com/413744 |
| 85 void detach() { | 88 void detach() { |
| 86 mNativeImeAdapter = 0; | 89 mNativeImeAdapter = 0; |
| 87 } | 90 } |
| 88 | 91 |
| 89 @Override | 92 @Override |
| 90 public void run() { | 93 public void run() { |
| 91 if (mNativeImeAdapter != 0) { | 94 if (mNativeImeAdapter != 0) { |
| 92 attach(mNativeImeAdapter, TextInputType.NONE, sTextInputFlagNone
); | 95 attach(mNativeImeAdapter, TextInputType.NONE, WebTextInputFlags.
None); |
| 93 } | 96 } |
| 94 dismissInput(true); | 97 dismissInput(true); |
| 95 } | 98 } |
| 96 } | 99 } |
| 97 | 100 |
| 98 private static final int COMPOSITION_KEY_CODE = 229; | 101 private static final int COMPOSITION_KEY_CODE = 229; |
| 99 | 102 |
| 100 // Delay introduced to avoid hiding the keyboard if new show requests are re
ceived. | 103 // Delay introduced to avoid hiding the keyboard if new show requests are re
ceived. |
| 101 // The time required by the unfocus-focus events triggered by tab has been m
easured in soju: | 104 // The time required by the unfocus-focus events triggered by tab has been m
easured in soju: |
| 102 // Mean: 18.633 ms, Standard deviation: 7.9837 ms. | 105 // Mean: 18.633 ms, Standard deviation: 7.9837 ms. |
| 103 // The value here should be higher enough to cover these cases, but not too
high to avoid | 106 // The value here should be higher enough to cover these cases, but not too
high to avoid |
| 104 // letting the user perceiving important delays. | 107 // letting the user perceiving important delays. |
| 105 private static final int INPUT_DISMISS_DELAY = 150; | 108 private static final int INPUT_DISMISS_DELAY = 150; |
| 106 | 109 |
| 107 // All the constants that are retrieved from the C++ code. | |
| 108 // They get set through initializeWebInputEvents and initializeTextInputType
s calls. | |
| 109 static int sEventTypeRawKeyDown; | |
| 110 static int sEventTypeKeyUp; | |
| 111 static int sEventTypeChar; | |
| 112 static int sTextInputFlagNone = 0; | |
| 113 static int sTextInputFlagAutocompleteOn; | |
| 114 static int sTextInputFlagAutocompleteOff; | |
| 115 static int sTextInputFlagAutocorrectOn; | |
| 116 static int sTextInputFlagAutocorrectOff; | |
| 117 static int sTextInputFlagSpellcheckOn; | |
| 118 static int sTextInputFlagSpellcheckOff; | |
| 119 static int sModifierShift; | |
| 120 static int sModifierAlt; | |
| 121 static int sModifierCtrl; | |
| 122 static int sModifierCapsLockOn; | |
| 123 static int sModifierNumLockOn; | |
| 124 static char[] sSingleCharArray = new char[1]; | 110 static char[] sSingleCharArray = new char[1]; |
| 125 static KeyCharacterMap sKeyCharacterMap; | 111 static KeyCharacterMap sKeyCharacterMap; |
| 126 | 112 |
| 127 private long mNativeImeAdapterAndroid; | 113 private long mNativeImeAdapterAndroid; |
| 128 private InputMethodManagerWrapper mInputMethodManagerWrapper; | 114 private InputMethodManagerWrapper mInputMethodManagerWrapper; |
| 129 private AdapterInputConnection mInputConnection; | 115 private AdapterInputConnection mInputConnection; |
| 130 private final ImeAdapterDelegate mViewEmbedder; | 116 private final ImeAdapterDelegate mViewEmbedder; |
| 131 private final Handler mHandler; | 117 private final Handler mHandler; |
| 132 private DelayedDismissInput mDismissInput = null; | 118 private DelayedDismissInput mDismissInput = null; |
| 133 private int mTextInputType; | 119 private int mTextInputType; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 * Should be used only by AdapterInputConnection. | 187 * Should be used only by AdapterInputConnection. |
| 202 * @return The input flags of the currently focused element. | 188 * @return The input flags of the currently focused element. |
| 203 */ | 189 */ |
| 204 int getTextInputFlags() { | 190 int getTextInputFlags() { |
| 205 return mTextInputFlags; | 191 return mTextInputFlags; |
| 206 } | 192 } |
| 207 | 193 |
| 208 private static int getModifiers(int metaState) { | 194 private static int getModifiers(int metaState) { |
| 209 int modifiers = 0; | 195 int modifiers = 0; |
| 210 if ((metaState & KeyEvent.META_SHIFT_ON) != 0) { | 196 if ((metaState & KeyEvent.META_SHIFT_ON) != 0) { |
| 211 modifiers |= sModifierShift; | 197 modifiers |= WebInputEventModifier.ShiftKey; |
| 212 } | 198 } |
| 213 if ((metaState & KeyEvent.META_ALT_ON) != 0) { | 199 if ((metaState & KeyEvent.META_ALT_ON) != 0) { |
| 214 modifiers |= sModifierAlt; | 200 modifiers |= WebInputEventModifier.AltKey; |
| 215 } | 201 } |
| 216 if ((metaState & KeyEvent.META_CTRL_ON) != 0) { | 202 if ((metaState & KeyEvent.META_CTRL_ON) != 0) { |
| 217 modifiers |= sModifierCtrl; | 203 modifiers |= WebInputEventModifier.ControlKey; |
| 218 } | 204 } |
| 219 if ((metaState & KeyEvent.META_CAPS_LOCK_ON) != 0) { | 205 if ((metaState & KeyEvent.META_CAPS_LOCK_ON) != 0) { |
| 220 modifiers |= sModifierCapsLockOn; | 206 modifiers |= WebInputEventModifier.CapsLockOn; |
| 221 } | 207 } |
| 222 if ((metaState & KeyEvent.META_NUM_LOCK_ON) != 0) { | 208 if ((metaState & KeyEvent.META_NUM_LOCK_ON) != 0) { |
| 223 modifiers |= sModifierNumLockOn; | 209 modifiers |= WebInputEventModifier.NumLockOn; |
| 224 } | 210 } |
| 225 return modifiers; | 211 return modifiers; |
| 226 } | 212 } |
| 227 | 213 |
| 228 /** | 214 /** |
| 229 * Shows or hides the keyboard based on passed parameters. | 215 * Shows or hides the keyboard based on passed parameters. |
| 230 * @param nativeImeAdapter Pointer to the ImeAdapterAndroid object that is s
ending the update. | 216 * @param nativeImeAdapter Pointer to the ImeAdapterAndroid object that is s
ending the update. |
| 231 * @param textInputType Text input type for the currently focused field in r
enderer. | 217 * @param textInputType Text input type for the currently focused field in r
enderer. |
| 232 * @param showIfNeeded Whether the keyboard should be shown if it is current
ly hidden. | 218 * @param showIfNeeded Whether the keyboard should be shown if it is current
ly hidden. |
| 233 */ | 219 */ |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 dismissInput(false); | 262 dismissInput(false); |
| 277 } | 263 } |
| 278 } | 264 } |
| 279 | 265 |
| 280 /** | 266 /** |
| 281 * Attaches the imeAdapter to its native counterpart. This is needed to star
t forwarding | 267 * Attaches the imeAdapter to its native counterpart. This is needed to star
t forwarding |
| 282 * keyboard events to WebKit. | 268 * keyboard events to WebKit. |
| 283 * @param nativeImeAdapter The pointer to the native ImeAdapter object. | 269 * @param nativeImeAdapter The pointer to the native ImeAdapter object. |
| 284 */ | 270 */ |
| 285 public void attach(long nativeImeAdapter) { | 271 public void attach(long nativeImeAdapter) { |
| 286 attach(nativeImeAdapter, TextInputType.NONE, sTextInputFlagNone); | 272 attach(nativeImeAdapter, TextInputType.NONE, WebTextInputFlags.None); |
| 287 } | 273 } |
| 288 | 274 |
| 289 private void showKeyboard() { | 275 private void showKeyboard() { |
| 290 mIsShowWithoutHideOutstanding = true; | 276 mIsShowWithoutHideOutstanding = true; |
| 291 mInputMethodManagerWrapper.showSoftInput(mViewEmbedder.getAttachedView()
, 0, | 277 mInputMethodManagerWrapper.showSoftInput(mViewEmbedder.getAttachedView()
, 0, |
| 292 mViewEmbedder.getNewShowKeyboardReceiver()); | 278 mViewEmbedder.getNewShowKeyboardReceiver()); |
| 293 } | 279 } |
| 294 | 280 |
| 295 private void dismissInput(boolean unzoomIfNeeded) { | 281 private void dismissInput(boolean unzoomIfNeeded) { |
| 296 mIsShowWithoutHideOutstanding = false; | 282 mIsShowWithoutHideOutstanding = false; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 // | 438 // |
| 453 // An alternative is to *not* call nativeSetComposingText() in the n
on-commit case | 439 // An alternative is to *not* call nativeSetComposingText() in the n
on-commit case |
| 454 // below. This avoids the restart of composition described above bu
t fails to send | 440 // below. This avoids the restart of composition described above bu
t fails to send |
| 455 // an update to the composition while in composition which, strictly
speaking, | 441 // an update to the composition while in composition which, strictly
speaking, |
| 456 // does not match the spec. | 442 // does not match the spec. |
| 457 // | 443 // |
| 458 // For now, the solution is to endure the restarting of composition
and only dive | 444 // For now, the solution is to endure the restarting of composition
and only dive |
| 459 // into the alternate solution should there be problems in the field
. --bcwhite | 445 // into the alternate solution should there be problems in the field
. --bcwhite |
| 460 | 446 |
| 461 if (keyCode >= 0) { | 447 if (keyCode >= 0) { |
| 462 nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventType
RawKeyDown, | 448 nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, WebInputEv
entType.RawKeyDown, |
| 463 timeStampMs, keyCode, modifiers, 0); | 449 timeStampMs, keyCode, modifiers, 0); |
| 464 } | 450 } |
| 465 | 451 |
| 466 if (isCommit) { | 452 if (isCommit) { |
| 467 nativeCommitText(mNativeImeAdapterAndroid, textStr); | 453 nativeCommitText(mNativeImeAdapterAndroid, textStr); |
| 468 textStr = null; | 454 textStr = null; |
| 469 } else { | 455 } else { |
| 470 nativeSetComposingText(mNativeImeAdapterAndroid, text, textStr,
newCursorPosition); | 456 nativeSetComposingText(mNativeImeAdapterAndroid, text, textStr,
newCursorPosition); |
| 471 } | 457 } |
| 472 | 458 |
| 473 if (keyCode >= 0) { | 459 if (keyCode >= 0) { |
| 474 nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventType
KeyUp, | 460 nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, WebInputEv
entType.KeyUp, |
| 475 timeStampMs, keyCode, modifiers, 0); | 461 timeStampMs, keyCode, modifiers, 0); |
| 476 } | 462 } |
| 477 | 463 |
| 478 mLastSyntheticKeyCode = keyCode; | 464 mLastSyntheticKeyCode = keyCode; |
| 479 } | 465 } |
| 480 | 466 |
| 481 mLastComposeText = textStr; | 467 mLastComposeText = textStr; |
| 482 return true; | 468 return true; |
| 483 } | 469 } |
| 484 | 470 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 */ | 594 */ |
| 609 public boolean paste() { | 595 public boolean paste() { |
| 610 if (mNativeImeAdapterAndroid == 0) return false; | 596 if (mNativeImeAdapterAndroid == 0) return false; |
| 611 nativePaste(mNativeImeAdapterAndroid); | 597 nativePaste(mNativeImeAdapterAndroid); |
| 612 return true; | 598 return true; |
| 613 } | 599 } |
| 614 | 600 |
| 615 // Calls from C++ to Java | 601 // Calls from C++ to Java |
| 616 | 602 |
| 617 @CalledByNative | 603 @CalledByNative |
| 618 private static void initializeWebInputEvents(int eventTypeRawKeyDown, int ev
entTypeKeyUp, | |
| 619 int eventTypeChar, int modifierShift, int modifierAlt, int modifierC
trl, | |
| 620 int modifierCapsLockOn, int modifierNumLockOn) { | |
| 621 sEventTypeRawKeyDown = eventTypeRawKeyDown; | |
| 622 sEventTypeKeyUp = eventTypeKeyUp; | |
| 623 sEventTypeChar = eventTypeChar; | |
| 624 sModifierShift = modifierShift; | |
| 625 sModifierAlt = modifierAlt; | |
| 626 sModifierCtrl = modifierCtrl; | |
| 627 sModifierCapsLockOn = modifierCapsLockOn; | |
| 628 sModifierNumLockOn = modifierNumLockOn; | |
| 629 } | |
| 630 | |
| 631 @CalledByNative | |
| 632 private static void initializeTextInputFlags( | |
| 633 int textInputFlagAutocompleteOn, int textInputFlagAutocompleteOff, | |
| 634 int textInputFlagAutocorrectOn, int textInputFlagAutocorrectOff, | |
| 635 int textInputFlagSpellcheckOn, int textInputFlagSpellcheckOff) { | |
| 636 sTextInputFlagAutocompleteOn = textInputFlagAutocompleteOn; | |
| 637 sTextInputFlagAutocompleteOff = textInputFlagAutocompleteOff; | |
| 638 sTextInputFlagAutocorrectOn = textInputFlagAutocorrectOn; | |
| 639 sTextInputFlagAutocorrectOff = textInputFlagAutocorrectOff; | |
| 640 sTextInputFlagSpellcheckOn = textInputFlagSpellcheckOn; | |
| 641 sTextInputFlagSpellcheckOff = textInputFlagSpellcheckOff; | |
| 642 } | |
| 643 | |
| 644 @CalledByNative | |
| 645 private void focusedNodeChanged(boolean isEditable) { | 604 private void focusedNodeChanged(boolean isEditable) { |
| 646 if (mInputConnection != null && isEditable) mInputConnection.restartInpu
t(); | 605 if (mInputConnection != null && isEditable) mInputConnection.restartInpu
t(); |
| 647 } | 606 } |
| 648 | 607 |
| 649 @CalledByNative | 608 @CalledByNative |
| 650 private void populateUnderlinesFromSpans(CharSequence text, long underlines)
{ | 609 private void populateUnderlinesFromSpans(CharSequence text, long underlines)
{ |
| 651 if (!(text instanceof SpannableString)) return; | 610 if (!(text instanceof SpannableString)) return; |
| 652 | 611 |
| 653 SpannableString spannableString = ((SpannableString) text); | 612 SpannableString spannableString = ((SpannableString) text); |
| 654 CharacterStyle spans[] = | 613 CharacterStyle spans[] = |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 710 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid
, | 669 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid
, |
| 711 int before, int after); | 670 int before, int after); |
| 712 | 671 |
| 713 private native void nativeUnselect(long nativeImeAdapterAndroid); | 672 private native void nativeUnselect(long nativeImeAdapterAndroid); |
| 714 private native void nativeSelectAll(long nativeImeAdapterAndroid); | 673 private native void nativeSelectAll(long nativeImeAdapterAndroid); |
| 715 private native void nativeCut(long nativeImeAdapterAndroid); | 674 private native void nativeCut(long nativeImeAdapterAndroid); |
| 716 private native void nativeCopy(long nativeImeAdapterAndroid); | 675 private native void nativeCopy(long nativeImeAdapterAndroid); |
| 717 private native void nativePaste(long nativeImeAdapterAndroid); | 676 private native void nativePaste(long nativeImeAdapterAndroid); |
| 718 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); | 677 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); |
| 719 } | 678 } |
| OLD | NEW |