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.content.res.Configuration; | 7 import android.content.res.Configuration; |
8 import android.os.Handler; | 8 import android.os.Handler; |
9 import android.os.ResultReceiver; | 9 import android.os.ResultReceiver; |
10 import android.os.SystemClock; | 10 import android.os.SystemClock; |
11 import android.text.Editable; | 11 import android.text.Editable; |
12 import android.text.SpannableString; | 12 import android.text.SpannableString; |
13 import android.text.style.BackgroundColorSpan; | 13 import android.text.style.BackgroundColorSpan; |
14 import android.text.style.CharacterStyle; | 14 import android.text.style.CharacterStyle; |
15 import android.text.style.UnderlineSpan; | 15 import android.text.style.UnderlineSpan; |
16 import android.view.KeyCharacterMap; | 16 import android.view.KeyCharacterMap; |
17 import android.view.KeyEvent; | 17 import android.view.KeyEvent; |
18 import android.view.View; | 18 import android.view.View; |
| 19 import android.view.inputmethod.CursorAnchorInfo; |
19 import android.view.inputmethod.EditorInfo; | 20 import android.view.inputmethod.EditorInfo; |
| 21 import android.view.inputmethod.InputMethodManager; |
20 | 22 |
21 import org.chromium.base.CalledByNative; | 23 import org.chromium.base.CalledByNative; |
22 import org.chromium.base.JNINamespace; | 24 import org.chromium.base.JNINamespace; |
23 import org.chromium.base.VisibleForTesting; | 25 import org.chromium.base.VisibleForTesting; |
24 import org.chromium.blink_public.web.WebInputEventModifier; | 26 import org.chromium.blink_public.web.WebInputEventModifier; |
25 import org.chromium.blink_public.web.WebInputEventType; | 27 import org.chromium.blink_public.web.WebInputEventType; |
26 import org.chromium.blink_public.web.WebTextInputFlags; | 28 import org.chromium.blink_public.web.WebTextInputFlags; |
| 29 import org.chromium.content.browser.RenderCoordinates; |
27 import org.chromium.ui.base.ime.TextInputType; | 30 import org.chromium.ui.base.ime.TextInputType; |
28 import org.chromium.ui.picker.InputDialogContainer; | 31 import org.chromium.ui.picker.InputDialogContainer; |
29 | 32 |
30 import java.lang.CharSequence; | 33 import java.lang.CharSequence; |
31 | 34 |
32 /** | 35 /** |
33 * Adapts and plumbs android IME service onto the chrome text input API. | 36 * Adapts and plumbs android IME service onto the chrome text input API. |
34 * ImeAdapter provides an interface in both ways native <-> java: | 37 * ImeAdapter provides an interface in both ways native <-> java: |
35 * 1. InputConnectionAdapter notifies native code of text composition state and | 38 * 1. InputConnectionAdapter notifies native code of text composition state and |
36 * dispatch key events from java -> WebKit. | 39 * dispatch key events from java -> WebKit. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 | 106 |
104 private long mNativeImeAdapterAndroid; | 107 private long mNativeImeAdapterAndroid; |
105 private InputMethodManagerWrapper mInputMethodManagerWrapper; | 108 private InputMethodManagerWrapper mInputMethodManagerWrapper; |
106 private AdapterInputConnection mInputConnection; | 109 private AdapterInputConnection mInputConnection; |
107 private final ImeAdapterDelegate mViewEmbedder; | 110 private final ImeAdapterDelegate mViewEmbedder; |
108 private final Handler mHandler; | 111 private final Handler mHandler; |
109 private int mTextInputType; | 112 private int mTextInputType; |
110 private int mTextInputFlags; | 113 private int mTextInputFlags; |
111 private String mLastComposeText; | 114 private String mLastComposeText; |
112 | 115 |
| 116 private final CursorAnchorInfoController mCursorAnchorInfoController; |
| 117 |
113 @VisibleForTesting | 118 @VisibleForTesting |
114 int mLastSyntheticKeyCode; | 119 int mLastSyntheticKeyCode; |
115 | 120 |
116 @VisibleForTesting | 121 @VisibleForTesting |
117 boolean mIsShowWithoutHideOutstanding = false; | 122 boolean mIsShowWithoutHideOutstanding = false; |
118 | 123 |
119 /** | 124 /** |
120 * @param wrapper InputMethodManagerWrapper that should receive all the call
directed to | 125 * @param wrapper InputMethodManagerWrapper that should receive all the call
directed to |
121 * InputMethodManager. | 126 * InputMethodManager. |
122 * @param embedder The view that is used for callbacks from ImeAdapter. | 127 * @param embedder The view that is used for callbacks from ImeAdapter. |
123 */ | 128 */ |
124 public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embe
dder) { | 129 public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embe
dder) { |
125 mInputMethodManagerWrapper = wrapper; | 130 mInputMethodManagerWrapper = wrapper; |
126 mViewEmbedder = embedder; | 131 mViewEmbedder = embedder; |
127 mHandler = new Handler(); | 132 mHandler = new Handler(); |
| 133 mCursorAnchorInfoController = CursorAnchorInfoController.create(wrapper)
; |
128 } | 134 } |
129 | 135 |
130 /** | 136 /** |
131 * Default factory for AdapterInputConnection classes. | 137 * Default factory for AdapterInputConnection classes. |
132 */ | 138 */ |
133 public static class AdapterInputConnectionFactory { | 139 public static class AdapterInputConnectionFactory { |
134 public AdapterInputConnection get(View view, ImeAdapter imeAdapter, | 140 public AdapterInputConnection get(View view, ImeAdapter imeAdapter, |
135 Editable editable, EditorInfo outAttrs) { | 141 Editable editable, EditorInfo outAttrs) { |
136 return new AdapterInputConnection(view, imeAdapter, editable, outAtt
rs); | 142 return new AdapterInputConnection(view, imeAdapter, editable, outAtt
rs); |
137 } | 143 } |
138 } | 144 } |
139 | 145 |
140 /** | 146 /** |
141 * Overrides the InputMethodManagerWrapper that ImeAdapter uses to make call
s to | 147 * Overrides the InputMethodManagerWrapper that ImeAdapter uses to make call
s to |
142 * InputMethodManager. | 148 * InputMethodManager. |
143 * @param immw InputMethodManagerWrapper that should be used to call InputMe
thodManager. | 149 * @param immw InputMethodManagerWrapper that should be used to call InputMe
thodManager. |
144 */ | 150 */ |
145 @VisibleForTesting | 151 @VisibleForTesting |
146 public void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) { | 152 public void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) { |
147 mInputMethodManagerWrapper = immw; | 153 mInputMethodManagerWrapper = immw; |
| 154 if (mCursorAnchorInfoController != null) { |
| 155 mCursorAnchorInfoController.setInputMethodManagerWrapper(immw); |
| 156 } |
148 } | 157 } |
149 | 158 |
150 /** | 159 /** |
151 * Should be only used by AdapterInputConnection. | 160 * Should be only used by AdapterInputConnection. |
152 * @return InputMethodManagerWrapper that should receive all the calls direc
ted to | 161 * @return InputMethodManagerWrapper that should receive all the calls direc
ted to |
153 * InputMethodManager. | 162 * InputMethodManager. |
154 */ | 163 */ |
155 InputMethodManagerWrapper getInputMethodManagerWrapper() { | 164 InputMethodManagerWrapper getInputMethodManagerWrapper() { |
156 return mInputMethodManagerWrapper; | 165 return mInputMethodManagerWrapper; |
157 } | 166 } |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 /** | 611 /** |
603 * Send a request to the native counterpart of ImeAdapter to paste the text
from the clipboard. | 612 * Send a request to the native counterpart of ImeAdapter to paste the text
from the clipboard. |
604 * @return Whether the native counterpart of ImeAdapter received the call. | 613 * @return Whether the native counterpart of ImeAdapter received the call. |
605 */ | 614 */ |
606 public boolean paste() { | 615 public boolean paste() { |
607 if (mNativeImeAdapterAndroid == 0) return false; | 616 if (mNativeImeAdapterAndroid == 0) return false; |
608 nativePaste(mNativeImeAdapterAndroid); | 617 nativePaste(mNativeImeAdapterAndroid); |
609 return true; | 618 return true; |
610 } | 619 } |
611 | 620 |
| 621 public boolean onRequestCursorUpdates(int cursorUpdateMode) { |
| 622 if (mCursorAnchorInfoController == null) return false; |
| 623 return mCursorAnchorInfoController.onRequestCursorUpdates(cursorUpdateMo
de, |
| 624 mViewEmbedder.getAttachedView()); |
| 625 } |
| 626 |
| 627 /** |
| 628 * Update the parameters that are to be passed to the IME through |
| 629 * {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)}
. |
| 630 * @param text Text in the focused text field. |
| 631 * @param selectionStart Index where the text selection starts. {@code -1} i
f there is no |
| 632 * selection. |
| 633 * @param selectionEnd Index where the text selection ends. {@code -1} if th
ere is no |
| 634 * selection. |
| 635 * @param compositionStart Index where the text composition starts. {@code -
1} if there is no |
| 636 * selection. |
| 637 * @param compositionEnd Index where the text composition ends. {@code -1} i
f there is no |
| 638 * selection. |
| 639 */ |
| 640 public void updateTextAndSelection(String text, int selectionStart, int sele
ctionEnd, |
| 641 int compositionStart, int compositionEnd) { |
| 642 if (mCursorAnchorInfoController == null) return; |
| 643 mCursorAnchorInfoController.updateTextAndSelection(text, compositionStar
t, compositionEnd, |
| 644 selectionStart, selectionEnd); |
| 645 } |
| 646 |
| 647 /** |
| 648 * Notify the location of composing characters to the IME if it explicitly r
equested them. |
| 649 * @param renderCoordinates coordinate information to convert CSS (document)
coordinates to |
| 650 * View-local Physical (screen) coordinates |
| 651 * @param hasInsertionMarker Whether the insertion marker is visible or not. |
| 652 * @param insertionMarkerHorizontal X coordinates of the insertion marker if
it exists. |
| 653 * Will be ignored otherwise. |
| 654 * @param insertionMarkerTop Y coordinates of the top of the insertion marke
r if it exists. |
| 655 * Will be ignored otherwise. |
| 656 * @param insertionMarkerBottom Y coordinates of the bottom of the insertion
marker if it |
| 657 * exists. Will be ignored otherwise. |
| 658 */ |
| 659 public void onUpdateFrameInfo(RenderCoordinates renderCoordinates, boolean h
asInsertionMarker, |
| 660 boolean isInsertionMarkerVisible, float insertionMarkerHorizontal, |
| 661 float insertionMarkerTop, float insertionMarkerBottom) { |
| 662 if (mCursorAnchorInfoController == null) return; |
| 663 mCursorAnchorInfoController.onUpdateFrameInfo(renderCoordinates, hasInse
rtionMarker, |
| 664 isInsertionMarkerVisible, insertionMarkerHorizontal, insertionMa
rkerTop, |
| 665 insertionMarkerBottom, mViewEmbedder.getAttachedView()); |
| 666 } |
| 667 |
612 // Calls from C++ to Java | 668 // Calls from C++ to Java |
613 | 669 |
614 @CalledByNative | 670 @CalledByNative |
615 private void focusedNodeChanged(boolean isEditable) { | 671 private void focusedNodeChanged(boolean isEditable) { |
| 672 // Update controller before the connection is restarted. |
| 673 if (mCursorAnchorInfoController != null) { |
| 674 mCursorAnchorInfoController.focusedNodeChanged(isEditable); |
| 675 } |
616 if (mInputConnection != null && isEditable) mInputConnection.restartInpu
t(); | 676 if (mInputConnection != null && isEditable) mInputConnection.restartInpu
t(); |
617 } | 677 } |
618 | 678 |
619 @CalledByNative | 679 @CalledByNative |
620 private void populateUnderlinesFromSpans(CharSequence text, long underlines)
{ | 680 private void populateUnderlinesFromSpans(CharSequence text, long underlines)
{ |
621 if (!(text instanceof SpannableString)) return; | 681 if (!(text instanceof SpannableString)) return; |
622 | 682 |
623 SpannableString spannableString = ((SpannableString) text); | 683 SpannableString spannableString = ((SpannableString) text); |
624 CharacterStyle spans[] = | 684 CharacterStyle spans[] = |
625 spannableString.getSpans(0, text.length(), CharacterStyle.class)
; | 685 spannableString.getSpans(0, text.length(), CharacterStyle.class)
; |
626 for (CharacterStyle span : spans) { | 686 for (CharacterStyle span : spans) { |
627 if (span instanceof BackgroundColorSpan) { | 687 if (span instanceof BackgroundColorSpan) { |
628 nativeAppendBackgroundColorSpan(underlines, spannableString.getS
panStart(span), | 688 nativeAppendBackgroundColorSpan(underlines, spannableString.getS
panStart(span), |
629 spannableString.getSpanEnd(span), | 689 spannableString.getSpanEnd(span), |
630 ((BackgroundColorSpan) span).getBackgroundColor()); | 690 ((BackgroundColorSpan) span).getBackgroundColor()); |
631 } else if (span instanceof UnderlineSpan) { | 691 } else if (span instanceof UnderlineSpan) { |
632 nativeAppendUnderlineSpan(underlines, spannableString.getSpanSta
rt(span), | 692 nativeAppendUnderlineSpan(underlines, spannableString.getSpanSta
rt(span), |
633 spannableString.getSpanEnd(span)); | 693 spannableString.getSpanEnd(span)); |
634 } | 694 } |
635 } | 695 } |
636 } | 696 } |
637 | 697 |
638 @CalledByNative | 698 @CalledByNative |
639 private void cancelComposition() { | 699 private void cancelComposition() { |
640 if (mInputConnection != null) mInputConnection.restartInput(); | 700 if (mInputConnection != null) mInputConnection.restartInput(); |
641 mLastComposeText = null; | 701 mLastComposeText = null; |
642 } | 702 } |
643 | 703 |
644 @CalledByNative | 704 @CalledByNative |
| 705 private void setCharacterBounds(float[] characterBounds) { |
| 706 if (mCursorAnchorInfoController == null) return; |
| 707 mCursorAnchorInfoController.setCompositionCharacterBounds(characterBound
s); |
| 708 } |
| 709 |
| 710 @CalledByNative |
645 void detach() { | 711 void detach() { |
646 mHandler.removeCallbacks(mDismissInputRunnable); | 712 mHandler.removeCallbacks(mDismissInputRunnable); |
647 mNativeImeAdapterAndroid = 0; | 713 mNativeImeAdapterAndroid = 0; |
648 mTextInputType = 0; | 714 mTextInputType = 0; |
| 715 if (mCursorAnchorInfoController != null) { |
| 716 mCursorAnchorInfoController.focusedNodeChanged(false); |
| 717 } |
649 } | 718 } |
650 | 719 |
651 private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndr
oid, | 720 private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndr
oid, |
652 int eventType, long timestampMs, int keyCode, int modifiers, int uni
codeChar); | 721 int eventType, long timestampMs, int keyCode, int modifiers, int uni
codeChar); |
653 | 722 |
654 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE
vent event, | 723 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE
vent event, |
655 int action, int modifiers, long timestampMs, int keyCode, boolean is
SystemKey, | 724 int action, int modifiers, long timestampMs, int keyCode, boolean is
SystemKey, |
656 int unicodeChar); | 725 int unicodeChar); |
657 | 726 |
658 private static native void nativeAppendUnderlineSpan(long underlinePtr, int
start, int end); | 727 private static native void nativeAppendUnderlineSpan(long underlinePtr, int
start, int end); |
(...skipping 18 matching lines...) Expand all Loading... |
677 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid
, | 746 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid
, |
678 int before, int after); | 747 int before, int after); |
679 | 748 |
680 private native void nativeUnselect(long nativeImeAdapterAndroid); | 749 private native void nativeUnselect(long nativeImeAdapterAndroid); |
681 private native void nativeSelectAll(long nativeImeAdapterAndroid); | 750 private native void nativeSelectAll(long nativeImeAdapterAndroid); |
682 private native void nativeCut(long nativeImeAdapterAndroid); | 751 private native void nativeCut(long nativeImeAdapterAndroid); |
683 private native void nativeCopy(long nativeImeAdapterAndroid); | 752 private native void nativeCopy(long nativeImeAdapterAndroid); |
684 private native void nativePaste(long nativeImeAdapterAndroid); | 753 private native void nativePaste(long nativeImeAdapterAndroid); |
685 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); | 754 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); |
686 } | 755 } |
OLD | NEW |