OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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; | 5 package org.chromium.content.browser; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.os.Handler; | 8 import android.os.Handler; |
9 import android.os.ResultReceiver; | 9 import android.os.ResultReceiver; |
10 import android.text.Editable; | 10 import android.text.Editable; |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 nativePaste(mNativeImeAdapterAndroid); | 489 nativePaste(mNativeImeAdapterAndroid); |
490 return true; | 490 return true; |
491 } | 491 } |
492 | 492 |
493 // This InputConnection is created by ContentView.onCreateInputConnection. | 493 // This InputConnection is created by ContentView.onCreateInputConnection. |
494 // It then adapts android's IME to chrome's RenderWidgetHostView using the | 494 // It then adapts android's IME to chrome's RenderWidgetHostView using the |
495 // native ImeAdapterAndroid via the outer class ImeAdapter. | 495 // native ImeAdapterAndroid via the outer class ImeAdapter. |
496 static public class AdapterInputConnection extends BaseInputConnection { | 496 static public class AdapterInputConnection extends BaseInputConnection { |
497 private View mInternalView; | 497 private View mInternalView; |
498 private ImeAdapter mImeAdapter; | 498 private ImeAdapter mImeAdapter; |
499 private Editable mEditable; | |
500 private boolean mSingleLine; | 499 private boolean mSingleLine; |
501 | 500 |
502 // Factory function. | 501 // Factory function. |
503 static public AdapterInputConnection getInstance(View view, ImeAdapter i
meAdapter, | 502 static public AdapterInputConnection getInstance(View view, ImeAdapter i
meAdapter, |
504 EditorInfo outAttrs) { | 503 EditorInfo outAttrs) { |
505 return new AdapterInputConnection(view, imeAdapter, outAttrs); | 504 return new AdapterInputConnection(view, imeAdapter, outAttrs); |
506 } | 505 } |
507 | 506 |
508 /** | 507 /** |
509 * Updates the AdapterInputConnection's internal representation of the t
ext | 508 * Updates the AdapterInputConnection's internal representation of the t
ext |
510 * being edited and its selection and composition properties. The result
ing | 509 * being edited and its selection and composition properties. The result
ing |
511 * Editable is accessible through the getEditable() method. | 510 * Editable is accessible through the getEditable() method. |
512 * If the text has not changed, this also calls updateSelection on the I
nputMethodManager. | 511 * If the text has not changed, this also calls updateSelection on the I
nputMethodManager. |
513 * @param text The String contents of the field being edited | 512 * @param text The String contents of the field being edited |
514 * @param selectionStart The character offset of the selection start, or
the caret | 513 * @param selectionStart The character offset of the selection start, or
the caret |
515 * position if there is no selection | 514 * position if there is no selection |
516 * @param selectionEnd The character offset of the selection end, or the
caret | 515 * @param selectionEnd The character offset of the selection end, or the
caret |
517 * position if there is no selection | 516 * position if there is no selection |
518 * @param compositionStart The character offset of the composition start
, or -1 | 517 * @param compositionStart The character offset of the composition start
, or -1 |
519 * if there is no composition | 518 * if there is no composition |
520 * @param compositionEnd The character offset of the composition end, or
-1 | 519 * @param compositionEnd The character offset of the composition end, or
-1 |
521 * if there is no selection | 520 * if there is no selection |
522 */ | 521 */ |
523 public void setEditableText(String text, int selectionStart, int selecti
onEnd, | 522 public void setEditableText(String text, int selectionStart, int selecti
onEnd, |
524 int compositionStart, int compositionEnd) { | 523 int compositionStart, int compositionEnd) { |
525 | 524 |
526 if (mEditable == null) { | 525 Editable editable = getEditable(); |
527 mEditable = Editable.Factory.getInstance().newEditable(""); | |
528 } | |
529 | 526 |
530 int prevSelectionStart = Selection.getSelectionStart(mEditable); | 527 int prevSelectionStart = Selection.getSelectionStart(editable); |
531 int prevSelectionEnd = Selection.getSelectionEnd(mEditable); | 528 int prevSelectionEnd = Selection.getSelectionEnd(editable); |
532 int prevEditableLength = mEditable.length(); | 529 int prevEditableLength = editable.length(); |
533 int prevCompositionStart = getComposingSpanStart(mEditable); | 530 int prevCompositionStart = getComposingSpanStart(editable); |
534 int prevCompositionEnd = getComposingSpanEnd(mEditable); | 531 int prevCompositionEnd = getComposingSpanEnd(editable); |
535 String prevText = mEditable.toString(); | 532 String prevText = editable.toString(); |
536 | 533 |
537 selectionStart = Math.min(selectionStart, text.length()); | 534 selectionStart = Math.min(selectionStart, text.length()); |
538 selectionEnd = Math.min(selectionEnd, text.length()); | 535 selectionEnd = Math.min(selectionEnd, text.length()); |
539 compositionStart = Math.min(compositionStart, text.length()); | 536 compositionStart = Math.min(compositionStart, text.length()); |
540 compositionEnd = Math.min(compositionEnd, text.length()); | 537 compositionEnd = Math.min(compositionEnd, text.length()); |
541 | 538 |
542 boolean textUnchanged = prevText.equals(text); | 539 boolean textUnchanged = prevText.equals(text); |
543 | 540 |
544 if (textUnchanged | 541 if (textUnchanged |
545 && prevSelectionStart == selectionStart && prevSelectionEnd
== selectionEnd | 542 && prevSelectionStart == selectionStart && prevSelectionEnd
== selectionEnd |
546 && prevCompositionStart == compositionStart | 543 && prevCompositionStart == compositionStart |
547 && prevCompositionEnd == compositionEnd) { | 544 && prevCompositionEnd == compositionEnd) { |
548 // Nothing has changed; don't need to do anything | 545 // Nothing has changed; don't need to do anything |
549 return; | 546 return; |
550 } | 547 } |
551 | 548 |
552 // When a programmatic change has been made to the editable field, b
oth the start | 549 // When a programmatic change has been made to the editable field, b
oth the start |
553 // and end positions for the composition will equal zero. In this ca
se we cancel the | 550 // and end positions for the composition will equal zero. In this ca
se we cancel the |
554 // active composition in the editor as this no longer is relevant. | 551 // active composition in the editor as this no longer is relevant. |
555 if (textUnchanged && compositionStart == 0 && compositionEnd == 0) { | 552 if (textUnchanged && compositionStart == 0 && compositionEnd == 0) { |
556 cancelComposition(); | 553 cancelComposition(); |
557 } | 554 } |
558 | 555 |
559 if (!textUnchanged) { | 556 if (!textUnchanged) { |
560 mEditable.replace(0, mEditable.length(), text); | 557 editable.replace(0, editable.length(), text); |
561 } | 558 } |
562 Selection.setSelection(mEditable, selectionStart, selectionEnd); | 559 Selection.setSelection(editable, selectionStart, selectionEnd); |
563 super.setComposingRegion(compositionStart, compositionEnd); | 560 super.setComposingRegion(compositionStart, compositionEnd); |
564 | 561 |
565 if (textUnchanged || prevText.equals("")) { | 562 if (textUnchanged || prevText.equals("")) { |
566 // updateSelection should be called when a manual selection chan
ge occurs. | 563 // updateSelection should be called when a manual selection chan
ge occurs. |
567 // Should not be called if text is being entered else issues can
occur | 564 // Should not be called if text is being entered else issues can
occur |
568 // e.g. backspace to undo autocorrection will not work with the
default OSK. | 565 // e.g. backspace to undo autocorrection will not work with the
default OSK. |
569 getInputMethodManager().updateSelection(mInternalView, | 566 getInputMethodManager().updateSelection(mInternalView, |
570 selectionStart, selectionEnd, compositionStart, composit
ionEnd); | 567 selectionStart, selectionEnd, compositionStart, composit
ionEnd); |
571 } | 568 } |
572 } | 569 } |
573 | 570 |
574 @Override | 571 @Override |
575 public Editable getEditable() { | |
576 if (mEditable == null) { | |
577 mEditable = Editable.Factory.getInstance().newEditable(""); | |
578 Selection.setSelection(mEditable, 0); | |
579 } | |
580 return mEditable; | |
581 } | |
582 | |
583 @Override | |
584 public boolean setComposingText(CharSequence text, int newCursorPosition
) { | 572 public boolean setComposingText(CharSequence text, int newCursorPosition
) { |
585 super.setComposingText(text, newCursorPosition); | 573 super.setComposingText(text, newCursorPosition); |
586 return mImeAdapter.checkCompositionQueueAndCallNative(text.toString(
), | 574 return mImeAdapter.checkCompositionQueueAndCallNative(text.toString(
), |
587 newCursorPosition, false); | 575 newCursorPosition, false); |
588 } | 576 } |
589 | 577 |
590 @Override | 578 @Override |
591 public boolean commitText(CharSequence text, int newCursorPosition) { | 579 public boolean commitText(CharSequence text, int newCursorPosition) { |
592 super.commitText(text, newCursorPosition); | 580 super.commitText(text, newCursorPosition); |
593 return mImeAdapter.checkCompositionQueueAndCallNative(text.toString(
), | 581 return mImeAdapter.checkCompositionQueueAndCallNative(text.toString(
), |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 case android.R.id.paste: | 613 case android.R.id.paste: |
626 return mImeAdapter.paste(); | 614 return mImeAdapter.paste(); |
627 default: | 615 default: |
628 return false; | 616 return false; |
629 } | 617 } |
630 } | 618 } |
631 | 619 |
632 @Override | 620 @Override |
633 public ExtractedText getExtractedText(ExtractedTextRequest request, int
flags) { | 621 public ExtractedText getExtractedText(ExtractedTextRequest request, int
flags) { |
634 ExtractedText et = new ExtractedText(); | 622 ExtractedText et = new ExtractedText(); |
635 if (mEditable == null) { | 623 Editable editable = getEditable(); |
636 et.text = ""; | 624 et.text = editable.toString(); |
637 } else { | 625 et.partialEndOffset = editable.length(); |
638 et.text = mEditable.toString(); | 626 et.selectionStart = Selection.getSelectionStart(editable); |
639 et.partialEndOffset = mEditable.length(); | 627 et.selectionEnd = Selection.getSelectionEnd(editable); |
640 et.selectionStart = Selection.getSelectionStart(mEditable); | |
641 et.selectionEnd = Selection.getSelectionEnd(mEditable); | |
642 } | |
643 et.flags = mSingleLine ? ExtractedText.FLAG_SINGLE_LINE : 0; | 628 et.flags = mSingleLine ? ExtractedText.FLAG_SINGLE_LINE : 0; |
644 return et; | 629 return et; |
645 } | 630 } |
646 | 631 |
647 @Override | 632 @Override |
648 public boolean deleteSurroundingText(int leftLength, int rightLength) { | 633 public boolean deleteSurroundingText(int leftLength, int rightLength) { |
649 if (!super.deleteSurroundingText(leftLength, rightLength)) { | 634 if (!super.deleteSurroundingText(leftLength, rightLength)) { |
650 return false; | 635 return false; |
651 } | 636 } |
652 return mImeAdapter.deleteSurroundingText(leftLength, rightLength); | 637 return mImeAdapter.deleteSurroundingText(leftLength, rightLength); |
(...skipping 26 matching lines...) Expand all Loading... |
679 editable.replace(selectionStart, selectionEnd, | 664 editable.replace(selectionStart, selectionEnd, |
680 Character.toString((char)unicodeChar)); | 665 Character.toString((char)unicodeChar)); |
681 } | 666 } |
682 } | 667 } |
683 } | 668 } |
684 return super.sendKeyEvent(event); | 669 return super.sendKeyEvent(event); |
685 } | 670 } |
686 | 671 |
687 @Override | 672 @Override |
688 public boolean finishComposingText() { | 673 public boolean finishComposingText() { |
689 if (mEditable == null | 674 Editable editable = getEditable(); |
690 || (getComposingSpanStart(mEditable) == getComposingSpanEnd(
mEditable))) { | 675 if (getComposingSpanStart(editable) == getComposingSpanEnd(editable)
) { |
691 return true; | 676 return true; |
692 } | 677 } |
693 super.finishComposingText(); | 678 super.finishComposingText(); |
694 return mImeAdapter.checkCompositionQueueAndCallNative("", 0, true); | 679 return mImeAdapter.checkCompositionQueueAndCallNative("", 0, true); |
695 } | 680 } |
696 | 681 |
697 @Override | 682 @Override |
698 public boolean setSelection(int start, int end) { | 683 public boolean setSelection(int start, int end) { |
699 if (start < 0 || end < 0) return true; | 684 if (start < 0 || end < 0) return true; |
700 super.setSelection(start, end); | 685 super.setSelection(start, end); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 | 790 |
806 private native void nativeDeleteSurroundingText(int nativeImeAdapterAndroid, | 791 private native void nativeDeleteSurroundingText(int nativeImeAdapterAndroid, |
807 int before, int after); | 792 int before, int after); |
808 | 793 |
809 private native void nativeUnselect(int nativeImeAdapterAndroid); | 794 private native void nativeUnselect(int nativeImeAdapterAndroid); |
810 private native void nativeSelectAll(int nativeImeAdapterAndroid); | 795 private native void nativeSelectAll(int nativeImeAdapterAndroid); |
811 private native void nativeCut(int nativeImeAdapterAndroid); | 796 private native void nativeCut(int nativeImeAdapterAndroid); |
812 private native void nativeCopy(int nativeImeAdapterAndroid); | 797 private native void nativeCopy(int nativeImeAdapterAndroid); |
813 private native void nativePaste(int nativeImeAdapterAndroid); | 798 private native void nativePaste(int nativeImeAdapterAndroid); |
814 } | 799 } |
OLD | NEW |