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

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: Created 5 years, 4 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.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;
12 import android.text.SpannableString; 11 import android.text.SpannableString;
13 import android.text.style.BackgroundColorSpan; 12 import android.text.style.BackgroundColorSpan;
14 import android.text.style.CharacterStyle; 13 import android.text.style.CharacterStyle;
15 import android.text.style.UnderlineSpan; 14 import android.text.style.UnderlineSpan;
16 import android.view.KeyCharacterMap; 15 import android.view.KeyCharacterMap;
17 import android.view.KeyEvent; 16 import android.view.KeyEvent;
18 import android.view.View; 17 import android.view.View;
19 import android.view.inputmethod.EditorInfo; 18 import android.view.inputmethod.BaseInputConnection;
20 19
21 import org.chromium.base.VisibleForTesting; 20 import org.chromium.base.VisibleForTesting;
22 import org.chromium.base.annotations.CalledByNative; 21 import org.chromium.base.annotations.CalledByNative;
23 import org.chromium.base.annotations.JNINamespace; 22 import org.chromium.base.annotations.JNINamespace;
24 import org.chromium.blink_public.web.WebInputEventModifier; 23 import org.chromium.blink_public.web.WebInputEventModifier;
25 import org.chromium.blink_public.web.WebInputEventType; 24 import org.chromium.blink_public.web.WebInputEventType;
26 import org.chromium.blink_public.web.WebTextInputFlags; 25 import org.chromium.blink_public.web.WebTextInputFlags;
27 import org.chromium.ui.base.ime.TextInputType; 26 import org.chromium.ui.base.ime.TextInputType;
28 import org.chromium.ui.picker.InputDialogContainer; 27 import org.chromium.ui.picker.InputDialogContainer;
29 28
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 public void run() { 93 public void run() {
95 dismissInput(true); 94 dismissInput(true);
96 } 95 }
97 }; 96 };
98 97
99 static char[] sSingleCharArray = new char[1]; 98 static char[] sSingleCharArray = new char[1];
100 static KeyCharacterMap sKeyCharacterMap; 99 static KeyCharacterMap sKeyCharacterMap;
101 100
102 private long mNativeImeAdapterAndroid; 101 private long mNativeImeAdapterAndroid;
103 private InputMethodManagerWrapper mInputMethodManagerWrapper; 102 private InputMethodManagerWrapper mInputMethodManagerWrapper;
104 private AdapterInputConnection mInputConnection; 103 public ChromiumBaseInputConnection mInputConnection;
105 private final ImeAdapterDelegate mViewEmbedder; 104 private final ImeAdapterDelegate mViewEmbedder;
106 private final Handler mHandler; 105 private final Handler mHandler;
107 private int mTextInputType; 106 private int mTextInputType;
108 private int mTextInputFlags; 107 private int mTextInputFlags;
109 private String mLastComposeText; 108 private String mLastComposeText;
110 109
111 @VisibleForTesting 110 @VisibleForTesting
112 int mLastSyntheticKeyCode; 111 int mLastSyntheticKeyCode;
113 112
114 @VisibleForTesting 113 @VisibleForTesting
115 boolean mIsShowWithoutHideOutstanding = false; 114 boolean mIsShowWithoutHideOutstanding = false;
116 115
117 /** 116 /**
118 * @param wrapper InputMethodManagerWrapper that should receive all the call directed to 117 * @param wrapper InputMethodManagerWrapper that should receive all the call directed to
119 * InputMethodManager. 118 * InputMethodManager.
120 * @param embedder The view that is used for callbacks from ImeAdapter. 119 * @param embedder The view that is used for callbacks from ImeAdapter.
121 */ 120 */
122 public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embe dder) { 121 public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embe dder) {
123 mInputMethodManagerWrapper = wrapper; 122 mInputMethodManagerWrapper = wrapper;
124 mViewEmbedder = embedder; 123 mViewEmbedder = embedder;
125 mHandler = new Handler(); 124 mHandler = new Handler();
126 } 125 }
127 126
128 /** 127 /**
129 * Default factory for AdapterInputConnection classes.
130 */
131 public static class AdapterInputConnectionFactory {
132 public AdapterInputConnection get(View view, ImeAdapter imeAdapter,
133 Editable editable, EditorInfo outAttrs) {
134 return new AdapterInputConnection(view, imeAdapter, editable, outAtt rs);
135 }
136 }
137
138 /**
139 * Overrides the InputMethodManagerWrapper that ImeAdapter uses to make call s to 128 * Overrides the InputMethodManagerWrapper that ImeAdapter uses to make call s to
140 * InputMethodManager. 129 * InputMethodManager.
141 * @param immw InputMethodManagerWrapper that should be used to call InputMe thodManager. 130 * @param immw InputMethodManagerWrapper that should be used to call InputMe thodManager.
142 */ 131 */
143 @VisibleForTesting 132 @VisibleForTesting
144 public void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) { 133 public void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) {
145 mInputMethodManagerWrapper = immw; 134 mInputMethodManagerWrapper = immw;
146 } 135 }
147 136
148 /** 137 /**
149 * Should be only used by AdapterInputConnection. 138 * Should be only used by AdapterInputConnection.
150 * @return InputMethodManagerWrapper that should receive all the calls direc ted to 139 * @return InputMethodManagerWrapper that should receive all the calls direc ted to
151 * InputMethodManager. 140 * InputMethodManager.
152 */ 141 */
153 InputMethodManagerWrapper getInputMethodManagerWrapper() { 142 InputMethodManagerWrapper getInputMethodManagerWrapper() {
154 return mInputMethodManagerWrapper; 143 return mInputMethodManagerWrapper;
155 } 144 }
156 145
157 /** 146 /**
158 * Set the current active InputConnection when a new InputConnection is cons tructed. 147 * Set the current active InputConnection when a new InputConnection is cons tructed.
159 * @param inputConnection The input connection that is currently used with I ME. 148 * @param inputConnection The input connection that is currently used with I ME.
160 */ 149 */
161 void setInputConnection(AdapterInputConnection inputConnection) { 150 void setInputConnection(ChromiumBaseInputConnection inputConnection) {
162 mInputConnection = inputConnection; 151 mInputConnection = inputConnection;
163 mLastComposeText = null; 152 mLastComposeText = null;
164 } 153 }
165 154
166 /** 155 /**
167 * Should be used only by AdapterInputConnection. 156 * Should be used only by AdapterInputConnection.
168 * @return The input type of currently focused element. 157 * @return The input type of currently focused element.
169 */ 158 */
170 int getTextInputType() { 159 int getTextInputType() {
171 return mTextInputType; 160 return mTextInputType;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 } 203 }
215 204
216 if (mNativeImeAdapterAndroid != nativeImeAdapter || mTextInputType != te xtInputType) { 205 if (mNativeImeAdapterAndroid != nativeImeAdapter || mTextInputType != te xtInputType) {
217 // We have to attach immediately, even if we're going to delay the d ismissing of 206 // We have to attach immediately, even if we're going to delay the d ismissing of
218 // currently visible keyboard because otherwise we have a race condi tion: If the 207 // currently visible keyboard because otherwise we have a race condi tion: If the
219 // native IME adapter gets destructed before the delayed-dismiss fir es, we'll access 208 // native IME adapter gets destructed before the delayed-dismiss fir es, we'll access
220 // an object that has been already released. http://crbug.com/44728 7 209 // an object that has been already released. http://crbug.com/44728 7
221 attach(nativeImeAdapter, textInputType, textInputFlags, true); 210 attach(nativeImeAdapter, textInputType, textInputFlags, true);
222 211
223 if (mTextInputType != TextInputType.NONE) { 212 if (mTextInputType != TextInputType.NONE) {
224 mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttache dView()); 213 if (mInputConnection != null) mInputConnection.restartInput();
225 if (showIfNeeded) { 214 if (showIfNeeded) {
226 showKeyboard(); 215 showKeyboard();
227 } 216 }
228 } 217 }
229 } else if (hasInputType() && showIfNeeded) { 218 } else if (hasInputType() && showIfNeeded) {
230 showKeyboard(); 219 showKeyboard();
231 } 220 }
232 } 221 }
233 222
234 private void attach(long nativeImeAdapter, int textInputType, int textInputF lags, 223 private void attach(long nativeImeAdapter, int textInputType, int textInputF lags,
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 // The content has shrunk in length: assume that backspace was pressed. 367 // The content has shrunk in length: assume that backspace was pressed.
379 if (oldtext.length() > newtext.length() && oldtext.startsWith(newtext)) { 368 if (oldtext.length() > newtext.length() && oldtext.startsWith(newtext)) {
380 return new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL); 369 return new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL);
381 } 370 }
382 371
383 // The content is unchanged or has undergone a complex change (i.e. not a simple tail 372 // The content is unchanged or has undergone a complex change (i.e. not a simple tail
384 // modification) so return an unknown key-code. 373 // modification) so return an unknown key-code.
385 return null; 374 return null;
386 } 375 }
387 376
388 void sendKeyEventWithKeyCode(int keyCode, int flags) { 377 boolean sendKeyEventWithKeyCode(int keyCode, int flags) {
389 long eventTime = SystemClock.uptimeMillis(); 378 long eventTime = SystemClock.uptimeMillis();
390 mLastSyntheticKeyCode = keyCode; 379 mLastSyntheticKeyCode = keyCode;
391 translateAndSendNativeEvents(new KeyEvent(eventTime, eventTime, 380 boolean result = translateAndSendNativeEvents(new KeyEvent(eventTime, ev entTime,
392 KeyEvent.ACTION_DOWN, keyCode, 0, 0, 381 KeyEvent.ACTION_DOWN, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEY BOARD, 0, flags));
393 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 382 if (!result) return false;
394 flags)); 383 result = translateAndSendNativeEvents(new KeyEvent(SystemClock.uptimeMil lis(), eventTime,
395 translateAndSendNativeEvents(new KeyEvent(SystemClock.uptimeMillis(), ev entTime, 384 KeyEvent.ACTION_UP, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBO ARD, 0, flags));
396 KeyEvent.ACTION_UP, keyCode, 0, 0, 385 return result;
397 KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
398 flags));
399 } 386 }
400 387
401 // Calls from Java to C++ 388 // Calls from Java to C++
402 // TODO: Add performance tracing to more complicated functions. 389 // TODO: Add performance tracing to more complicated functions.
403 390
404 boolean checkCompositionQueueAndCallNative(CharSequence text, int newCursorP osition, 391 boolean checkCompositionQueueAndCallNative(CharSequence text, int newCursorP osition,
405 boolean isCommit) { 392 boolean isCommit) {
406 if (mNativeImeAdapterAndroid == 0) return false; 393 if (mNativeImeAdapterAndroid == 0) return false;
407 mViewEmbedder.onImeEvent(); 394 mViewEmbedder.onImeEvent();
408 395
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 } 462 }
476 463
477 mLastSyntheticKeyCode = keyCode; 464 mLastSyntheticKeyCode = keyCode;
478 } 465 }
479 466
480 mLastComposeText = textStr; 467 mLastComposeText = textStr;
481 return true; 468 return true;
482 } 469 }
483 470
484 @VisibleForTesting 471 @VisibleForTesting
485 protected void finishComposingText() { 472 protected boolean finishComposingText() {
486 mLastComposeText = null; 473 mLastComposeText = null;
487 if (mNativeImeAdapterAndroid == 0) return; 474 if (mNativeImeAdapterAndroid == 0) return false;
488 nativeFinishComposingText(mNativeImeAdapterAndroid); 475 nativeFinishComposingText(mNativeImeAdapterAndroid);
476 return true;
489 } 477 }
490 478
491 boolean translateAndSendNativeEvents(KeyEvent event) { 479 boolean translateAndSendNativeEvents(KeyEvent event) {
492 if (mNativeImeAdapterAndroid == 0) return false; 480 if (mNativeImeAdapterAndroid == 0) return false;
493 481
494 int action = event.getAction(); 482 int action = event.getAction();
495 if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_UP) { 483 if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_UP) {
496 // action == KeyEvent.ACTION_MULTIPLE 484 // action == KeyEvent.ACTION_MULTIPLE
497 // TODO(bulach): confirm the actual behavior. Apparently: 485 // TODO(bulach): confirm the actual behavior. Apparently:
498 // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a 486 // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 * @param end The end of the composition. 541 * @param end The end of the composition.
554 * @return Whether the native counterpart of ImeAdapter received the call. 542 * @return Whether the native counterpart of ImeAdapter received the call.
555 */ 543 */
556 boolean setComposingRegion(CharSequence text, int start, int end) { 544 boolean setComposingRegion(CharSequence text, int start, int end) {
557 if (mNativeImeAdapterAndroid == 0) return false; 545 if (mNativeImeAdapterAndroid == 0) return false;
558 nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end); 546 nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end);
559 mLastComposeText = text != null ? text.toString() : null; 547 mLastComposeText = text != null ? text.toString() : null;
560 return true; 548 return true;
561 } 549 }
562 550
563 // Calls from C++ to Java 551 /**
552 * Send a request to the native counterpart to give the latest text input st ate update.
553 */
554 boolean requestTextInputStateUpdate() {
555 if (mNativeImeAdapterAndroid == 0) return false;
556 nativeRequestTextInputStateUpdate(mNativeImeAdapterAndroid);
557 return true;
558 }
564 559
565 @CalledByNative 560 @CalledByNative
566 private void focusedNodeChanged(boolean isEditable) { 561 private void focusedNodeChanged(boolean isEditable) {
567 if (mInputConnection != null && isEditable) mInputConnection.restartInpu t(); 562 if (mInputConnection != null && isEditable) {
563 mInputConnection.restartInput();
564 }
568 } 565 }
569 566
570 @CalledByNative 567 @CalledByNative
571 private void populateUnderlinesFromSpans(CharSequence text, long underlines) { 568 private void populateUnderlinesFromSpans(CharSequence text, long underlines) {
572 if (!(text instanceof SpannableString)) return; 569 if (!(text instanceof SpannableString)) return;
573 570
574 SpannableString spannableString = ((SpannableString) text); 571 SpannableString spannableString = ((SpannableString) text);
575 CharacterStyle spans[] = 572 CharacterStyle spans[] =
576 spannableString.getSpans(0, text.length(), CharacterStyle.class) ; 573 spannableString.getSpans(0, text.length(), CharacterStyle.class) ;
577 for (CharacterStyle span : spans) { 574 for (CharacterStyle span : spans) {
578 if (span instanceof BackgroundColorSpan) { 575 if (span instanceof BackgroundColorSpan) {
579 nativeAppendBackgroundColorSpan(underlines, spannableString.getS panStart(span), 576 nativeAppendBackgroundColorSpan(underlines, spannableString.getS panStart(span),
580 spannableString.getSpanEnd(span), 577 spannableString.getSpanEnd(span),
581 ((BackgroundColorSpan) span).getBackgroundColor()); 578 ((BackgroundColorSpan) span).getBackgroundColor());
582 } else if (span instanceof UnderlineSpan) { 579 } else if (span instanceof UnderlineSpan) {
583 nativeAppendUnderlineSpan(underlines, spannableString.getSpanSta rt(span), 580 nativeAppendUnderlineSpan(underlines, spannableString.getSpanSta rt(span),
584 spannableString.getSpanEnd(span)); 581 spannableString.getSpanEnd(span));
585 } 582 }
586 } 583 }
587 } 584 }
588 585
589 @CalledByNative 586 @CalledByNative
590 private void cancelComposition() { 587 private void cancelComposition() {
591 if (mInputConnection != null) mInputConnection.restartInput(); 588 mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView()) ;
592 mLastComposeText = null; 589 mLastComposeText = null;
593 } 590 }
594 591
595 @CalledByNative 592 @CalledByNative
596 void detach() { 593 void detach() {
597 mHandler.removeCallbacks(mDismissInputRunnable); 594 mHandler.removeCallbacks(mDismissInputRunnable);
598 mNativeImeAdapterAndroid = 0; 595 mNativeImeAdapterAndroid = 0;
599 mTextInputType = 0; 596 mTextInputType = 0;
600 } 597 }
601 598
602 private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndr oid, 599 private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndr oid,
603 int eventType, long timestampMs, int keyCode, int modifiers, int uni codeChar); 600 int eventType, long timestampMs, int keyCode, int modifiers, int uni codeChar);
604
605 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE vent event, 601 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE vent event,
606 int action, int modifiers, long timestampMs, int keyCode, boolean is SystemKey, 602 int action, int modifiers, long timestampMs, int keyCode, boolean is SystemKey,
607 int unicodeChar); 603 int unicodeChar);
608
609 private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end); 604 private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end);
610
611 private static native void nativeAppendBackgroundColorSpan(long underlinePtr , int start, 605 private static native void nativeAppendBackgroundColorSpan(long underlinePtr , int start,
612 int end, int backgroundColor); 606 int end, int backgroundColor);
613
614 private native void nativeSetComposingText(long nativeImeAdapterAndroid, Cha rSequence text, 607 private native void nativeSetComposingText(long nativeImeAdapterAndroid, Cha rSequence text,
615 String textStr, int newCursorPosition); 608 String textStr, int newCursorPosition);
616
617 private native void nativeCommitText(long nativeImeAdapterAndroid, String te xtStr); 609 private native void nativeCommitText(long nativeImeAdapterAndroid, String te xtStr);
618
619 private native void nativeFinishComposingText(long nativeImeAdapterAndroid); 610 private native void nativeFinishComposingText(long nativeImeAdapterAndroid);
620
621 private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid); 611 private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid);
622
623 private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterA ndroid, 612 private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterA ndroid,
624 int start, int end); 613 int start, int end);
625
626 private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, i nt start, int end); 614 private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, i nt start, int end);
627
628 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid , 615 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid ,
629 int before, int after); 616 int before, int after);
630
631 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); 617 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid);
618 private native void nativeRequestTextInputStateUpdate(long nativeImeAdapterA ndroid);
632 } 619 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698