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