Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java

Issue 1278593004: Introduce ThreadedInputConnection behind a switch (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: straighten up state update, replace mQueue.poll() by mQueue.take() Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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.ResultReceiver; 8 import android.os.ResultReceiver;
9 import android.os.SystemClock; 9 import android.os.SystemClock;
10 import android.text.Editable;
11 import android.text.Selection;
12 import android.text.SpannableString; 10 import android.text.SpannableString;
13 import android.text.style.BackgroundColorSpan; 11 import android.text.style.BackgroundColorSpan;
14 import android.text.style.CharacterStyle; 12 import android.text.style.CharacterStyle;
15 import android.text.style.UnderlineSpan; 13 import android.text.style.UnderlineSpan;
16 import android.view.KeyCharacterMap; 14 import android.view.KeyCharacterMap;
17 import android.view.KeyEvent; 15 import android.view.KeyEvent;
18 import android.view.View; 16 import android.view.View;
19 import android.view.inputmethod.BaseInputConnection; 17 import android.view.inputmethod.BaseInputConnection;
20 import android.view.inputmethod.EditorInfo; 18 import android.view.inputmethod.EditorInfo;
21 19
20 import org.chromium.base.CommandLine;
22 import org.chromium.base.Log; 21 import org.chromium.base.Log;
23 import org.chromium.base.VisibleForTesting; 22 import org.chromium.base.VisibleForTesting;
24 import org.chromium.base.annotations.CalledByNative; 23 import org.chromium.base.annotations.CalledByNative;
25 import org.chromium.base.annotations.JNINamespace; 24 import org.chromium.base.annotations.JNINamespace;
26 import org.chromium.blink_public.web.WebInputEventModifier; 25 import org.chromium.blink_public.web.WebInputEventModifier;
27 import org.chromium.blink_public.web.WebInputEventType; 26 import org.chromium.blink_public.web.WebInputEventType;
27 import org.chromium.content.common.ContentSwitches;
28 import org.chromium.ui.base.ime.TextInputType; 28 import org.chromium.ui.base.ime.TextInputType;
29 import org.chromium.ui.picker.InputDialogContainer; 29 import org.chromium.ui.picker.InputDialogContainer;
30 30
31 /** 31 /**
32 * 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.
33 * ImeAdapter provides an interface in both ways native <-> java: 33 * ImeAdapter provides an interface in both ways native <-> java:
34 * 1. InputConnectionAdapter notifies native code of text composition state and 34 * 1. InputConnectionAdapter notifies native code of text composition state and
35 * dispatch key events from java -> WebKit. 35 * dispatch key events from java -> WebKit.
36 * 2. Native ImeAdapter notifies java side to clear composition text. 36 * 2. Native ImeAdapter notifies java side to clear composition text.
37 * 37 *
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 * @return Object that should be called for all keyboard show and hide r equests. 83 * @return Object that should be called for all keyboard show and hide r equests.
84 */ 84 */
85 ResultReceiver getNewShowKeyboardReceiver(); 85 ResultReceiver getNewShowKeyboardReceiver();
86 } 86 }
87 87
88 static char[] sSingleCharArray = new char[1]; 88 static char[] sSingleCharArray = new char[1];
89 static KeyCharacterMap sKeyCharacterMap; 89 static KeyCharacterMap sKeyCharacterMap;
90 90
91 private long mNativeImeAdapterAndroid; 91 private long mNativeImeAdapterAndroid;
92 private InputMethodManagerWrapper mInputMethodManagerWrapper; 92 private InputMethodManagerWrapper mInputMethodManagerWrapper;
93 private AdapterInputConnection mInputConnection; 93 private ChromiumBaseInputConnection mInputConnection;
94 private AdapterInputConnectionFactory mInputConnectionFactory; 94 private ChromiumBaseInputConnection.Factory mInputConnectionFactory;
95
95 private final ImeAdapterDelegate mViewEmbedder; 96 private final ImeAdapterDelegate mViewEmbedder;
96 97
97 // This holds the state of editable text (e.g. contents of <input>, contente ditable) of
98 // a focused element.
99 // Every time the user, IME, javascript (Blink), autofill etc. modifies the content, the new
100 // state must be reflected to this to keep consistency.
101 private final Editable mEditable;
102
103 private int mTextInputType = TextInputType.NONE; 98 private int mTextInputType = TextInputType.NONE;
104 private int mTextInputFlags; 99 private int mTextInputFlags;
105 100
106 // Keep the current configuration to detect the change when onConfigurationC hanged() is called. 101 // Keep the current configuration to detect the change when onConfigurationC hanged() is called.
107 private Configuration mCurrentConfig; 102 private Configuration mCurrentConfig;
108 103
109 /** 104 /**
110 * @param wrapper InputMethodManagerWrapper that should receive all the call directed to 105 * @param wrapper InputMethodManagerWrapper that should receive all the call directed to
111 * InputMethodManager. 106 * InputMethodManager.
112 * @param embedder The view that is used for callbacks from ImeAdapter. 107 * @param embedder The view that is used for callbacks from ImeAdapter.
113 */ 108 */
114 public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embe dder) { 109 public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embe dder) {
115 mInputMethodManagerWrapper = wrapper; 110 mInputMethodManagerWrapper = wrapper;
116 mViewEmbedder = embedder; 111 mViewEmbedder = embedder;
117 mInputConnectionFactory = new AdapterInputConnectionFactory(); 112 if (CommandLine.getInstance().hasSwitch(ContentSwitches.USE_IME_THREAD)) {
118 mEditable = Editable.Factory.getInstance().newEditable(""); 113 mInputConnectionFactory = new ChromiumInputConnectionFactory();
119 Selection.setSelection(mEditable, 0); 114 } else {
115 mInputConnectionFactory = new ReplicaInputConnection.Factory();
116 }
120 // Deep copy newConfig so that we can notice the difference. 117 // Deep copy newConfig so that we can notice the difference.
121 mCurrentConfig = new Configuration( 118 mCurrentConfig = new Configuration(
122 mViewEmbedder.getAttachedView().getResources().getConfiguration( )); 119 mViewEmbedder.getAttachedView().getResources().getConfiguration( ));
123 } 120 }
124 121
125 /** 122 /**
126 * Default factory for AdapterInputConnection classes.
127 */
128 static class AdapterInputConnectionFactory {
129 AdapterInputConnection get(View view, ImeAdapter imeAdapter, int initial SelStart,
130 int initialSelEnd, EditorInfo outAttrs) {
131 return new AdapterInputConnection(
132 view, imeAdapter, initialSelStart, initialSelEnd, outAttrs);
133 }
134 }
135
136 /**
137 * @see View#onCreateInputConnection(EditorInfo) 123 * @see View#onCreateInputConnection(EditorInfo)
138 */ 124 */
139 public AdapterInputConnection onCreateInputConnection(EditorInfo outAttrs) { 125 public ChromiumBaseInputConnection onCreateInputConnection(EditorInfo outAtt rs) {
140 // Without this line, some third-party IMEs will try to compose text eve n when 126 // Without this line, some third-party IMEs will try to compose text eve n when
141 // not on an editable node. Even when we return null here, key events ca n still go through 127 // not on an editable node. Even when we return null here, key events ca n still go
142 // ImeAdapter#dispatchKeyEvent(). 128 // through ImeAdapter#dispatchKeyEvent().
143 if (mTextInputType == TextInputType.NONE) { 129 if (mTextInputType == TextInputType.NONE) {
144 mInputConnection = null; 130 mInputConnection = null;
145 Log.d(TAG, "onCreateInputConnection returns null."); 131 Log.d(TAG, "onCreateInputConnection returns null.");
146 // InputMethodService evaluates fullscreen mode even when the new in put connection is 132 // InputMethodService evaluates fullscreen mode even when the new in put connection is
147 // null. This makes sure IME doesn't enter fullscreen mode or open c ustom UI. 133 // null. This makes sure IME doesn't enter fullscreen mode or open c ustom UI.
148 outAttrs.imeOptions = 134 outAttrs.imeOptions =
149 EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FLAG_NO_E XTRACT_UI; 135 EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FLAG_NO_E XTRACT_UI;
150 return null; 136 return null;
151 } 137 }
152 138 mInputConnection = mInputConnectionFactory.initializeAndGet(
153 if (!isTextInputType(mTextInputType)) { 139 mViewEmbedder.getAttachedView(), this, mTextInputType, mTextInpu tFlags, outAttrs);
154 // Although onCheckIsTextEditor will return false in this case, the EditorInfo 140 Log.d(TAG, "onCreateInputConnection: " + mInputConnection);
155 // is still used by the InputMethodService. Need to make sure the IM E doesn't
156 // enter fullscreen mode.
157 outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
158 }
159 int initialSelStart = Selection.getSelectionStart(mEditable);
160 int initialSelEnd = outAttrs.initialSelEnd = Selection.getSelectionEnd(m Editable);
161 mInputConnection = mInputConnectionFactory.get(
162 mViewEmbedder.getAttachedView(), this, initialSelStart, initialS elEnd, outAttrs);
163 Log.d(TAG, "onCreateInputConnection");
164 return mInputConnection; 141 return mInputConnection;
165 } 142 }
166 143
167 /** 144 /**
168 * Overrides the InputMethodManagerWrapper that ImeAdapter uses to make call s to 145 * Overrides the InputMethodManagerWrapper that ImeAdapter uses to make call s to
169 * InputMethodManager. 146 * InputMethodManager.
170 * @param immw InputMethodManagerWrapper that should be used to call InputMe thodManager. 147 * @param immw InputMethodManagerWrapper that should be used to call InputMe thodManager.
171 */ 148 */
172 @VisibleForTesting 149 @VisibleForTesting
173 public void setInputMethodManagerWrapperForTest(InputMethodManagerWrapper im mw) { 150 public void setInputMethodManagerWrapperForTest(InputMethodManagerWrapper im mw) {
174 mInputMethodManagerWrapper = immw; 151 mInputMethodManagerWrapper = immw;
175 } 152 }
176 153
177 @VisibleForTesting 154 @VisibleForTesting
178 void setInputConnectionFactory(AdapterInputConnectionFactory factory) { 155 void setInputConnectionFactory(ChromiumBaseInputConnection.Factory factory) {
179 mInputConnectionFactory = factory; 156 mInputConnectionFactory = factory;
180 } 157 }
181 158
182 /** 159 /**
183 * Set the current active InputConnection when a new InputConnection is cons tructed.
184 * @param inputConnection The input connection that is currently used with I ME.
185 */
186 void setInputConnection(AdapterInputConnection inputConnection) {
187 mInputConnection = inputConnection;
188 }
189
190 /**
191 * Get the current input connection for testing purposes. 160 * Get the current input connection for testing purposes.
192 */ 161 */
193 @VisibleForTesting 162 @VisibleForTesting
194 public AdapterInputConnection getInputConnectionForTest() { 163 public ChromiumBaseInputConnection getInputConnectionForTest() {
195 return mInputConnection; 164 return mInputConnection;
196 } 165 }
197 166
198 /**
199 * @return The Editable instance that will be shared across AdapterInputConn ection instances.
200 */
201 Editable getEditable() {
202 return mEditable;
203 }
204
205 /**
206 * Should be used only by AdapterInputConnection.
207 * @return The input type of currently focused element.
208 */
209 int getTextInputType() {
210 return mTextInputType;
211 }
212
213 /**
214 * Should be used only by AdapterInputConnection.
215 * @return The input flags of the currently focused element.
216 */
217 int getTextInputFlags() {
218 return mTextInputFlags;
219 }
220
221 private static int getModifiers(int metaState) { 167 private static int getModifiers(int metaState) {
222 int modifiers = 0; 168 int modifiers = 0;
223 if ((metaState & KeyEvent.META_SHIFT_ON) != 0) { 169 if ((metaState & KeyEvent.META_SHIFT_ON) != 0) {
224 modifiers |= WebInputEventModifier.ShiftKey; 170 modifiers |= WebInputEventModifier.ShiftKey;
225 } 171 }
226 if ((metaState & KeyEvent.META_ALT_ON) != 0) { 172 if ((metaState & KeyEvent.META_ALT_ON) != 0) {
227 modifiers |= WebInputEventModifier.AltKey; 173 modifiers |= WebInputEventModifier.AltKey;
228 } 174 }
229 if ((metaState & KeyEvent.META_CTRL_ON) != 0) { 175 if ((metaState & KeyEvent.META_CTRL_ON) != 0) {
230 modifiers |= WebInputEventModifier.ControlKey; 176 modifiers |= WebInputEventModifier.ControlKey;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 * is no selection. 221 * is no selection.
276 * @param compositionStart The character offset of the composition start, or -1 if there is no 222 * @param compositionStart The character offset of the composition start, or -1 if there is no
277 * composition. 223 * composition.
278 * @param compositionEnd The character offset of the composition end, or -1 if there is no 224 * @param compositionEnd The character offset of the composition end, or -1 if there is no
279 * selection. 225 * selection.
280 * @param isNonImeChange True when the update was caused by non-IME (e.g. Ja vascript). 226 * @param isNonImeChange True when the update was caused by non-IME (e.g. Ja vascript).
281 */ 227 */
282 public void updateState(String text, int selectionStart, int selectionEnd, i nt compositionStart, 228 public void updateState(String text, int selectionStart, int selectionEnd, i nt compositionStart,
283 int compositionEnd, boolean isNonImeChange) { 229 int compositionEnd, boolean isNonImeChange) {
284 if (mInputConnection == null) return; 230 if (mInputConnection == null) return;
285 mInputConnection.updateState(text, selectionStart, selectionEnd, composi tionStart, 231 boolean singleLine = mTextInputType != TextInputType.TEXT_AREA
286 compositionEnd, isNonImeChange); 232 && mTextInputType != TextInputType.CONTENT_EDITABLE;
233 mInputConnection.updateStateOnUiThread(text, selectionStart, selectionEn d, compositionStart,
234 compositionEnd, singleLine, isNonImeChange);
287 } 235 }
288 236
289 /** 237 /**
290 * Attaches the imeAdapter to its native counterpart. This is needed to star t forwarding 238 * Attaches the imeAdapter to its native counterpart. This is needed to star t forwarding
291 * keyboard events to WebKit. 239 * keyboard events to WebKit.
292 * @param nativeImeAdapter The pointer to the native ImeAdapter object. 240 * @param nativeImeAdapter The pointer to the native ImeAdapter object.
293 */ 241 */
294 public void attach(long nativeImeAdapter) { 242 public void attach(long nativeImeAdapter) {
295 if (mNativeImeAdapterAndroid == nativeImeAdapter) return; 243 if (mNativeImeAdapterAndroid == nativeImeAdapter) return;
296 if (mNativeImeAdapterAndroid != 0) { 244 if (mNativeImeAdapterAndroid != 0) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 Log.d(TAG, "onViewFocusChanged: gainFocus [%b]", gainFocus); 311 Log.d(TAG, "onViewFocusChanged: gainFocus [%b]", gainFocus);
364 if (!gainFocus) hideKeyboard(); 312 if (!gainFocus) hideKeyboard();
365 } 313 }
366 314
367 /** 315 /**
368 * Move cursor to the end of the current selection. 316 * Move cursor to the end of the current selection.
369 */ 317 */
370 public void moveCursorToSelectionEnd() { 318 public void moveCursorToSelectionEnd() {
371 Log.d(TAG, "movecursorToEnd"); 319 Log.d(TAG, "movecursorToEnd");
372 if (mInputConnection != null) { 320 if (mInputConnection != null) {
373 int selectionEnd = Selection.getSelectionEnd(mEditable); 321 mInputConnection.moveCursorToSelectionEndOnUiThread();
374 mInputConnection.setSelection(selectionEnd, selectionEnd);
375 } 322 }
376 } 323 }
377 324
378 @VisibleForTesting 325 @VisibleForTesting
379 void setInputTypeForTest(int textInputType) { 326 void setInputTypeForTest(int textInputType) {
380 mTextInputType = textInputType; 327 mTextInputType = textInputType;
381 } 328 }
382 329
383 private static boolean isTextInputType(int type) { 330 private static boolean isTextInputType(int type) {
384 return type != TextInputType.NONE && !InputDialogContainer.isDialogInput Type(type); 331 return type != TextInputType.NONE && !InputDialogContainer.isDialogInput Type(type);
385 } 332 }
386 333
387 public boolean hasTextInputType() { 334 public boolean hasTextInputType() {
388 return isTextInputType(mTextInputType); 335 return isTextInputType(mTextInputType);
389 } 336 }
390 337
391 public boolean dispatchKeyEvent(KeyEvent event) { 338 public boolean dispatchKeyEvent(KeyEvent event) {
392 Log.d(TAG, "dispatchKeyEvent: action [%d], keycode [%d]", event.getActio n(), 339 Log.d(TAG, "dispatchKeyEvent: action [%d], keycode [%d]", event.getActio n(),
393 event.getKeyCode()); 340 event.getKeyCode());
394 if (mInputConnection != null) { 341 if (mInputConnection != null) return mInputConnection.sendKeyEventOnUiTh read(event);
395 return mInputConnection.sendKeyEvent(event);
396 }
397 return sendKeyEvent(event); 342 return sendKeyEvent(event);
398 } 343 }
399 344
400 /** 345 /**
401 * Update selection to input method manager. 346 * Update selection to input method manager.
402 * 347 *
403 * @param selectionStart The selection start. 348 * @param selectionStart The selection start.
404 * @param selectionEnd The selection end. 349 * @param selectionEnd The selection end.
405 * @param compositionStart The composition start. 350 * @param compositionStart The composition start.
406 * @param compositionEnd The composition end. 351 * @param compositionEnd The composition end.
407 */ 352 */
408 void updateSelection( 353 void updateSelection(
409 int selectionStart, int selectionEnd, int compositionStart, int comp ositionEnd) { 354 int selectionStart, int selectionEnd, int compositionStart, int comp ositionEnd) {
410 mInputMethodManagerWrapper.updateSelection(mViewEmbedder.getAttachedView (), selectionStart, 355 mInputMethodManagerWrapper.updateSelection(mViewEmbedder.getAttachedView (), selectionStart,
411 selectionEnd, compositionStart, compositionEnd); 356 selectionEnd, compositionStart, compositionEnd);
412 } 357 }
413 358
414 /** 359 /**
415 * Restart input (finish composition and change EditorInfo, such as input ty pe). 360 * Restart input (finish composition and change EditorInfo, such as input ty pe).
416 */ 361 */
417 void restartInput() { 362 void restartInput() {
418 mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView()) ; 363 mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView()) ;
419 if (mInputConnection != null) mInputConnection.onRestartInput(); 364 if (mInputConnection != null) mInputConnection.onRestartInputOnUiThread( );
420 } 365 }
421 366
422 /** 367 /**
423 * @see BaseInputConnection#performContextMenuAction(int) 368 * @see BaseInputConnection#performContextMenuAction(int)
424 */ 369 */
425 boolean performContextMenuAction(int id) { 370 boolean performContextMenuAction(int id) {
426 Log.d(TAG, "performContextMenuAction: id [%d]", id); 371 Log.d(TAG, "performContextMenuAction: id [%d]", id);
427 return mViewEmbedder.performContextMenuAction(id); 372 return mViewEmbedder.performContextMenuAction(id);
428 } 373 }
429 374
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 nativeSetComposingText( 420 nativeSetComposingText(
476 mNativeImeAdapterAndroid, text, text.toString(), newCursorPo sition); 421 mNativeImeAdapterAndroid, text, text.toString(), newCursorPo sition);
477 } 422 }
478 423
479 nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, WebInputEventType. KeyUp, 424 nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, WebInputEventType. KeyUp,
480 timestampMs, COMPOSITION_KEY_CODE, 0, 0); 425 timestampMs, COMPOSITION_KEY_CODE, 0, 0);
481 return true; 426 return true;
482 } 427 }
483 428
484 @VisibleForTesting 429 @VisibleForTesting
485 void finishComposingText() { 430 boolean finishComposingText() {
486 if (mNativeImeAdapterAndroid == 0) return; 431 if (mNativeImeAdapterAndroid == 0) return false;
487 nativeFinishComposingText(mNativeImeAdapterAndroid); 432 nativeFinishComposingText(mNativeImeAdapterAndroid);
433 return true;
488 } 434 }
489 435
490 boolean sendKeyEvent(KeyEvent event) { 436 boolean sendKeyEvent(KeyEvent event) {
491 if (mNativeImeAdapterAndroid == 0) return false; 437 if (mNativeImeAdapterAndroid == 0) return false;
492 438
493 int action = event.getAction(); 439 int action = event.getAction();
494 if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_UP) { 440 if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_UP) {
495 // action == KeyEvent.ACTION_MULTIPLE 441 // action == KeyEvent.ACTION_MULTIPLE
496 // TODO(bulach): confirm the actual behavior. Apparently: 442 // TODO(bulach): confirm the actual behavior. Apparently:
497 // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a 443 // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end); 486 nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end);
541 return true; 487 return true;
542 } 488 }
543 489
544 /** 490 /**
545 * Send a request to the native counterpart to set composing region to given indices. 491 * Send a request to the native counterpart to set composing region to given indices.
546 * @param start The start of the composition. 492 * @param start The start of the composition.
547 * @param end The end of the composition. 493 * @param end The end of the composition.
548 * @return Whether the native counterpart of ImeAdapter received the call. 494 * @return Whether the native counterpart of ImeAdapter received the call.
549 */ 495 */
550 boolean setComposingRegion(CharSequence text, int start, int end) { 496 boolean setComposingRegion(int start, int end) {
551 if (mNativeImeAdapterAndroid == 0) return false; 497 if (mNativeImeAdapterAndroid == 0) return false;
552 nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end); 498 nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end);
553 return true; 499 return true;
554 } 500 }
555 501
556 @CalledByNative 502 @CalledByNative
557 private void focusedNodeChanged(boolean isEditable) { 503 private void focusedNodeChanged(boolean isEditable) {
558 Log.d(TAG, "focusedNodeChanged: isEditable [%b]", isEditable); 504 Log.d(TAG, "focusedNodeChanged: isEditable [%b]", isEditable);
559 if (mTextInputType != TextInputType.NONE && mInputConnection != null && isEditable) { 505 if (mTextInputType != TextInputType.NONE && mInputConnection != null && isEditable) {
560 restartInput(); 506 restartInput();
561 } 507 }
562 } 508 }
563 509
510 /**
511 * Send a request to the native counterpart to give the latest text input st ate update.
512 */
513 boolean requestTextInputStateUpdate() {
514 if (mNativeImeAdapterAndroid == 0) return false;
515 return nativeRequestTextInputStateUpdate(mNativeImeAdapterAndroid);
516 }
517
564 @CalledByNative 518 @CalledByNative
565 private void populateUnderlinesFromSpans(CharSequence text, long underlines) { 519 private void populateUnderlinesFromSpans(CharSequence text, long underlines) {
566 Log.d(TAG, "populateUnderlinesFromSpans: text [%s], underlines [%d]", te xt, underlines); 520 Log.d(TAG, "populateUnderlinesFromSpans: text [%s], underlines [%d]", te xt, underlines);
567 if (!(text instanceof SpannableString)) return; 521 if (!(text instanceof SpannableString)) return;
568 522
569 SpannableString spannableString = ((SpannableString) text); 523 SpannableString spannableString = ((SpannableString) text);
570 CharacterStyle spans[] = 524 CharacterStyle spans[] =
571 spannableString.getSpans(0, text.length(), CharacterStyle.class) ; 525 spannableString.getSpans(0, text.length(), CharacterStyle.class) ;
572 for (CharacterStyle span : spans) { 526 for (CharacterStyle span : spans) {
573 if (span instanceof BackgroundColorSpan) { 527 if (span instanceof BackgroundColorSpan) {
(...skipping 14 matching lines...) Expand all
588 } 542 }
589 543
590 @CalledByNative 544 @CalledByNative
591 private void detach() { 545 private void detach() {
592 Log.d(TAG, "detach"); 546 Log.d(TAG, "detach");
593 mNativeImeAdapterAndroid = 0; 547 mNativeImeAdapterAndroid = 0;
594 } 548 }
595 549
596 private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndr oid, 550 private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndr oid,
597 int eventType, long timestampMs, int keyCode, int modifiers, int uni codeChar); 551 int eventType, long timestampMs, int keyCode, int modifiers, int uni codeChar);
598
599 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE vent event, 552 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE vent event,
600 int action, int modifiers, long timestampMs, int keyCode, int scanCo de, 553 int action, int modifiers, long timestampMs, int keyCode, int scanCo de,
601 boolean isSystemKey, int unicodeChar); 554 boolean isSystemKey, int unicodeChar);
602
603 private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end); 555 private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end);
604
605 private static native void nativeAppendBackgroundColorSpan(long underlinePtr , int start, 556 private static native void nativeAppendBackgroundColorSpan(long underlinePtr , int start,
606 int end, int backgroundColor); 557 int end, int backgroundColor);
607
608 private native void nativeSetComposingText(long nativeImeAdapterAndroid, Cha rSequence text, 558 private native void nativeSetComposingText(long nativeImeAdapterAndroid, Cha rSequence text,
609 String textStr, int newCursorPosition); 559 String textStr, int newCursorPosition);
610
611 private native void nativeCommitText(long nativeImeAdapterAndroid, String te xtStr); 560 private native void nativeCommitText(long nativeImeAdapterAndroid, String te xtStr);
612
613 private native void nativeFinishComposingText(long nativeImeAdapterAndroid); 561 private native void nativeFinishComposingText(long nativeImeAdapterAndroid);
614
615 private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid); 562 private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid);
616
617 private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterA ndroid, 563 private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterA ndroid,
618 int start, int end); 564 int start, int end);
619
620 private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, i nt start, int end); 565 private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, i nt start, int end);
621
622 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid , 566 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid ,
623 int before, int after); 567 int before, int after);
624
625 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); 568 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid);
569 private native boolean nativeRequestTextInputStateUpdate(long nativeImeAdapt erAndroid);
626 } 570 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698