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

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

Issue 2752113005: Let ImeAdapterAndroid have the same lifecycle as its Java peer (Closed)
Patch Set: fix tests Created 3 years, 8 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.Build; 8 import android.os.Build;
9 import android.os.ResultReceiver; 9 import android.os.ResultReceiver;
10 import android.os.SystemClock; 10 import android.os.SystemClock;
(...skipping 11 matching lines...) Expand all
22 22
23 import org.chromium.base.Log; 23 import org.chromium.base.Log;
24 import org.chromium.base.VisibleForTesting; 24 import org.chromium.base.VisibleForTesting;
25 import org.chromium.base.annotations.CalledByNative; 25 import org.chromium.base.annotations.CalledByNative;
26 import org.chromium.base.annotations.JNINamespace; 26 import org.chromium.base.annotations.JNINamespace;
27 import org.chromium.blink_public.web.WebInputEventModifier; 27 import org.chromium.blink_public.web.WebInputEventModifier;
28 import org.chromium.blink_public.web.WebInputEventType; 28 import org.chromium.blink_public.web.WebInputEventType;
29 import org.chromium.blink_public.web.WebTextInputMode; 29 import org.chromium.blink_public.web.WebTextInputMode;
30 import org.chromium.content.browser.RenderCoordinates; 30 import org.chromium.content.browser.RenderCoordinates;
31 import org.chromium.content.browser.picker.InputDialogContainer; 31 import org.chromium.content.browser.picker.InputDialogContainer;
32 import org.chromium.content_public.browser.WebContents;
32 import org.chromium.ui.base.ime.TextInputType; 33 import org.chromium.ui.base.ime.TextInputType;
33 34
34 /** 35 /**
35 * 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.
36 * ImeAdapter provides an interface in both ways native <-> java: 37 * ImeAdapter provides an interface in both ways native <-> java:
37 * 1. InputConnectionAdapter notifies native code of text composition state and 38 * 1. InputConnectionAdapter notifies native code of text composition state and
38 * dispatch key events from java -> WebKit. 39 * dispatch key events from java -> WebKit.
39 * 2. Native ImeAdapter notifies java side to clear composition text. 40 * 2. Native ImeAdapter notifies java side to clear composition text.
40 * 41 *
41 * The basic flow is: 42 * The basic flow is:
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 // Keep the current configuration to detect the change when onConfigurationC hanged() is called. 112 // Keep the current configuration to detect the change when onConfigurationC hanged() is called.
112 private Configuration mCurrentConfig; 113 private Configuration mCurrentConfig;
113 114
114 private int mLastSelectionStart; 115 private int mLastSelectionStart;
115 private int mLastSelectionEnd; 116 private int mLastSelectionEnd;
116 private String mLastText; 117 private String mLastText;
117 private int mLastCompositionStart; 118 private int mLastCompositionStart;
118 private int mLastCompositionEnd; 119 private int mLastCompositionEnd;
119 private boolean mRestartInputOnNextStateUpdate; 120 private boolean mRestartInputOnNextStateUpdate;
120 121
122 // True if ImeAdapter is connected to render process.
123 private boolean mIsConnected;
124
121 /** 125 /**
126 * @param webContents WebContents instance with which this ImeAdapter is ass ociated.
122 * @param wrapper InputMethodManagerWrapper that should receive all the call directed to 127 * @param wrapper InputMethodManagerWrapper that should receive all the call directed to
123 * InputMethodManager. 128 * InputMethodManager.
124 * @param embedder The view that is used for callbacks from ImeAdapter. 129 * @param embedder The view that is used for callbacks from ImeAdapter.
125 */ 130 */
126 public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embe dder) { 131 public ImeAdapter(WebContents webContents, InputMethodManagerWrapper wrapper ,
132 ImeAdapterDelegate embedder) {
127 mInputMethodManagerWrapper = wrapper; 133 mInputMethodManagerWrapper = wrapper;
128 mViewEmbedder = embedder; 134 mViewEmbedder = embedder;
129 // Deep copy newConfig so that we can notice the difference. 135 // Deep copy newConfig so that we can notice the difference.
130 mCurrentConfig = new Configuration( 136 mCurrentConfig = new Configuration(
131 mViewEmbedder.getAttachedView().getResources().getConfiguration( )); 137 mViewEmbedder.getAttachedView().getResources().getConfiguration( ));
132 // CursorAnchroInfo is supported only after L. 138 // CursorAnchroInfo is supported only after L.
133 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 139 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
134 mCursorAnchorInfoController = CursorAnchorInfoController.create(wrap per, 140 mCursorAnchorInfoController = CursorAnchorInfoController.create(wrap per,
135 new CursorAnchorInfoController.ComposingTextDelegate() { 141 new CursorAnchorInfoController.ComposingTextDelegate() {
136 @Override 142 @Override
(...skipping 13 matching lines...) Expand all
150 return mLastCompositionStart; 156 return mLastCompositionStart;
151 } 157 }
152 @Override 158 @Override
153 public int getComposingTextEnd() { 159 public int getComposingTextEnd() {
154 return mLastCompositionEnd; 160 return mLastCompositionEnd;
155 } 161 }
156 }); 162 });
157 } else { 163 } else {
158 mCursorAnchorInfoController = null; 164 mCursorAnchorInfoController = null;
159 } 165 }
166 mNativeImeAdapterAndroid = nativeInit(webContents);
160 } 167 }
161 168
162 private void createInputConnectionFactory() { 169 private void createInputConnectionFactory() {
163 if (mInputConnectionFactory != null) return; 170 if (mInputConnectionFactory != null) return;
164 mInputConnectionFactory = new ThreadedInputConnectionFactory(mInputMetho dManagerWrapper); 171 mInputConnectionFactory = new ThreadedInputConnectionFactory(mInputMetho dManagerWrapper);
165 } 172 }
166 173
174 // Tells if the ImeAdapter in valid state (i.e. not in destroyed state), and is
175 // connected to render process. The former check guards against the call via
176 // ThreadedInputConnection from Android framework after ImeAdapter.destroy() is called.
177 private boolean isValid() {
178 return mNativeImeAdapterAndroid != 0 && mIsConnected;
179 }
180
167 /** 181 /**
168 * @see View#onCreateInputConnection(EditorInfo) 182 * @see View#onCreateInputConnection(EditorInfo)
169 */ 183 */
170 public ChromiumBaseInputConnection onCreateInputConnection(EditorInfo outAtt rs) { 184 public ChromiumBaseInputConnection onCreateInputConnection(EditorInfo outAtt rs) {
171 // InputMethodService evaluates fullscreen mode even when the new input connection is 185 // InputMethodService evaluates fullscreen mode even when the new input connection is
172 // null. This makes sure IME doesn't enter fullscreen mode or open custo m UI. 186 // null. This makes sure IME doesn't enter fullscreen mode or open custo m UI.
173 outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME _FLAG_NO_EXTRACT_UI; 187 outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME _FLAG_NO_EXTRACT_UI;
174 // Without this line, some third-party IMEs will try to compose text eve n when 188 // Without this line, some third-party IMEs will try to compose text eve n when
175 // not on an editable node. Even when we return null here, key events ca n still go 189 // not on an editable node. Even when we return null here, key events ca n still go
176 // through ImeAdapter#dispatchKeyEvent(). 190 // through ImeAdapter#dispatchKeyEvent().
177 if (mTextInputType == TextInputType.NONE) { 191 if (mTextInputType == TextInputType.NONE) {
178 setInputConnection(null); 192 setInputConnection(null);
179 if (DEBUG_LOGS) Log.i(TAG, "onCreateInputConnection returns null."); 193 if (DEBUG_LOGS) Log.i(TAG, "onCreateInputConnection returns null.");
180 return null; 194 return null;
181 } 195 }
182 if (mInputConnectionFactory == null) return null; 196 if (mInputConnectionFactory == null) return null;
183 setInputConnection(mInputConnectionFactory.initializeAndGet(mViewEmbedde r.getAttachedView(), 197 setInputConnection(mInputConnectionFactory.initializeAndGet(mViewEmbedde r.getAttachedView(),
184 this, mTextInputType, mTextInputFlags, mTextInputMode, mLastSele ctionStart, 198 this, mTextInputType, mTextInputFlags, mTextInputMode, mLastSele ctionStart,
185 mLastSelectionEnd, outAttrs)); 199 mLastSelectionEnd, outAttrs));
186 if (DEBUG_LOGS) Log.i(TAG, "onCreateInputConnection: " + mInputConnectio n); 200 if (DEBUG_LOGS) Log.i(TAG, "onCreateInputConnection: " + mInputConnectio n);
187 201
188 if (mCursorAnchorInfoController != null) { 202 if (mCursorAnchorInfoController != null) {
189 mCursorAnchorInfoController.onRequestCursorUpdates( 203 mCursorAnchorInfoController.onRequestCursorUpdates(
190 false /* not an immediate request */, false /* disable monit oring */, 204 false /* not an immediate request */, false /* disable monit oring */,
191 mViewEmbedder.getAttachedView()); 205 mViewEmbedder.getAttachedView());
192 } 206 }
193 if (mNativeImeAdapterAndroid != 0) { 207 if (isValid()) {
194 nativeRequestCursorUpdate(mNativeImeAdapterAndroid, 208 nativeRequestCursorUpdate(mNativeImeAdapterAndroid,
195 false /* not an immediate request */, false /* disable monit oring */); 209 false /* not an immediate request */, false /* disable monit oring */);
196 } 210 }
197 return mInputConnection; 211 return mInputConnection;
198 } 212 }
199 213
200 private void setInputConnection(ChromiumBaseInputConnection inputConnection) { 214 private void setInputConnection(ChromiumBaseInputConnection inputConnection) {
201 if (mInputConnection == inputConnection) return; 215 if (mInputConnection == inputConnection) return;
202 // The previous input connection might be waiting for state update. 216 // The previous input connection might be waiting for state update.
203 if (mInputConnection != null) mInputConnection.unblockOnUiThread(); 217 if (mInputConnection != null) mInputConnection.unblockOnUiThread();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 } 332 }
319 333
320 if (mInputConnection == null) return; 334 if (mInputConnection == null) return;
321 boolean singleLine = mTextInputType != TextInputType.TEXT_AREA 335 boolean singleLine = mTextInputType != TextInputType.TEXT_AREA
322 && mTextInputType != TextInputType.CONTENT_EDITABLE; 336 && mTextInputType != TextInputType.CONTENT_EDITABLE;
323 mInputConnection.updateStateOnUiThread(text, selectionStart, selectionEn d, compositionStart, 337 mInputConnection.updateStateOnUiThread(text, selectionStart, selectionEn d, compositionStart,
324 compositionEnd, singleLine, replyToRequest); 338 compositionEnd, singleLine, replyToRequest);
325 } 339 }
326 340
327 /** 341 /**
328 * Attaches the imeAdapter to its native counterpart. This is needed to star t forwarding
329 * keyboard events to WebKit.
330 * @param nativeImeAdapter The pointer to the native ImeAdapter object.
331 */
332 public void attach(long nativeImeAdapter) {
333 if (DEBUG_LOGS) Log.i(TAG, "attach");
334 if (mNativeImeAdapterAndroid == nativeImeAdapter) return;
335 if (mNativeImeAdapterAndroid != 0) {
336 nativeResetImeAdapter(mNativeImeAdapterAndroid);
337 }
338 if (nativeImeAdapter != 0) {
339 nativeAttachImeAdapter(nativeImeAdapter);
340 }
341 mNativeImeAdapterAndroid = nativeImeAdapter;
342 if (nativeImeAdapter != 0) {
343 createInputConnectionFactory();
344 }
345 resetAndHideKeyboard();
346 }
347
348 /**
349 * Show soft keyboard only if it is the current keyboard configuration. 342 * Show soft keyboard only if it is the current keyboard configuration.
350 */ 343 */
351 private void showSoftKeyboard() { 344 private void showSoftKeyboard() {
352 if (DEBUG_LOGS) Log.i(TAG, "showSoftKeyboard"); 345 if (DEBUG_LOGS) Log.i(TAG, "showSoftKeyboard");
353 mInputMethodManagerWrapper.showSoftInput( 346 mInputMethodManagerWrapper.showSoftInput(
354 mViewEmbedder.getAttachedView(), 0, mViewEmbedder.getNewShowKeyb oardReceiver()); 347 mViewEmbedder.getAttachedView(), 0, mViewEmbedder.getNewShowKeyb oardReceiver());
355 if (mViewEmbedder.getAttachedView().getResources().getConfiguration().ke yboard 348 if (mViewEmbedder.getAttachedView().getResources().getConfiguration().ke yboard
356 != Configuration.KEYBOARD_NOKEYS) { 349 != Configuration.KEYBOARD_NOKEYS) {
357 mViewEmbedder.onKeyboardBoundsUnchanged(); 350 mViewEmbedder.onKeyboardBoundsUnchanged();
358 } 351 }
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 public void resetAndHideKeyboard() { 471 public void resetAndHideKeyboard() {
479 if (DEBUG_LOGS) Log.i(TAG, "resetAndHideKeyboard"); 472 if (DEBUG_LOGS) Log.i(TAG, "resetAndHideKeyboard");
480 mTextInputType = TextInputType.NONE; 473 mTextInputType = TextInputType.NONE;
481 mTextInputFlags = 0; 474 mTextInputFlags = 0;
482 mTextInputMode = WebTextInputMode.kDefault; 475 mTextInputMode = WebTextInputMode.kDefault;
483 mRestartInputOnNextStateUpdate = false; 476 mRestartInputOnNextStateUpdate = false;
484 // This will trigger unblocking if necessary. 477 // This will trigger unblocking if necessary.
485 hideKeyboard(); 478 hideKeyboard();
486 } 479 }
487 480
481 @CalledByNative
482 private void destroy() {
483 resetAndHideKeyboard();
484 mNativeImeAdapterAndroid = 0;
485 mIsConnected = false;
486 if (mCursorAnchorInfoController != null) {
487 mCursorAnchorInfoController.focusedNodeChanged(false);
488 }
489 }
490
488 /** 491 /**
489 * Update selection to input method manager. 492 * Update selection to input method manager.
490 * 493 *
491 * @param selectionStart The selection start. 494 * @param selectionStart The selection start.
492 * @param selectionEnd The selection end. 495 * @param selectionEnd The selection end.
493 * @param compositionStart The composition start. 496 * @param compositionStart The composition start.
494 * @param compositionEnd The composition end. 497 * @param compositionEnd The composition end.
495 */ 498 */
496 void updateSelection( 499 void updateSelection(
497 int selectionStart, int selectionEnd, int compositionStart, int comp ositionEnd) { 500 int selectionStart, int selectionEnd, int compositionStart, int comp ositionEnd) {
(...skipping 12 matching lines...) Expand all
510 513
511 /** 514 /**
512 * @see BaseInputConnection#performContextMenuAction(int) 515 * @see BaseInputConnection#performContextMenuAction(int)
513 */ 516 */
514 boolean performContextMenuAction(int id) { 517 boolean performContextMenuAction(int id) {
515 if (DEBUG_LOGS) Log.i(TAG, "performContextMenuAction: id [%d]", id); 518 if (DEBUG_LOGS) Log.i(TAG, "performContextMenuAction: id [%d]", id);
516 return mViewEmbedder.performContextMenuAction(id); 519 return mViewEmbedder.performContextMenuAction(id);
517 } 520 }
518 521
519 boolean performEditorAction(int actionCode) { 522 boolean performEditorAction(int actionCode) {
520 if (mNativeImeAdapterAndroid == 0) return false; 523 if (!isValid()) return false;
521 if (actionCode == EditorInfo.IME_ACTION_NEXT) { 524 if (actionCode == EditorInfo.IME_ACTION_NEXT) {
522 sendSyntheticKeyPress(KeyEvent.KEYCODE_TAB, 525 sendSyntheticKeyPress(KeyEvent.KEYCODE_TAB,
523 KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE 526 KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
524 | KeyEvent.FLAG_EDITOR_ACTION); 527 | KeyEvent.FLAG_EDITOR_ACTION);
525 } else { 528 } else {
526 sendSyntheticKeyPress(KeyEvent.KEYCODE_ENTER, 529 sendSyntheticKeyPress(KeyEvent.KEYCODE_ENTER,
527 KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE 530 KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
528 | KeyEvent.FLAG_EDITOR_ACTION); 531 | KeyEvent.FLAG_EDITOR_ACTION);
529 } 532 }
530 return true; 533 return true;
(...skipping 11 matching lines...) Expand all
542 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 545 KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
543 flags)); 546 flags));
544 sendKeyEvent(new KeyEvent(eventTime, eventTime, 547 sendKeyEvent(new KeyEvent(eventTime, eventTime,
545 KeyEvent.ACTION_UP, keyCode, 0, 0, 548 KeyEvent.ACTION_UP, keyCode, 0, 0,
546 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 549 KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
547 flags)); 550 flags));
548 } 551 }
549 552
550 boolean sendCompositionToNative( 553 boolean sendCompositionToNative(
551 CharSequence text, int newCursorPosition, boolean isCommit, int unic odeFromKeyEvent) { 554 CharSequence text, int newCursorPosition, boolean isCommit, int unic odeFromKeyEvent) {
552 if (mNativeImeAdapterAndroid == 0) return false; 555 if (!isValid()) return false;
553 556
554 // One WebView app detects Enter in JS by looking at KeyDown (http://crb ug/577967). 557 // One WebView app detects Enter in JS by looking at KeyDown (http://crb ug/577967).
555 if (TextUtils.equals(text, "\n")) { 558 if (TextUtils.equals(text, "\n")) {
556 sendSyntheticKeyPress(KeyEvent.KEYCODE_ENTER, 559 sendSyntheticKeyPress(KeyEvent.KEYCODE_ENTER,
557 KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE) ; 560 KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE) ;
558 return true; 561 return true;
559 } 562 }
560 563
561 mViewEmbedder.onImeEvent(); 564 mViewEmbedder.onImeEvent();
562 long timestampMs = SystemClock.uptimeMillis(); 565 long timestampMs = SystemClock.uptimeMillis();
563 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Raw KeyDown, 0, 566 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Raw KeyDown, 0,
564 timestampMs, COMPOSITION_KEY_CODE, 0, false, unicodeFromKeyEvent ); 567 timestampMs, COMPOSITION_KEY_CODE, 0, false, unicodeFromKeyEvent );
565 568
566 if (isCommit) { 569 if (isCommit) {
567 nativeCommitText(mNativeImeAdapterAndroid, text, text.toString(), ne wCursorPosition); 570 nativeCommitText(mNativeImeAdapterAndroid, text, text.toString(), ne wCursorPosition);
568 } else { 571 } else {
569 nativeSetComposingText( 572 nativeSetComposingText(
570 mNativeImeAdapterAndroid, text, text.toString(), newCursorPo sition); 573 mNativeImeAdapterAndroid, text, text.toString(), newCursorPo sition);
571 } 574 }
572 575
573 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Key Up, 0, timestampMs, 576 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Key Up, 0, timestampMs,
574 COMPOSITION_KEY_CODE, 0, false, unicodeFromKeyEvent); 577 COMPOSITION_KEY_CODE, 0, false, unicodeFromKeyEvent);
575 return true; 578 return true;
576 } 579 }
577 580
578 @VisibleForTesting 581 @VisibleForTesting
579 boolean finishComposingText() { 582 boolean finishComposingText() {
580 if (mNativeImeAdapterAndroid == 0) return false; 583 if (!isValid()) return false;
581 nativeFinishComposingText(mNativeImeAdapterAndroid); 584 nativeFinishComposingText(mNativeImeAdapterAndroid);
582 return true; 585 return true;
583 } 586 }
584 587
585 boolean sendKeyEvent(KeyEvent event) { 588 boolean sendKeyEvent(KeyEvent event) {
586 if (mNativeImeAdapterAndroid == 0) return false; 589 if (!isValid()) return false;
587 590
588 int action = event.getAction(); 591 int action = event.getAction();
589 int type; 592 int type;
590 if (action == KeyEvent.ACTION_DOWN) { 593 if (action == KeyEvent.ACTION_DOWN) {
591 type = WebInputEventType.KeyDown; 594 type = WebInputEventType.KeyDown;
592 } else if (action == KeyEvent.ACTION_UP) { 595 } else if (action == KeyEvent.ACTION_UP) {
593 type = WebInputEventType.KeyUp; 596 type = WebInputEventType.KeyUp;
594 } else { 597 } else {
595 // In theory, KeyEvent.ACTION_MULTIPLE is a valid value, but in prac tice 598 // In theory, KeyEvent.ACTION_MULTIPLE is a valid value, but in prac tice
596 // this seems to have been quietly deprecated and we've never observ ed 599 // this seems to have been quietly deprecated and we've never observ ed
(...skipping 11 matching lines...) Expand all
608 /** 611 /**
609 * Send a request to the native counterpart to delete a given range of chara cters. 612 * Send a request to the native counterpart to delete a given range of chara cters.
610 * @param beforeLength Number of characters to extend the selection by befor e the existing 613 * @param beforeLength Number of characters to extend the selection by befor e the existing
611 * selection. 614 * selection.
612 * @param afterLength Number of characters to extend the selection by after the existing 615 * @param afterLength Number of characters to extend the selection by after the existing
613 * selection. 616 * selection.
614 * @return Whether the native counterpart of ImeAdapter received the call. 617 * @return Whether the native counterpart of ImeAdapter received the call.
615 */ 618 */
616 boolean deleteSurroundingText(int beforeLength, int afterLength) { 619 boolean deleteSurroundingText(int beforeLength, int afterLength) {
617 mViewEmbedder.onImeEvent(); 620 mViewEmbedder.onImeEvent();
618 if (mNativeImeAdapterAndroid == 0) return false; 621 if (!isValid()) return false;
619 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Raw KeyDown, 0, 622 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Raw KeyDown, 0,
620 SystemClock.uptimeMillis(), COMPOSITION_KEY_CODE, 0, false, 0); 623 SystemClock.uptimeMillis(), COMPOSITION_KEY_CODE, 0, false, 0);
621 nativeDeleteSurroundingText(mNativeImeAdapterAndroid, beforeLength, afte rLength); 624 nativeDeleteSurroundingText(mNativeImeAdapterAndroid, beforeLength, afte rLength);
622 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Key Up, 0, 625 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Key Up, 0,
623 SystemClock.uptimeMillis(), COMPOSITION_KEY_CODE, 0, false, 0); 626 SystemClock.uptimeMillis(), COMPOSITION_KEY_CODE, 0, false, 0);
624 return true; 627 return true;
625 } 628 }
626 629
627 /** 630 /**
628 * Send a request to the native counterpart to delete a given range of chara cters. 631 * Send a request to the native counterpart to delete a given range of chara cters.
629 * @param beforeLength Number of code points to extend the selection by befo re the existing 632 * @param beforeLength Number of code points to extend the selection by befo re the existing
630 * selection. 633 * selection.
631 * @param afterLength Number of code points to extend the selection by after the existing 634 * @param afterLength Number of code points to extend the selection by after the existing
632 * selection. 635 * selection.
633 * @return Whether the native counterpart of ImeAdapter received the call. 636 * @return Whether the native counterpart of ImeAdapter received the call.
634 */ 637 */
635 boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) { 638 boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
636 mViewEmbedder.onImeEvent(); 639 mViewEmbedder.onImeEvent();
637 if (mNativeImeAdapterAndroid == 0) return false; 640 if (!isValid()) return false;
638 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Raw KeyDown, 0, 641 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Raw KeyDown, 0,
639 SystemClock.uptimeMillis(), COMPOSITION_KEY_CODE, 0, false, 0); 642 SystemClock.uptimeMillis(), COMPOSITION_KEY_CODE, 0, false, 0);
640 nativeDeleteSurroundingTextInCodePoints( 643 nativeDeleteSurroundingTextInCodePoints(
641 mNativeImeAdapterAndroid, beforeLength, afterLength); 644 mNativeImeAdapterAndroid, beforeLength, afterLength);
642 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Key Up, 0, 645 nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.Key Up, 0,
643 SystemClock.uptimeMillis(), COMPOSITION_KEY_CODE, 0, false, 0); 646 SystemClock.uptimeMillis(), COMPOSITION_KEY_CODE, 0, false, 0);
644 return true; 647 return true;
645 } 648 }
646 649
647 /** 650 /**
648 * Send a request to the native counterpart to set the selection to given ra nge. 651 * Send a request to the native counterpart to set the selection to given ra nge.
649 * @param start Selection start index. 652 * @param start Selection start index.
650 * @param end Selection end index. 653 * @param end Selection end index.
651 * @return Whether the native counterpart of ImeAdapter received the call. 654 * @return Whether the native counterpart of ImeAdapter received the call.
652 */ 655 */
653 boolean setEditableSelectionOffsets(int start, int end) { 656 boolean setEditableSelectionOffsets(int start, int end) {
654 if (mNativeImeAdapterAndroid == 0) return false; 657 if (!isValid()) return false;
655 nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end); 658 nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end);
656 return true; 659 return true;
657 } 660 }
658 661
659 /** 662 /**
660 * Send a request to the native counterpart to set composing region to given indices. 663 * Send a request to the native counterpart to set composing region to given indices.
661 * @param start The start of the composition. 664 * @param start The start of the composition.
662 * @param end The end of the composition. 665 * @param end The end of the composition.
663 * @return Whether the native counterpart of ImeAdapter received the call. 666 * @return Whether the native counterpart of ImeAdapter received the call.
664 */ 667 */
665 boolean setComposingRegion(int start, int end) { 668 boolean setComposingRegion(int start, int end) {
666 if (mNativeImeAdapterAndroid == 0) return false; 669 if (!isValid()) return false;
667 if (start <= end) { 670 if (start <= end) {
668 nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end); 671 nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end);
669 } else { 672 } else {
670 nativeSetComposingRegion(mNativeImeAdapterAndroid, end, start); 673 nativeSetComposingRegion(mNativeImeAdapterAndroid, end, start);
671 } 674 }
672 return true; 675 return true;
673 } 676 }
674 677
675 @CalledByNative 678 @CalledByNative
676 private void focusedNodeChanged(boolean isEditable) { 679 private void focusedNodeChanged(boolean isEditable) {
677 if (DEBUG_LOGS) Log.i(TAG, "focusedNodeChanged: isEditable [%b]", isEdit able); 680 if (DEBUG_LOGS) Log.i(TAG, "focusedNodeChanged: isEditable [%b]", isEdit able);
678 681
679 // Update controller before the connection is restarted. 682 // Update controller before the connection is restarted.
680 if (mCursorAnchorInfoController != null) { 683 if (mCursorAnchorInfoController != null) {
681 mCursorAnchorInfoController.focusedNodeChanged(isEditable); 684 mCursorAnchorInfoController.focusedNodeChanged(isEditable);
682 } 685 }
683 686
684 if (mTextInputType != TextInputType.NONE && mInputConnection != null && isEditable) { 687 if (mTextInputType != TextInputType.NONE && mInputConnection != null && isEditable) {
685 mRestartInputOnNextStateUpdate = true; 688 mRestartInputOnNextStateUpdate = true;
686 } 689 }
687 } 690 }
688 691
689 /** 692 /**
690 * Send a request to the native counterpart to give the latest text input st ate update. 693 * Send a request to the native counterpart to give the latest text input st ate update.
691 */ 694 */
692 boolean requestTextInputStateUpdate() { 695 boolean requestTextInputStateUpdate() {
693 if (mNativeImeAdapterAndroid == 0) return false; 696 if (!isValid()) return false;
694 // You won't get state update anyways. 697 // You won't get state update anyways.
695 if (mInputConnection == null) return false; 698 if (mInputConnection == null) return false;
696 return nativeRequestTextInputStateUpdate(mNativeImeAdapterAndroid); 699 return nativeRequestTextInputStateUpdate(mNativeImeAdapterAndroid);
697 } 700 }
698 701
699 /** 702 /**
700 * Notified when IME requested Chrome to change the cursor update mode. 703 * Notified when IME requested Chrome to change the cursor update mode.
701 */ 704 */
702 public boolean onRequestCursorUpdates(int cursorUpdateMode) { 705 public boolean onRequestCursorUpdates(int cursorUpdateMode) {
703 final boolean immediateRequest = 706 final boolean immediateRequest =
704 (cursorUpdateMode & InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0; 707 (cursorUpdateMode & InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
705 final boolean monitorRequest = 708 final boolean monitorRequest =
706 (cursorUpdateMode & InputConnection.CURSOR_UPDATE_MONITOR) != 0; 709 (cursorUpdateMode & InputConnection.CURSOR_UPDATE_MONITOR) != 0;
707 710
708 if (mNativeImeAdapterAndroid != 0) { 711 if (isValid()) {
709 nativeRequestCursorUpdate(mNativeImeAdapterAndroid, immediateRequest , monitorRequest); 712 nativeRequestCursorUpdate(mNativeImeAdapterAndroid, immediateRequest , monitorRequest);
710 } 713 }
711 if (mCursorAnchorInfoController == null) return false; 714 if (mCursorAnchorInfoController == null) return false;
712 return mCursorAnchorInfoController.onRequestCursorUpdates(immediateReque st, monitorRequest, 715 return mCursorAnchorInfoController.onRequestCursorUpdates(immediateReque st, monitorRequest,
713 mViewEmbedder.getAttachedView()); 716 mViewEmbedder.getAttachedView());
714 } 717 }
715 718
716 /** 719 /**
717 * Notified when a frame has been produced by the renderer and all the assoc iated metadata. 720 * Notified when a frame has been produced by the renderer and all the assoc iated metadata.
718 * @param renderCoordinates coordinate information to convert CSS (document) coordinates to 721 * @param renderCoordinates coordinate information to convert CSS (document) coordinates to
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 } 766 }
764 767
765 @CalledByNative 768 @CalledByNative
766 private void setCharacterBounds(float[] characterBounds) { 769 private void setCharacterBounds(float[] characterBounds) {
767 if (mCursorAnchorInfoController == null) return; 770 if (mCursorAnchorInfoController == null) return;
768 mCursorAnchorInfoController.setCompositionCharacterBounds(characterBound s, 771 mCursorAnchorInfoController.setCompositionCharacterBounds(characterBound s,
769 mViewEmbedder.getAttachedView()); 772 mViewEmbedder.getAttachedView());
770 } 773 }
771 774
772 @CalledByNative 775 @CalledByNative
773 private void detach() { 776 private void onConnectedToRenderProcess() {
774 if (DEBUG_LOGS) Log.i(TAG, "detach"); 777 if (DEBUG_LOGS) Log.i(TAG, "onConnectedToRenderProcess");
775 mNativeImeAdapterAndroid = 0; 778 mIsConnected = true;
776 if (mCursorAnchorInfoController != null) { 779 createInputConnectionFactory();
777 mCursorAnchorInfoController.focusedNodeChanged(false); 780 resetAndHideKeyboard();
778 }
779 } 781 }
780 782
783 private native long nativeInit(WebContents webContents);
781 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE vent event, 784 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE vent event,
782 int type, int modifiers, long timestampMs, int keyCode, int scanCode , 785 int type, int modifiers, long timestampMs, int keyCode, int scanCode ,
783 boolean isSystemKey, int unicodeChar); 786 boolean isSystemKey, int unicodeChar);
784 private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end); 787 private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end);
785 private static native void nativeAppendBackgroundColorSpan(long underlinePtr , int start, 788 private static native void nativeAppendBackgroundColorSpan(long underlinePtr , int start,
786 int end, int backgroundColor); 789 int end, int backgroundColor);
787 private native void nativeSetComposingText(long nativeImeAdapterAndroid, Cha rSequence text, 790 private native void nativeSetComposingText(long nativeImeAdapterAndroid, Cha rSequence text,
788 String textStr, int newCursorPosition); 791 String textStr, int newCursorPosition);
789 private native void nativeCommitText( 792 private native void nativeCommitText(
790 long nativeImeAdapterAndroid, CharSequence text, String textStr, int newCursorPosition); 793 long nativeImeAdapterAndroid, CharSequence text, String textStr, int newCursorPosition);
791 private native void nativeFinishComposingText(long nativeImeAdapterAndroid); 794 private native void nativeFinishComposingText(long nativeImeAdapterAndroid);
792 private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid);
793 private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterA ndroid, 795 private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterA ndroid,
794 int start, int end); 796 int start, int end);
795 private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, i nt start, int end); 797 private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, i nt start, int end);
796 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid , 798 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid ,
797 int before, int after); 799 int before, int after);
798 private native void nativeDeleteSurroundingTextInCodePoints( 800 private native void nativeDeleteSurroundingTextInCodePoints(
799 long nativeImeAdapterAndroid, int before, int after); 801 long nativeImeAdapterAndroid, int before, int after);
800 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid);
801 private native boolean nativeRequestTextInputStateUpdate(long nativeImeAdapt erAndroid); 802 private native boolean nativeRequestTextInputStateUpdate(long nativeImeAdapt erAndroid);
802 private native void nativeRequestCursorUpdate(long nativeImeAdapterAndroid, 803 private native void nativeRequestCursorUpdate(long nativeImeAdapterAndroid,
803 boolean immediateRequest, boolean monitorRequest); 804 boolean immediateRequest, boolean monitorRequest);
804 } 805 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698