| 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..be18a330291ffab6a21ac6ade56d20c9ed68176b
|
| --- /dev/null
|
| +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/CursorAnchorInfoControllerTest.java
|
| @@ -0,0 +1,576 @@
|
| +// Copyright 2014 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.graphics.Matrix;
|
| +import android.graphics.RectF;
|
| +import android.test.InstrumentationTestCase;
|
| +import android.test.suitebuilder.annotation.SmallTest;
|
| +import android.text.TextUtils;
|
| +import android.view.View;
|
| +
|
| +import org.chromium.base.test.util.Feature;
|
| +import org.chromium.content.browser.RenderCoordinates;
|
| +import org.chromium.content.browser.test.util.TestCursorAnchorInfoWrapper;
|
| +import org.chromium.content.browser.test.util.TestInputMethodManagerWrapper;
|
| +
|
| +/**
|
| + * Test for {@link CursorAnchorInfoController}.
|
| + */
|
| +public class CursorAnchorInfoControllerTest extends InstrumentationTestCase {
|
| +
|
| + public static final int CURSOR_UPDATE_IMMEDIATE = 1 << 0;
|
| + public static final int CURSOR_UPDATE_MONITOR = 1 << 1;
|
| +
|
| + private static RenderCoordinates createRenderCoordinates(float deviceScaleFactor,
|
| + float pageScaleFactor, float scrollXCss, float scrollYCss, float contentOffsetYPix) {
|
| + RenderCoordinates renderCoordinates = new RenderCoordinates();
|
| + renderCoordinates.setFrameInfoForTest(deviceScaleFactor, pageScaleFactor, scrollXCss,
|
| + scrollYCss, contentOffsetYPix);
|
| + return renderCoordinates;
|
| + }
|
| +
|
| + private static final class TestViewDelegate implements CursorAnchorInfoController.ViewDelegate {
|
| + public int mLocationX;
|
| + public int mLocationY;
|
| + @Override
|
| + public void getLocationOnScreen(View view, int[] location) {
|
| + location[0] = mLocationX;
|
| + location[1] = mLocationY;
|
| + }
|
| + }
|
| +
|
| + private void assertScaleAndTranslate(float expectedScale, float expectedTranslateX,
|
| + float expectedTranslateY, CursorAnchorInfoWrapper actual) {
|
| + Matrix expectedMatrix = new Matrix();
|
| + expectedMatrix.setScale(expectedScale, expectedScale);
|
| + expectedMatrix.postTranslate(expectedTranslateX, expectedTranslateY);
|
| + float[] expectedMatrixValues = new float[12];
|
| + expectedMatrix.getValues(expectedMatrixValues);
|
| + float[] actualMatrixValues = new float[12];
|
| + actual.getMatrix().getValues(actualMatrixValues);
|
| + for (int i = 0; i < expectedMatrixValues.length; ++i) {
|
| + assertEquals(expectedMatrixValues[i], actualMatrixValues[i]);
|
| + }
|
| + }
|
| +
|
| + private void assertHasInsertionMarker(int expectedFlags, float expectedHorizontal,
|
| + float expectedTop, float expectedBaseline, float expectedBottom,
|
| + CursorAnchorInfoWrapper actual) {
|
| + assertEquals(expectedFlags, actual.getInsertionMarkerFlags());
|
| + assertEquals(expectedHorizontal, actual.getInsertionMarkerHorizontal());
|
| + assertEquals(expectedTop, actual.getInsertionMarkerTop());
|
| + assertEquals(expectedBaseline, actual.getInsertionMarkerBaseline());
|
| + assertEquals(expectedBottom, actual.getInsertionMarkerBottom());
|
| + }
|
| +
|
| + private void assertHasNoInsertionMarker(CursorAnchorInfoWrapper 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, CursorAnchorInfoWrapper actual) {
|
| + assertTrue(TextUtils.equals(expectedComposingText, actual.getComposingText()));
|
| + assertEquals(expectedComposingTextStart, actual.getComposingTextStart());
|
| + }
|
| +
|
| + private void assertSelection(int expecteSelectionStart, int expecteSelectionEnd,
|
| + CursorAnchorInfoWrapper actual) {
|
| + assertEquals(expecteSelectionStart, actual.getSelectionStart());
|
| + assertEquals(expecteSelectionEnd, actual.getSelectionEnd());
|
| + }
|
| +
|
| + private void assertEquals(RectF expectedRect, RectF actualRect) {
|
| + if (expectedRect == null) {
|
| + assertNull(actualRect);
|
| + return;
|
| + }
|
| + assertNotNull(actualRect);
|
| + assertEquals(actualRect.left, expectedRect.left);
|
| + assertEquals(actualRect.top, expectedRect.top);
|
| + assertEquals(actualRect.right, expectedRect.right);
|
| + assertEquals(actualRect.bottom, expectedRect.bottom);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testFocusedNodeChanged() {
|
| + TestInputMethodManagerWrapper immw =
|
| + new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWrapper.Builder();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, builder, viewDelegate);
|
| + View view = null;
|
| +
|
| + viewDelegate.mLocationX = 0;
|
| + viewDelegate.mLocationY = 0;
|
| +
|
| + assertFalse(
|
| + "IC#onRequestCursorUpdates() must be rejected if the focused node is not editable.",
|
| + controller.onRequestCursorUpdates(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});
|
| + controller.updateTextAndSelection("0", 0, 1, 0, 1);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(0, immw.getUpdateCursorAnchorInfoCounter());
|
| +
|
| + controller.focusedNodeChanged(false);
|
| +
|
| + // 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});
|
| + controller.updateTextAndSelection("1", 0, 1, 0, 1);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 2.0f, 0.0f, 0.0f, 0.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();
|
| + TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWrapper.Builder();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, builder, viewDelegate);
|
| + View view = null;
|
| + viewDelegate.mLocationX = 0;
|
| + viewDelegate.mLocationY = 0;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is not be called until the matrix info becomes
|
| + // available with #onUpdateFrameInfo().
|
| + assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_IMMEDIATE, view));
|
| + controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3.0f});
|
| + controller.updateTextAndSelection("0", 0, 1, 0, 1);
|
| + assertEquals(0, immw.getUpdateCursorAnchorInfoCounter());
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // Make sure that 2nd call of #onUpdateFrameInfo() is ignored.
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 2.0f, 0.0f, 0.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(CURSOR_UPDATE_IMMEDIATE, view));
|
| + assertEquals(2, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // Make sure that CURSOR_UPDATE_IMMEDIATE and CURSOR_UPDATE_MONITOR can be specified at
|
| + // the same time.
|
| + assertTrue(controller.onRequestCursorUpdates(
|
| + CURSOR_UPDATE_IMMEDIATE | CURSOR_UPDATE_MONITOR, view));
|
| + assertEquals(3, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(4, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // Make sure that CURSOR_UPDATE_IMMEDIATE is cleared if the focused node becomes
|
| + // non-editable.
|
| + controller.focusedNodeChanged(false);
|
| + controller.focusedNodeChanged(true);
|
| + assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_IMMEDIATE, view));
|
| + controller.focusedNodeChanged(false);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 2.0f, 0.0f, 0.0f, 0.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);
|
| + assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_IMMEDIATE, view));
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(5, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertComposingText(null, -1, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(-1, -1, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testMonitorMode() {
|
| + TestInputMethodManagerWrapper immw =
|
| + new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWrapper.Builder();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, builder, viewDelegate);
|
| + View view = null;
|
| + viewDelegate.mLocationX = 0;
|
| + viewDelegate.mLocationY = 0;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is not be called until the matrix info becomes
|
| + // available with #onUpdateFrameInfo().
|
| + assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view));
|
| + controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3.0f});
|
| + controller.updateTextAndSelection("0", 0, 1, 0, 1);
|
| + assertEquals(0, immw.getUpdateCursorAnchorInfoCounter());
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is not be called if any parameter is changed
|
| + // for better performance.
|
| + controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3.0f});
|
| + controller.updateTextAndSelection("0", 0, 1, 0, 1);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.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, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(2, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is called if #updateTextAndSelection()
|
| + // is called with a different parameter.
|
| + controller.updateTextAndSelection("1", 0, 1, 0, 1);
|
| + assertEquals(2, immw.getUpdateCursorAnchorInfoCounter());
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(3, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertComposingText("1", 0, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is called if #onUpdateFrameInfo()
|
| + // is called with a different parameter.
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 2.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(4, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertComposingText("1", 0, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // Make sure that #updateCursorAnchorInfo() is called when the view origin is changed.
|
| + viewDelegate.mLocationX = 7;
|
| + viewDelegate.mLocationY = 9;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 2.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(5, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 7.0f, 9.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertComposingText("1", 0, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // Make sure that CURSOR_UPDATE_IMMEDIATE is cleared if the focused node becomes
|
| + // non-editable.
|
| + controller.focusedNodeChanged(false);
|
| + controller.focusedNodeChanged(true);
|
| + assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view));
|
| + controller.focusedNodeChanged(false);
|
| + controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3.0f});
|
| + controller.updateTextAndSelection("0", 0, 1, 0, 1);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.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);
|
| + assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view));
|
| + controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3.0f});
|
| + controller.updateTextAndSelection("0", 0, 1, 0, 1);
|
| + assertEquals(5, immw.getUpdateCursorAnchorInfoCounter());
|
| + viewDelegate.mLocationX = 0;
|
| + viewDelegate.mLocationY = 0;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 2.0f, 0.0f, 3.0f, view);
|
| + assertEquals(6, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, 2.0f, 0.0f, 3.0f,
|
| + 3.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testSetCompositionCharacterBounds() {
|
| + TestInputMethodManagerWrapper immw =
|
| + new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWrapper.Builder();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, builder, viewDelegate);
|
| + View view = null;
|
| +
|
| + viewDelegate.mLocationX = 0;
|
| + viewDelegate.mLocationY = 0;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| + assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view));
|
| +
|
| + controller.updateTextAndSelection("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, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(1));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(1));
|
| + assertEquals(new RectF(4.0f, 1.1f, 6.0f, 2.9f),
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(2));
|
| + assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(2));
|
| + assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(3));
|
| + assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(3));
|
| + assertComposingText("12", 1, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(1, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testUpdateTextAndSelection() {
|
| + TestInputMethodManagerWrapper immw =
|
| + new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWrapper.Builder();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, builder, viewDelegate);
|
| + View view = null;
|
| +
|
| + viewDelegate.mLocationX = 0;
|
| + viewDelegate.mLocationY = 0;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| + assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view));
|
| +
|
| + controller.updateTextAndSelection("01234", 3, 3, 1, 1);
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0));
|
| + assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0));
|
| + assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(1));
|
| + assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(1));
|
| + assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(2));
|
| + assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(2));
|
| + assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(3));
|
| + assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(3));
|
| + assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(4));
|
| + assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(4));
|
| + assertComposingText("", 3, immw.getLastCursorAnchorInfoWrapper());
|
| + assertSelection(1, 1, immw.getLastCursorAnchorInfoWrapper());
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testInsertionMarker() {
|
| + TestInputMethodManagerWrapper immw =
|
| + new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWrapper.Builder();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, builder, viewDelegate);
|
| + View view = null;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| + assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view));
|
| +
|
| + // Test no insertion marker.
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertHasNoInsertionMarker(immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // Test a visible insertion marker.
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + true, true, 10.0f, 23.0f, 29.0f, view);
|
| + assertEquals(2, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION,
|
| + 10.0f, 23.0f, 29.0f, 29.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // Test a invisible insertion marker.
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + true, false, 10.0f, 23.0f, 29.0f, view);
|
| + assertEquals(3, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_INVISIBLE_REGION,
|
| + 10.0f, 23.0f, 29.0f, 29.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Input-Text-IME"})
|
| + public void testMatrix() {
|
| + TestInputMethodManagerWrapper immw =
|
| + new TestInputMethodManagerWrapper(null);
|
| + TestViewDelegate viewDelegate = new TestViewDelegate();
|
| + TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWrapper.Builder();
|
| + CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
|
| + immw, builder, viewDelegate);
|
| + View view = null;
|
| +
|
| + controller.focusedNodeChanged(true);
|
| + assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view));
|
| +
|
| + // Test no transformation
|
| + viewDelegate.mLocationX = 0;
|
| + viewDelegate.mLocationY = 0;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(1, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // device scale factor == 2.0
|
| + viewDelegate.mLocationX = 0;
|
| + viewDelegate.mLocationY = 0;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(2, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // device scale factor == 2.0
|
| + // view origin == (10, 141)
|
| + viewDelegate.mLocationX = 10;
|
| + viewDelegate.mLocationY = 141;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 1.0f, 0.0f, 0.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(3, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 10.0f, 141.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // device scale factor == 2.0
|
| + // root scroll offset == (1.0f, 2.0f)
|
| + // view origin == (10, 141)
|
| + viewDelegate.mLocationX = 10;
|
| + viewDelegate.mLocationY = 141;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 1.0f, 1.0f, 2.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(4, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(2.0f, 8.0f, 137.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // device scale factor == 2.0
|
| + // page scale factor == 3.0f
|
| + // root scroll offset == (1.0f, 2.0f)
|
| + // view origin == (10, 141)
|
| + viewDelegate.mLocationX = 10;
|
| + viewDelegate.mLocationY = 141;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 3.0f, 1.0f, 2.0f, 0.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(5, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(6.0f, 4.0f, 129.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| +
|
| + // device scale factor == 2.0
|
| + // page scale factor == 3.0f
|
| + // root scroll offset == (1.0f, 2.0f)
|
| + // content offset Y = 40.0f
|
| + // view origin == (10, 141)
|
| + viewDelegate.mLocationX = 10;
|
| + viewDelegate.mLocationY = 141;
|
| + controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 3.0f, 1.0f, 2.0f, 40.0f),
|
| + false, false, Float.NaN, Float.NaN, Float.NaN, view);
|
| + assertEquals(6, immw.getUpdateCursorAnchorInfoCounter());
|
| + assertScaleAndTranslate(6.0f, 4.0f, 169.0f, immw.getLastCursorAnchorInfoWrapper());
|
| + immw.clearLastCursorAnchorInfoWrapper();
|
| + }
|
| +}
|
|
|