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 |