Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(932)

Unified Diff: content/public/android/javatests/src/org/chromium/content/browser/input/CursorAnchorInfoControllerTest.java

Issue 1589953005: Support InputMethodManager#updateCursorAnchorInfo for Android 5.0 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed #36. Added ImeLollipopTest for IMMEDIATE case. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..bc20180ad67b374093fa77dd8b897d454a176d9d
--- /dev/null
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/CursorAnchorInfoControllerTest.java
@@ -0,0 +1,607 @@
+// 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 mLocationX;
Ted C 2016/03/07 21:31:45 no leading m prefix for public fields.
kinaba 2016/03/10 06:24:12 Done.
+ public int mLocationY;
+ @Override
+ public void getLocationOnScreen(View view, int[] location) {
+ location[0] = mLocationX;
+ location[1] = mLocationY;
+ }
+ }
+
+ 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);
+ float[] expectedMatrixValues = new float[12];
+ expectedMatrix.getValues(expectedMatrixValues);
Ted C 2016/03/07 21:31:45 The documentation states it copies 9, is that inco
kinaba 2016/03/10 06:24:12 It's 9.
+ float[] actualMatrixValues = new float[12];
+ actual.getMatrix().getValues(actualMatrixValues);
+ for (int i = 0; i < expectedMatrixValues.length; ++i) {
+ assertEquals(expectedMatrixValues[i], actualMatrixValues[i]);
Ted C 2016/03/07 21:31:45 why not use Matrix.equals instead of comparing flo
kinaba 2016/03/10 06:24:12 Done.
+ }
+ }
+
+ 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());
+ }
+
+ private void assertEquals(RectF expectedRect, RectF actualRect) {
Ted C 2016/03/07 21:31:45 same question as Matrix, why not use the .equals
kinaba 2016/03/10 06:24:12 Done.
+ 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();
+ TestComposingTextDelegate composingTextDelegate = new TestComposingTextDelegate();
+ CursorAnchorInfoController controller = CursorAnchorInfoController.createForTest(
+ immw, composingTextDelegate, 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(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});
Ted C 2016/03/07 21:31:45 pretty sure there is supposed to be a space after
kinaba 2016/03/10 06:24:12 Done.
+ 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.mLocationX = 0;
+ viewDelegate.mLocationY = 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.mLocationX = 0;
+ viewDelegate.mLocationY = 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.mLocationX = 7;
+ viewDelegate.mLocationY = 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.mLocationX = 0;
+ viewDelegate.mLocationY = 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.mLocationX = 0;
+ viewDelegate.mLocationY = 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.mLocationX = 0;
+ viewDelegate.mLocationY = 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.mLocationX = 0;
+ viewDelegate.mLocationY = 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.mLocationX = 0;
+ viewDelegate.mLocationY = 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.mLocationX = 10;
+ viewDelegate.mLocationY = 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.mLocationX = 10;
+ viewDelegate.mLocationY = 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();
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698