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.os.Handler; | 7 import android.os.Handler; |
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; | 10 import android.text.Editable; |
11 import android.text.SpannableString; | |
12 import android.text.style.BackgroundColorSpan; | |
13 import android.text.style.CharacterStyle; | |
14 import android.text.style.UnderlineSpan; | |
11 import android.view.KeyCharacterMap; | 15 import android.view.KeyCharacterMap; |
12 import android.view.KeyEvent; | 16 import android.view.KeyEvent; |
13 import android.view.View; | 17 import android.view.View; |
14 import android.view.inputmethod.EditorInfo; | 18 import android.view.inputmethod.EditorInfo; |
15 | 19 |
16 import com.google.common.annotations.VisibleForTesting; | 20 import com.google.common.annotations.VisibleForTesting; |
17 | 21 |
22 import java.lang.CharSequence; | |
23 | |
18 import org.chromium.base.CalledByNative; | 24 import org.chromium.base.CalledByNative; |
19 import org.chromium.base.JNINamespace; | 25 import org.chromium.base.JNINamespace; |
20 | 26 |
21 /** | 27 /** |
22 * Adapts and plumbs android IME service onto the chrome text input API. | 28 * Adapts and plumbs android IME service onto the chrome text input API. |
23 * ImeAdapter provides an interface in both ways native <-> java: | 29 * ImeAdapter provides an interface in both ways native <-> java: |
24 * 1. InputConnectionAdapter notifies native code of text composition state and | 30 * 1. InputConnectionAdapter notifies native code of text composition state and |
25 * dispatch key events from java -> WebKit. | 31 * dispatch key events from java -> WebKit. |
26 * 2. Native ImeAdapter notifies java side to clear composition text. | 32 * 2. Native ImeAdapter notifies java side to clear composition text. |
27 * | 33 * |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
321 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, | 327 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, |
322 flags)); | 328 flags)); |
323 translateAndSendNativeEvents(new KeyEvent(SystemClock.uptimeMillis(), ev entTime, | 329 translateAndSendNativeEvents(new KeyEvent(SystemClock.uptimeMillis(), ev entTime, |
324 KeyEvent.ACTION_UP, keyCode, 0, 0, | 330 KeyEvent.ACTION_UP, keyCode, 0, 0, |
325 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, | 331 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, |
326 flags)); | 332 flags)); |
327 } | 333 } |
328 | 334 |
329 // Calls from Java to C++ | 335 // Calls from Java to C++ |
330 | 336 |
331 boolean checkCompositionQueueAndCallNative(String text, int newCursorPositio n, | 337 boolean checkCompositionQueueAndCallNative(CharSequence text, int newCursorP osition, |
332 boolean isCommit) { | 338 boolean isCommit) { |
333 if (mNativeImeAdapterAndroid == 0) return false; | 339 if (mNativeImeAdapterAndroid == 0) return false; |
340 String textStr = text.toString(); | |
334 | 341 |
335 // Committing an empty string finishes the current composition. | 342 // Committing an empty string finishes the current composition. |
336 boolean isFinish = text.isEmpty(); | 343 boolean isFinish = textStr.isEmpty(); |
337 mViewEmbedder.onImeEvent(isFinish); | 344 mViewEmbedder.onImeEvent(isFinish); |
338 int keyCode = shouldSendKeyEventWithKeyCode(text); | 345 int keyCode = shouldSendKeyEventWithKeyCode(textStr); |
339 long timeStampMs = SystemClock.uptimeMillis(); | 346 long timeStampMs = SystemClock.uptimeMillis(); |
340 | 347 |
341 if (keyCode != COMPOSITION_KEY_CODE) { | 348 if (keyCode != COMPOSITION_KEY_CODE) { |
342 sendKeyEventWithKeyCode(keyCode, | 349 sendKeyEventWithKeyCode(keyCode, |
343 KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE) ; | 350 KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE) ; |
344 } else { | 351 } else { |
345 nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawK eyDown, | 352 nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawK eyDown, |
346 timeStampMs, keyCode, 0); | 353 timeStampMs, keyCode, 0); |
347 if (isCommit) { | 354 if (isCommit) { |
348 nativeCommitText(mNativeImeAdapterAndroid, text); | 355 nativeCommitText(mNativeImeAdapterAndroid, textStr); |
349 } else { | 356 } else { |
350 nativeSetComposingText(mNativeImeAdapterAndroid, text, newCursor Position); | 357 nativeSetComposingText(mNativeImeAdapterAndroid, text, textStr, newCursorPosition); |
351 } | 358 } |
352 nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyU p, | 359 nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyU p, |
353 timeStampMs, keyCode, 0); | 360 timeStampMs, keyCode, 0); |
354 } | 361 } |
355 | 362 |
356 return true; | 363 return true; |
357 } | 364 } |
358 | 365 |
359 void finishComposingText() { | 366 void finishComposingText() { |
360 if (mNativeImeAdapterAndroid == 0) return; | 367 if (mNativeImeAdapterAndroid == 0) return; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
513 sTextInputTypeNumber = textInputTypeNumber; | 520 sTextInputTypeNumber = textInputTypeNumber; |
514 sTextInputTypeContentEditable = textInputTypeContentEditable; | 521 sTextInputTypeContentEditable = textInputTypeContentEditable; |
515 } | 522 } |
516 | 523 |
517 @CalledByNative | 524 @CalledByNative |
518 private void focusedNodeChanged(boolean isEditable) { | 525 private void focusedNodeChanged(boolean isEditable) { |
519 if (mInputConnection != null && isEditable) mInputConnection.restartInpu t(); | 526 if (mInputConnection != null && isEditable) mInputConnection.restartInpu t(); |
520 } | 527 } |
521 | 528 |
522 @CalledByNative | 529 @CalledByNative |
530 private void populateUnderlinesFromSpans(CharSequence text, long underlines) { | |
531 String textStr = text.toString(); | |
Ted C
2014/06/10 20:47:33
You don't need textStr do you? CharSequence has .
huangs
2014/06/11 02:41:01
Done.
| |
532 if (text instanceof SpannableString) { | |
Ted C
2014/06/10 20:47:33
Even if we don't add the assert, I think we should
huangs
2014/06/11 02:41:01
Done.
| |
533 SpannableString spannableString = ((SpannableString) text); | |
534 CharacterStyle spans[] = | |
535 spannableString.getSpans(0, textStr.length(), CharacterStyle .class); | |
536 for (CharacterStyle span : spans) { | |
537 if (span instanceof BackgroundColorSpan) { | |
538 nativeAppendBackgroundColorSpan(underlines, spannableString. getSpanStart(span), | |
539 spannableString.getSpanEnd(span), | |
Ted C
2014/06/10 20:47:33
+4 indent on these two lines (same for the line be
huangs
2014/06/11 02:41:01
Done.
| |
540 ((BackgroundColorSpan) span).getBackgroundColor()); | |
541 } else if (span instanceof UnderlineSpan) { | |
542 nativeAppendUnderlineSpan(underlines, spannableString.getSpa nStart(span), | |
543 spannableString.getSpanEnd(span)); | |
544 } | |
545 } | |
546 } | |
547 } | |
548 | |
549 @CalledByNative | |
523 private void cancelComposition() { | 550 private void cancelComposition() { |
524 if (mInputConnection != null) mInputConnection.restartInput(); | 551 if (mInputConnection != null) mInputConnection.restartInput(); |
525 } | 552 } |
526 | 553 |
527 @CalledByNative | 554 @CalledByNative |
528 void detach() { | 555 void detach() { |
529 if (mDismissInput != null) mHandler.removeCallbacks(mDismissInput); | 556 if (mDismissInput != null) mHandler.removeCallbacks(mDismissInput); |
530 mNativeImeAdapterAndroid = 0; | 557 mNativeImeAdapterAndroid = 0; |
531 mTextInputType = 0; | 558 mTextInputType = 0; |
532 } | 559 } |
533 | 560 |
534 private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndr oid, | 561 private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndr oid, |
535 int eventType, long timestampMs, int keyCode, int unicodeChar); | 562 int eventType, long timestampMs, int keyCode, int unicodeChar); |
536 | 563 |
537 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE vent event, | 564 private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyE vent event, |
538 int action, int modifiers, long timestampMs, int keyCode, boolean is SystemKey, | 565 int action, int modifiers, long timestampMs, int keyCode, boolean is SystemKey, |
539 int unicodeChar); | 566 int unicodeChar); |
540 | 567 |
541 private native void nativeSetComposingText(long nativeImeAdapterAndroid, Str ing text, | 568 private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end); |
542 int newCursorPosition); | |
543 | 569 |
544 private native void nativeCommitText(long nativeImeAdapterAndroid, String te xt); | 570 private static native void nativeAppendBackgroundColorSpan(long underlinePtr , int start, |
571 int end, int backgroundColor); | |
572 | |
573 private native void nativeSetComposingText(long nativeImeAdapterAndroid, Cha rSequence text, | |
574 String textStr, int newCursorPosition); | |
575 | |
576 private native void nativeCommitText(long nativeImeAdapterAndroid, String te xtStr); | |
545 | 577 |
546 private native void nativeFinishComposingText(long nativeImeAdapterAndroid); | 578 private native void nativeFinishComposingText(long nativeImeAdapterAndroid); |
547 | 579 |
548 private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid); | 580 private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid); |
549 | 581 |
550 private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterA ndroid, | 582 private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterA ndroid, |
551 int start, int end); | 583 int start, int end); |
552 | 584 |
553 private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, i nt start, int end); | 585 private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, i nt start, int end); |
554 | 586 |
555 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid , | 587 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid , |
556 int before, int after); | 588 int before, int after); |
557 | 589 |
558 private native void nativeUnselect(long nativeImeAdapterAndroid); | 590 private native void nativeUnselect(long nativeImeAdapterAndroid); |
559 private native void nativeSelectAll(long nativeImeAdapterAndroid); | 591 private native void nativeSelectAll(long nativeImeAdapterAndroid); |
560 private native void nativeCut(long nativeImeAdapterAndroid); | 592 private native void nativeCut(long nativeImeAdapterAndroid); |
561 private native void nativeCopy(long nativeImeAdapterAndroid); | 593 private native void nativeCopy(long nativeImeAdapterAndroid); |
562 private native void nativePaste(long nativeImeAdapterAndroid); | 594 private native void nativePaste(long nativeImeAdapterAndroid); |
563 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); | 595 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); |
564 } | 596 } |
OLD | NEW |