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.graphics.Matrix; |
| 8 import android.os.Build; |
7 import android.os.Handler; | 9 import android.os.Handler; |
8 import android.os.ResultReceiver; | 10 import android.os.ResultReceiver; |
9 import android.os.SystemClock; | 11 import android.os.SystemClock; |
10 import android.text.Editable; | 12 import android.text.Editable; |
11 import android.text.SpannableString; | 13 import android.text.SpannableString; |
12 import android.text.style.BackgroundColorSpan; | 14 import android.text.style.BackgroundColorSpan; |
13 import android.text.style.CharacterStyle; | 15 import android.text.style.CharacterStyle; |
14 import android.text.style.UnderlineSpan; | 16 import android.text.style.UnderlineSpan; |
15 import android.view.KeyCharacterMap; | 17 import android.view.KeyCharacterMap; |
16 import android.view.KeyEvent; | 18 import android.view.KeyEvent; |
17 import android.view.View; | 19 import android.view.View; |
| 20 import android.view.inputmethod.CursorAnchorInfo; |
18 import android.view.inputmethod.EditorInfo; | 21 import android.view.inputmethod.EditorInfo; |
| 22 import android.view.inputmethod.InputConnection; |
| 23 import android.view.inputmethod.InputMethodManager; |
19 | 24 |
20 import org.chromium.base.CalledByNative; | 25 import org.chromium.base.CalledByNative; |
21 import org.chromium.base.JNINamespace; | 26 import org.chromium.base.JNINamespace; |
22 import org.chromium.base.VisibleForTesting; | 27 import org.chromium.base.VisibleForTesting; |
23 import org.chromium.ui.picker.InputDialogContainer; | 28 import org.chromium.ui.picker.InputDialogContainer; |
24 | 29 |
25 import java.lang.CharSequence; | 30 import java.lang.CharSequence; |
26 | 31 |
27 /** | 32 /** |
28 * Adapts and plumbs android IME service onto the chrome text input API. | 33 * Adapts and plumbs android IME service onto the chrome text input API. |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 private long mNativeImeAdapterAndroid; | 141 private long mNativeImeAdapterAndroid; |
137 private InputMethodManagerWrapper mInputMethodManagerWrapper; | 142 private InputMethodManagerWrapper mInputMethodManagerWrapper; |
138 private AdapterInputConnection mInputConnection; | 143 private AdapterInputConnection mInputConnection; |
139 private final ImeAdapterDelegate mViewEmbedder; | 144 private final ImeAdapterDelegate mViewEmbedder; |
140 private final Handler mHandler; | 145 private final Handler mHandler; |
141 private DelayedDismissInput mDismissInput = null; | 146 private DelayedDismissInput mDismissInput = null; |
142 private int mTextInputType; | 147 private int mTextInputType; |
143 private int mTextInputFlags; | 148 private int mTextInputFlags; |
144 private String mLastComposeText; | 149 private String mLastComposeText; |
145 | 150 |
| 151 private static class CursorAnchorInfoSource { |
| 152 private String mText; |
| 153 private int mSelectionStart; |
| 154 private int mSelectionEnd; |
| 155 private int mCompositionStart; |
| 156 private int mCompositionEnd; |
| 157 private float[] mLastCharacterBounds; |
| 158 } |
| 159 private CursorAnchorInfoSource mCursorAnchorInfoSource = new CursorAnchorInf
oSource(); |
| 160 |
| 161 private static class CursorAnchorInfoBuilderWrapper { |
| 162 |
| 163 public static boolean isSupported() { |
| 164 return false; |
| 165 } |
| 166 |
| 167 public static CursorAnchorInfoBuilderWrapper create() { |
| 168 return new CursorAnchorInfoBuilderWrapper(); |
| 169 } |
| 170 |
| 171 protected CursorAnchorInfoBuilderWrapper() { |
| 172 } |
| 173 |
| 174 public void update(CursorAnchorInfoSource source, Matrix matrix, boolean
hasInertionMarker, |
| 175 float insertionMarkerX, float insertionMarkerTop, float insertio
nMarkerBottom) { |
| 176 // This is a stub for platforms that do not support CursorAnchorInfo
. |
| 177 } |
| 178 |
| 179 public boolean hasData() { |
| 180 // This is a stub for platforms that do not support CursorAnchorInfo
. |
| 181 return false; |
| 182 } |
| 183 |
| 184 public void reset() { |
| 185 // This is a stub for platforms that do not support CursorAnchorInfo
. |
| 186 } |
| 187 |
| 188 public void send(InputMethodManagerWrapper inputMethodManagerWrapper, Vi
ew view) { |
| 189 // This is a stub for platforms that do not support CursorAnchorInfo
. |
| 190 } |
| 191 } |
| 192 |
| 193 private CursorAnchorInfoBuilderWrapper mCursorAnchorInfoBuilder = |
| 194 CursorAnchorInfoBuilderWrapper.create(); |
| 195 private boolean mCursorAnchorInfoMonitorEnabled = false; |
| 196 private boolean mOneshotUpdateCursorAnchorInfoEnabled = false; |
| 197 |
146 @VisibleForTesting | 198 @VisibleForTesting |
147 int mLastSyntheticKeyCode; | 199 int mLastSyntheticKeyCode; |
148 | 200 |
149 @VisibleForTesting | 201 @VisibleForTesting |
150 boolean mIsShowWithoutHideOutstanding = false; | 202 boolean mIsShowWithoutHideOutstanding = false; |
151 | 203 |
152 /** | 204 /** |
153 * @param wrapper InputMethodManagerWrapper that should receive all the call
directed to | 205 * @param wrapper InputMethodManagerWrapper that should receive all the call
directed to |
154 * InputMethodManager. | 206 * InputMethodManager. |
155 * @param embedder The view that is used for callbacks from ImeAdapter. | 207 * @param embedder The view that is used for callbacks from ImeAdapter. |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 /** | 666 /** |
615 * Send a request to the native counterpart of ImeAdapter to paste the text
from the clipboard. | 667 * Send a request to the native counterpart of ImeAdapter to paste the text
from the clipboard. |
616 * @return Whether the native counterpart of ImeAdapter received the call. | 668 * @return Whether the native counterpart of ImeAdapter received the call. |
617 */ | 669 */ |
618 public boolean paste() { | 670 public boolean paste() { |
619 if (mNativeImeAdapterAndroid == 0) return false; | 671 if (mNativeImeAdapterAndroid == 0) return false; |
620 nativePaste(mNativeImeAdapterAndroid); | 672 nativePaste(mNativeImeAdapterAndroid); |
621 return true; | 673 return true; |
622 } | 674 } |
623 | 675 |
| 676 /** |
| 677 * @return Whether the {@link CursorAnchorInfo} is available or not on this
device. |
| 678 */ |
| 679 public boolean isCursorAnchorInfoSupported() { |
| 680 return CursorAnchorInfoBuilderWrapper.isSupported(); |
| 681 } |
| 682 |
| 683 /** |
| 684 * Start or stop calling |
| 685 * {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)}
. |
| 686 * @param enabled {@code true} if {@link InputConnection#requestCursorUpdate
s(int)} is called |
| 687 * with {@link InputConnection#CURSOR_UPDATE_MONITOR} bit. |
| 688 */ |
| 689 public void setCursorAnchorInfoMonitorEnabled(boolean enabled) { |
| 690 mCursorAnchorInfoMonitorEnabled = enabled; |
| 691 } |
| 692 |
| 693 /** |
| 694 * Make sure {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAn
chorInfo)} is called |
| 695 * at least once immediately when the latest position becomes available. |
| 696 * @param view The view to be passed to |
| 697 * {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)}
if the latest |
| 698 * position is already available. Otherwise ignored. |
| 699 */ |
| 700 public void scheduleOneshotUpdateCursorAnchorInfo(View view) { |
| 701 if (!mCursorAnchorInfoBuilder.hasData()) { |
| 702 // If there is no data, send the data later when it becomes availabl
e. |
| 703 mOneshotUpdateCursorAnchorInfoEnabled = true; |
| 704 return; |
| 705 } |
| 706 mCursorAnchorInfoBuilder.send(mInputMethodManagerWrapper, view); |
| 707 mOneshotUpdateCursorAnchorInfoEnabled = false; |
| 708 } |
| 709 |
| 710 /** |
| 711 * Update the parameters that are to be passed to the IME through |
| 712 * {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)}
. |
| 713 * @param text The text in the focused text field. |
| 714 * @param selectionStart Index where the text selection starts. {@code -1} i
f there is no |
| 715 * selection. |
| 716 * @param selectionEnd Index where the text selection ends. {@code -1} if th
ere is no |
| 717 * selection. |
| 718 * @param compositionStart Index where the text composition starts. {@code -
1} if there is no |
| 719 * selection. |
| 720 * @param compositionEnd Index where the text composition ends. {@code -1} i
f there is no |
| 721 * selection. |
| 722 */ |
| 723 public void updateCursorAnchorInfoSource(String text, int selectionStart, in
t selectionEnd, |
| 724 int compositionStart, int compositionEnd) { |
| 725 mCursorAnchorInfoSource.mText = text; |
| 726 mCursorAnchorInfoSource.mSelectionStart = selectionStart; |
| 727 mCursorAnchorInfoSource.mSelectionEnd = selectionEnd; |
| 728 mCursorAnchorInfoSource.mCompositionStart = compositionStart; |
| 729 mCursorAnchorInfoSource.mCompositionEnd = compositionEnd; |
| 730 } |
| 731 |
| 732 /** |
| 733 * Call {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorI
nfo)} if it is |
| 734 * available and the active IME is actually requested it. |
| 735 * @param view The view to be passed to |
| 736 * {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)} |
| 737 * @param matrix The matrix from CSS coordinates to the absolute display coo
rdinates. |
| 738 * @param hasInsertionMaerker Whether the insertion marker exists or not. |
| 739 * @param insertionMarkerX The X position of the insertion marker, in CSS co
ordinates. |
| 740 * @param insertionMarkerTop The top position of the insertion marker, in CS
S coordinates. |
| 741 * @param insertionMarkerBottom The bottom position of the insertion marker,
in CSS coordinates. |
| 742 */ |
| 743 public void updateCursorAnchorInfo(View view, Matrix matrix, boolean hasInse
rtionMaerker, |
| 744 float insertionMarkerX, float insertionMarkerTop, float insertionMar
kerBottom) { |
| 745 mCursorAnchorInfoBuilder.update(mCursorAnchorInfoSource, matrix, hasInse
rtionMaerker, |
| 746 insertionMarkerX, insertionMarkerTop, insertionMarkerBottom); |
| 747 if (!mCursorAnchorInfoMonitorEnabled && !mOneshotUpdateCursorAnchorInfoE
nabled) return; |
| 748 mCursorAnchorInfoBuilder.send(mInputMethodManagerWrapper, view); |
| 749 mOneshotUpdateCursorAnchorInfoEnabled = false; |
| 750 } |
| 751 |
624 // Calls from C++ to Java | 752 // Calls from C++ to Java |
625 | 753 |
626 @CalledByNative | 754 @CalledByNative |
627 private static void initializeWebInputEvents(int eventTypeRawKeyDown, int ev
entTypeKeyUp, | 755 private static void initializeWebInputEvents(int eventTypeRawKeyDown, int ev
entTypeKeyUp, |
628 int eventTypeChar, int modifierShift, int modifierAlt, int modifierC
trl, | 756 int eventTypeChar, int modifierShift, int modifierAlt, int modifierC
trl, |
629 int modifierCapsLockOn, int modifierNumLockOn) { | 757 int modifierCapsLockOn, int modifierNumLockOn) { |
630 sEventTypeRawKeyDown = eventTypeRawKeyDown; | 758 sEventTypeRawKeyDown = eventTypeRawKeyDown; |
631 sEventTypeKeyUp = eventTypeKeyUp; | 759 sEventTypeKeyUp = eventTypeKeyUp; |
632 sEventTypeChar = eventTypeChar; | 760 sEventTypeChar = eventTypeChar; |
633 sModifierShift = modifierShift; | 761 sModifierShift = modifierShift; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 } | 820 } |
693 | 821 |
694 @CalledByNative | 822 @CalledByNative |
695 private void cancelComposition() { | 823 private void cancelComposition() { |
696 if (mInputConnection != null) mInputConnection.restartInput(); | 824 if (mInputConnection != null) mInputConnection.restartInput(); |
697 mLastComposeText = null; | 825 mLastComposeText = null; |
698 } | 826 } |
699 | 827 |
700 @CalledByNative | 828 @CalledByNative |
701 private void setCharacterBounds(float[] characterBounds) { | 829 private void setCharacterBounds(float[] characterBounds) { |
702 // TODO(yukawa): Implement this. | 830 mCursorAnchorInfoSource.mLastCharacterBounds = characterBounds; |
703 } | 831 } |
704 | 832 |
705 @CalledByNative | 833 @CalledByNative |
706 void detach() { | 834 void detach() { |
707 if (mDismissInput != null) { | 835 if (mDismissInput != null) { |
708 mHandler.removeCallbacks(mDismissInput); | 836 mHandler.removeCallbacks(mDismissInput); |
709 mDismissInput.detach(); | 837 mDismissInput.detach(); |
710 } | 838 } |
711 mNativeImeAdapterAndroid = 0; | 839 mNativeImeAdapterAndroid = 0; |
712 mTextInputType = 0; | 840 mTextInputType = 0; |
| 841 mCursorAnchorInfoBuilder.reset(); |
713 } | 842 } |
714 | 843 |
715 private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndr
oid, | 844 private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndr
oid, |
716 int eventType, long timestampMs, int keyCode, int modifiers, int uni
codeChar); | 845 int eventType, long timestampMs, int keyCode, int modifiers, int uni
codeChar); |
717 | 846 |
718 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE
vent event, | 847 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE
vent event, |
719 int action, int modifiers, long timestampMs, int keyCode, boolean is
SystemKey, | 848 int action, int modifiers, long timestampMs, int keyCode, boolean is
SystemKey, |
720 int unicodeChar); | 849 int unicodeChar); |
721 | 850 |
722 private static native void nativeAppendUnderlineSpan(long underlinePtr, int
start, int end); | 851 private static native void nativeAppendUnderlineSpan(long underlinePtr, int
start, int end); |
(...skipping 18 matching lines...) Expand all Loading... |
741 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid
, | 870 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid
, |
742 int before, int after); | 871 int before, int after); |
743 | 872 |
744 private native void nativeUnselect(long nativeImeAdapterAndroid); | 873 private native void nativeUnselect(long nativeImeAdapterAndroid); |
745 private native void nativeSelectAll(long nativeImeAdapterAndroid); | 874 private native void nativeSelectAll(long nativeImeAdapterAndroid); |
746 private native void nativeCut(long nativeImeAdapterAndroid); | 875 private native void nativeCut(long nativeImeAdapterAndroid); |
747 private native void nativeCopy(long nativeImeAdapterAndroid); | 876 private native void nativeCopy(long nativeImeAdapterAndroid); |
748 private native void nativePaste(long nativeImeAdapterAndroid); | 877 private native void nativePaste(long nativeImeAdapterAndroid); |
749 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); | 878 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); |
750 } | 879 } |
OLD | NEW |