| Index: content/public/android/javatests/src/org/chromium/content/browser/input/CursorAnchorInfoControllerTest.java
|
| diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/CursorAnchorInfoControllerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/CursorAnchorInfoControllerTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..768b6bbf91d2aded5ac6101e705e16983d39a7b4
|
| --- /dev/null
|
| +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/CursorAnchorInfoControllerTest.java
|
| @@ -0,0 +1,589 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.content.browser.input;
|
| +
|
| +import android.annotation.TargetApi;
|
| +import android.graphics.Matrix;
|
| +import android.graphics.RectF;
|
| +import android.os.Build;
|
| +import android.test.InstrumentationTestCase;
|
| +import android.test.suitebuilder.annotation.SmallTest;
|
| +import android.text.TextUtils;
|
| +import android.view.View;
|
| +import android.view.inputmethod.CursorAnchorInfo;
|
| +import android.view.inputmethod.InputConnection;
|
| +
|
| +import org.chromium.base.test.util.Feature;
|
| +import org.chromium.base.test.util.MinAndroidSdkLevel;
|
| +import org.chromium.content.browser.RenderCoordinates;
|
| +import org.chromium.content.browser.test.util.TestInputMethodManagerWrapper;
|
| +
|
| +/**
|
| + * Test for {@link CursorAnchorInfoController}.
|
| + */
|
| +@MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP)
|
| +@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
| +public class CursorAnchorInfoControllerTest extends InstrumentationTestCase {
|
| + private static RenderCoordinates createRenderCoordinates(float deviceScaleFactor,
|
| + float contentOffsetYPix) {
|
| + RenderCoordinates renderCoordinates = new RenderCoordinates();
|
| + renderCoordinates.setFrameInfoForTest(deviceScaleFactor, contentOffsetYPix);
|
| + return renderCoordinates;
|
| + }
|
| +
|
| + private static final class TestViewDelegate implements CursorAnchorInfoController.ViewDelegate {
|
| + public int locationX;
|
| + public int locationY;
|
| + @Override
|
| + public void getLocationOnScreen(View view, int[] location) {
|
| + location[0] = locationX;
|
| + location[1] = locationY;
|
| + }
|
| + }
|
| +
|
| + private static final class TestComposingTextDelegate
|
| + implements CursorAnchorInfoController.ComposingTextDelegate {
|
| + private String mText;
|
| + private int mSelectionStart = -1;
|
| + private int mSelectionEnd = -1;
|
| + private int mComposingTextStart = -1;
|
| + private int mComposingTextEnd = -1;
|
| +
|
| + @Override
|
| + public CharSequence getText() {
|
| + return mText;
|
| + }
|
| + @Override
|
| + public int getSelectionStart() {
|
| + return mSelectionStart;
|
| + }
|
| + @Override
|
| + public int getSelectionEnd() {
|
| + return mSelectionEnd;
|
| + }
|
| + @Override
|
| + public int getComposingTextStart() {
|
| + return mComposingTextStart;
|
| + }
|
| + @Override
|
| + public int getComposingTextEnd() {
|
| + return mComposingTextEnd;
|
| + }
|
| +
|
| + public void updateTextAndSelection(CursorAnchorInfoController controller,
|
| + String text, int compositionStart, int compositionEnd, int selectionStart,
|
| + int selectionEnd) {
|
| + mText = text;
|
| + mSelectionStart = selectionStart;
|
| + mSelectionEnd = selectionEnd;
|
| + mComposingTextStart = compositionStart;
|
| + mComposingTextEnd = compositionEnd;
|
| + controller.invalidateLastCursorAnchorInfo();
|
| + }
|
| +
|
| + public void clearTextAndSelection(CursorAnchorInfoController controller) {
|
| + updateTextAndSelection(controller, null, -1, -1, -1, -1);
|
| + }
|
| + }
|
| +
|
| + private void assertScaleAndTranslate(float expectedScale, float expectedTranslateX,
|
| + float expectedTranslateY, CursorAnchorInfo actual) {
|
| + Matrix expectedMatrix = new Matrix();
|
| + expectedMatrix.setScale(expectedScale, expectedScale);
|
| + expectedMatrix.postTranslate(expectedTranslateX, expectedTranslateY);
|
| + assertEquals(expectedMatrix, actual.getMatrix());
|
| + }
|
| +
|
| + private void assertHasInsertionMarker(int expectedFlags, float expectedHorizontal,
|
| + float expectedTop, float expectedBaseline, float expectedBottom,
|
| + CursorAnchorInfo actual) {
|
| + assertEquals(expectedFlags, actual.getInsertionMarkerFlags());
|
| + assertEquals(expectedHorizontal, actual.getInsertionMarkerHorizontal());
|
| + assertEquals(expectedTop, actual.getInsertionMarkerTop());
|
| + assertEquals(expectedBaseline, actual.getInsertionMarkerBaseline());
|
| + assertEquals(expectedBottom, actual.getInsertionMarkerBottom());
|
| + }
|
| +
|
| + private void assertHasNoInsertionMarker(CursorAnchorInfo actual) {
|
| + assertEquals(0, actual.getInsertionMarkerFlags());
|
| + assertTrue(Float.isNaN(actual.getInsertionMarkerHorizontal()));
|
| + assertTrue(Float.isNaN(actual.getInsertionMarkerTop()));
|
| + assertTrue(Float.isNaN(actual.getInsertionMarkerBaseline()));
|
| + assertTrue(Float.isNaN(actual.getInsertionMarkerBottom()));
|
| + }
|
| +
|
| + private void assertComposingText(CharSequence expectedComposingText,
|
| + int expectedComposingTextStart, CursorAnchorInfo actual) {
|
| + assertTrue(TextUtils.equals(expectedComposingText, actual.getComposingText()));
|
| + assertEquals(expectedComposingTextStart, actual.getComposingTextStart());
|
| + }
|
| +
|
| + private void assertSelection(int expecteSelectionStart, int expecteSelectionEnd,
|
| + CursorAnchorInfo actual) {
|
| + assertEquals(expecteSelectionStart, actual.getSelectionStart());
|
| + assertEquals(expecteSelectionEnd, actual.getSelectionEnd());
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testFocusedNodeChanged() {
|
| + TestInputMethodManagerWrapper immw = new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestComposingTextDelegate composingTextDelegate = new TestComposingTextDelegate();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, composingTextDelegate, viewDelegate);
|
| + View view = null;
|
| +
|
| + viewDelegate.locationX = 0;
|
| + viewDelegate.locationY = 0;
|
| +
|
| + assertFalse(
|
| + "IC#onRequestCursorUpdates() must be rejected if the focused node is not editable.",
|
| + controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_MONITOR, view));
|
| +
|
| + // Make sure that the focused node is considered to be non-editable by default.
|
| + controller.setCompositionCharacterBounds(new float[] {0.0f, 1.0f, 2.0f, 3.0f});
|
| + composingTextDelegate.updateTextAndSelection(controller, "0", 0, 1, 0, 1);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(0, immw.getUpdateCursorAnchorInfoCounter());
|
| +
|
| + controller.focusedNodeChanged(false);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| +
|
| + // Make sure that the controller does not crash even if it is called while the focused node
|
| + // is not editable.
|
| + controller.setCompositionCharacterBounds(new float[] {30.0f, 1.0f, 32.0f, 3.0f});
|
| + composingTextDelegate.updateTextAndSelection(controller, "1", 0, 1, 0, 1);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 100.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(0, immw.getUpdateCursorAnchorInfoCounter());
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testImmediateMode() {
|
| + TestInputMethodManagerWrapper immw = new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestComposingTextDelegate composingTextDelegate = new TestComposingTextDelegate();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, composingTextDelegate, viewDelegate);
|
| + View view = null;
|
| + viewDelegate.locationX = 0;
|
| + viewDelegate.locationY = 0;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is not be called until the matrix info becomes
|
| + // available with #onUpdateFrameInfo().
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_IMMEDIATE,
|
| + view));
|
| + controller.setCompositionCharacterBounds(new float[] {0.0f, 1.0f, 2.0f, 3.0f});
|
| + composingTextDelegate.updateTextAndSelection(controller, "0", 0, 1, 0, 1);
|
| + assertEquals(0, immw.getUpdateCursorAnchorInfoCounter());
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfo());
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfo());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // Make sure that 2nd call of #onUpdateFrameInfo() is ignored.
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| +
|
| + // Make sure that #onUpdateFrameInfo() is immediately called because the matrix info is
|
| + // already available.
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_IMMEDIATE,
|
| + view));
|
| + assertEquals(2, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfo());
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfo());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // Make sure that CURSOR_UPDATE_IMMEDIATE and CURSOR_UPDATE_MONITOR can be specified at
|
| + // the same time.
|
| + assertTrue(controller.onRequestCursorUpdates(
|
| + InputConnection.CURSOR_UPDATE_IMMEDIATE | InputConnection.CURSOR_UPDATE_MONITOR,
|
| + view));
|
| + assertEquals(3, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(4, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfo());
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfo());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // Make sure that CURSOR_UPDATE_IMMEDIATE is cleared if the focused node becomes
|
| + // non-editable.
|
| + controller.focusedNodeChanged(false);
|
| + controller.focusedNodeChanged(true);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_IMMEDIATE,
|
| + view));
|
| + controller.focusedNodeChanged(false);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 100.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(4, immw.getUpdateCursorAnchorInfoCounter());
|
| +
|
| + // Make sure that CURSOR_UPDATE_IMMEDIATE can be enabled again.
|
| + controller.focusedNodeChanged(true);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_IMMEDIATE,
|
| + view));
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(5, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfo());
|
| + assertEquals(null, immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(0, immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertComposingText(null, -1, immw.getLastCursorAnchorInfo());
|
| + assertSelection(-1, -1, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testMonitorMode() {
|
| + TestInputMethodManagerWrapper immw = new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestComposingTextDelegate composingTextDelegate = new TestComposingTextDelegate();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, composingTextDelegate, viewDelegate);
|
| + View view = null;
|
| + viewDelegate.locationX = 0;
|
| + viewDelegate.locationY = 0;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is not be called until the matrix info becomes
|
| + // available with #onUpdateFrameInfo().
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_MONITOR, view));
|
| + controller.setCompositionCharacterBounds(new float[] {0.0f, 1.0f, 2.0f, 3.0f});
|
| + composingTextDelegate.updateTextAndSelection(controller, "0", 0, 1, 0, 1);
|
| + assertEquals(0, immw.getUpdateCursorAnchorInfoCounter());
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfo());
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfo());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is not be called if any coordinate parameter is
|
| + // changed for better performance.
|
| + controller.setCompositionCharacterBounds(new float[] {0.0f, 1.0f, 2.0f, 3.0f});
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is called if #setCompositionCharacterBounds()
|
| + // is called with a different parameter.
|
| + controller.setCompositionCharacterBounds(new float[] {30.0f, 1.0f, 32.0f, 3.0f});
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(2, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfo());
|
| + assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfo());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is called if #updateTextAndSelection()
|
| + // is called with a different parameter.
|
| + composingTextDelegate.updateTextAndSelection(controller, "1", 0, 1, 0, 1);
|
| + assertEquals(2, immw.getUpdateCursorAnchorInfoCounter());
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(3, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfo());
|
| + assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertComposingText("1", 0, immw.getLastCursorAnchorInfo());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is called if #onUpdateFrameInfo()
|
| + // is called with a different parameter.
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(4, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfo());
|
| + assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertComposingText("1", 0, immw.getLastCursorAnchorInfo());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is called when the view origin is changed.
|
| + viewDelegate.locationX = 7;
|
| + viewDelegate.locationY = 9;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(5, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 7.0f, 9.0f, immw.getLastCursorAnchorInfo());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfo());
|
| + assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertComposingText("1", 0, immw.getLastCursorAnchorInfo());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // Make sure that CURSOR_UPDATE_IMMEDIATE is cleared if the focused node becomes
|
| + // non-editable.
|
| + controller.focusedNodeChanged(false);
|
| + controller.focusedNodeChanged(true);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_MONITOR, view));
|
| + controller.focusedNodeChanged(false);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| + controller.setCompositionCharacterBounds(new float[] {0.0f, 1.0f, 2.0f, 3.0f});
|
| + composingTextDelegate.updateTextAndSelection(controller, "0", 0, 1, 0, 1);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(5, immw.getUpdateCursorAnchorInfoCounter());
|
| +
|
| + // Make sure that CURSOR_UPDATE_MONITOR can be enabled again.
|
| + controller.focusedNodeChanged(true);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_MONITOR, view));
|
| + controller.setCompositionCharacterBounds(new float[] {0.0f, 1.0f, 2.0f, 3.0f});
|
| + composingTextDelegate.updateTextAndSelection(controller, "0", 0, 1, 0, 1);
|
| + assertEquals(5, immw.getUpdateCursorAnchorInfoCounter());
|
| + viewDelegate.locationX = 0;
|
| + viewDelegate.locationY = 0;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(6, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfo());
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfo());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testSetCompositionCharacterBounds() {
|
| + TestInputMethodManagerWrapper immw = new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestComposingTextDelegate composingTextDelegate = new TestComposingTextDelegate();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, composingTextDelegate, viewDelegate);
|
| + View view = null;
|
| +
|
| + viewDelegate.locationX = 0;
|
| + viewDelegate.locationY = 0;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_MONITOR, view));
|
| +
|
| + composingTextDelegate.updateTextAndSelection(controller, "01234", 1, 3, 1, 1);
|
| + controller.setCompositionCharacterBounds(new float[] {0.0f, 1.0f, 2.0f, 3.0f,
|
| + 4.0f, 1.1f, 6.0f, 2.9f});
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertEquals(null, immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(0, immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(1));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(1));
|
| + assertEquals(new RectF(4.0f, 1.1f, 6.0f, 2.9f),
|
| + immw.getLastCursorAnchorInfo().getCharacterBounds(2));
|
| + assertEquals(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(2));
|
| + assertEquals(null, immw.getLastCursorAnchorInfo().getCharacterBounds(3));
|
| + assertEquals(0, immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(3));
|
| + assertComposingText("12", 1, immw.getLastCursorAnchorInfo());
|
| + assertSelection(1, 1, immw.getLastCursorAnchorInfo());
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testUpdateTextAndSelection() {
|
| + TestInputMethodManagerWrapper immw = new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestComposingTextDelegate composingTextDelegate = new TestComposingTextDelegate();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, composingTextDelegate, viewDelegate);
|
| + View view = null;
|
| +
|
| + viewDelegate.locationX = 0;
|
| + viewDelegate.locationY = 0;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_MONITOR, view));
|
| +
|
| + composingTextDelegate.updateTextAndSelection(controller, "01234", 3, 3, 1, 1);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertEquals(null, immw.getLastCursorAnchorInfo().getCharacterBounds(0));
|
| + assertEquals(0, immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(0));
|
| + assertEquals(null, immw.getLastCursorAnchorInfo().getCharacterBounds(1));
|
| + assertEquals(0, immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(1));
|
| + assertEquals(null, immw.getLastCursorAnchorInfo().getCharacterBounds(2));
|
| + assertEquals(0, immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(2));
|
| + assertEquals(null, immw.getLastCursorAnchorInfo().getCharacterBounds(3));
|
| + assertEquals(0, immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(3));
|
| + assertEquals(null, immw.getLastCursorAnchorInfo().getCharacterBounds(4));
|
| + assertEquals(0, immw.getLastCursorAnchorInfo().getCharacterBoundsFlags(4));
|
| + assertComposingText("", 3, immw.getLastCursorAnchorInfo());
|
| + assertSelection(1, 1, immw.getLastCursorAnchorInfo());
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testInsertionMarker() {
|
| + TestInputMethodManagerWrapper immw = new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestComposingTextDelegate composingTextDelegate = new TestComposingTextDelegate();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, composingTextDelegate, viewDelegate);
|
| + View view = null;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_MONITOR, view));
|
| +
|
| + // Test no insertion marker.
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertHasNoInsertionMarker(immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // Test a visible insertion marker.
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, true, 10.0f, 23.0f, 29.0f, view);
|
| + assertEquals(2, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION,
|
| + 10.0f, 23.0f, 29.0f, 29.0f, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // Test a invisible insertion marker.
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + true, false, 10.0f, 23.0f, 29.0f, view);
|
| + assertEquals(3, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertHasInsertionMarker(CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION,
|
| + 10.0f, 23.0f, 29.0f, 29.0f, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testMatrix() {
|
| + TestInputMethodManagerWrapper immw = new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestComposingTextDelegate composingTextDelegate = new TestComposingTextDelegate();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, composingTextDelegate, viewDelegate);
|
| + View view = null;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| + composingTextDelegate.clearTextAndSelection(controller);
|
| + assertTrue(controller.onRequestCursorUpdates(InputConnection.CURSOR_UPDATE_MONITOR, view));
|
| +
|
| + // Test no transformation
|
| + viewDelegate.locationX = 0;
|
| + viewDelegate.locationY = 0;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // device scale factor == 2.0
|
| + viewDelegate.locationX = 0;
|
| + viewDelegate.locationY = 0;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(2, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // device scale factor == 2.0
|
| + // view origin == (10, 141)
|
| + viewDelegate.locationX = 10;
|
| + viewDelegate.locationY = 141;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(3, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 10.0f, 141.0f, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| +
|
| + // device scale factor == 2.0
|
| + // content offset Y = 40.0f
|
| + // view origin == (10, 141)
|
| + viewDelegate.locationX = 10;
|
| + viewDelegate.locationY = 141;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 40.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(4, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 10.0f, 181.0f, immw.getLastCursorAnchorInfo());
|
| + immw.clearLastCursorAnchorInfo();
|
| + }
|
| +}
|
|
|