OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.content.browser.input; |
| 6 |
| 7 import android.graphics.Matrix; |
| 8 import android.graphics.RectF; |
| 9 import android.test.InstrumentationTestCase; |
| 10 import android.test.suitebuilder.annotation.SmallTest; |
| 11 import android.text.TextUtils; |
| 12 import android.view.View; |
| 13 |
| 14 import org.chromium.base.test.util.Feature; |
| 15 import org.chromium.content.browser.RenderCoordinates; |
| 16 import org.chromium.content.browser.test.util.TestCursorAnchorInfoWrapper; |
| 17 import org.chromium.content.browser.test.util.TestInputMethodManagerWrapper; |
| 18 |
| 19 /** |
| 20 * Test for {@link CursorAnchorInfoController}. |
| 21 */ |
| 22 public class CursorAnchorInfoControllerTest extends InstrumentationTestCase { |
| 23 |
| 24 public static final int CURSOR_UPDATE_IMMEDIATE = 1 << 0; |
| 25 public static final int CURSOR_UPDATE_MONITOR = 1 << 1; |
| 26 |
| 27 private static RenderCoordinates createRenderCoordinates(float deviceScaleFa
ctor, |
| 28 float pageScaleFactor, float scrollXCss, float scrollYCss, float con
tentOffsetYPix) { |
| 29 RenderCoordinates renderCoordinates = new RenderCoordinates(); |
| 30 renderCoordinates.setFrameInfoForTest(deviceScaleFactor, pageScaleFactor
, scrollXCss, |
| 31 scrollYCss, contentOffsetYPix); |
| 32 return renderCoordinates; |
| 33 } |
| 34 |
| 35 private static final class TestViewDelegate implements CursorAnchorInfoContr
oller.ViewDelegate { |
| 36 public int mLocationX; |
| 37 public int mLocationY; |
| 38 @Override |
| 39 public void getLocationOnScreen(View view, int[] location) { |
| 40 location[0] = mLocationX; |
| 41 location[1] = mLocationY; |
| 42 } |
| 43 } |
| 44 |
| 45 private void assertScaleAndTranslate(float expectedScale, float expectedTran
slateX, |
| 46 float expectedTranslateY, CursorAnchorInfoWrapper actual) { |
| 47 Matrix expectedMatrix = new Matrix(); |
| 48 expectedMatrix.setScale(expectedScale, expectedScale); |
| 49 expectedMatrix.postTranslate(expectedTranslateX, expectedTranslateY); |
| 50 float[] expectedMatrixValues = new float[12]; |
| 51 expectedMatrix.getValues(expectedMatrixValues); |
| 52 float[] actualMatrixValues = new float[12]; |
| 53 actual.getMatrix().getValues(actualMatrixValues); |
| 54 for (int i = 0; i < expectedMatrixValues.length; ++i) { |
| 55 assertEquals(expectedMatrixValues[i], actualMatrixValues[i]); |
| 56 } |
| 57 } |
| 58 |
| 59 private void assertHasInsertionMarker(int expectedFlags, float expectedHoriz
ontal, |
| 60 float expectedTop, float expectedBaseline, float expectedBottom, |
| 61 CursorAnchorInfoWrapper actual) { |
| 62 assertEquals(expectedFlags, actual.getInsertionMarkerFlags()); |
| 63 assertEquals(expectedHorizontal, actual.getInsertionMarkerHorizontal()); |
| 64 assertEquals(expectedTop, actual.getInsertionMarkerTop()); |
| 65 assertEquals(expectedBaseline, actual.getInsertionMarkerBaseline()); |
| 66 assertEquals(expectedBottom, actual.getInsertionMarkerBottom()); |
| 67 } |
| 68 |
| 69 private void assertHasNoInsertionMarker(CursorAnchorInfoWrapper actual) { |
| 70 assertEquals(0, actual.getInsertionMarkerFlags()); |
| 71 assertTrue(Float.isNaN(actual.getInsertionMarkerHorizontal())); |
| 72 assertTrue(Float.isNaN(actual.getInsertionMarkerTop())); |
| 73 assertTrue(Float.isNaN(actual.getInsertionMarkerBaseline())); |
| 74 assertTrue(Float.isNaN(actual.getInsertionMarkerBottom())); |
| 75 } |
| 76 |
| 77 private void assertComposingText(CharSequence expectedComposingText, |
| 78 int expectedComposingTextStart, CursorAnchorInfoWrapper actual) { |
| 79 assertTrue(TextUtils.equals(expectedComposingText, actual.getComposingTe
xt())); |
| 80 assertEquals(expectedComposingTextStart, actual.getComposingTextStart())
; |
| 81 } |
| 82 |
| 83 private void assertSelection(int expecteSelectionStart, int expecteSelection
End, |
| 84 CursorAnchorInfoWrapper actual) { |
| 85 assertEquals(expecteSelectionStart, actual.getSelectionStart()); |
| 86 assertEquals(expecteSelectionEnd, actual.getSelectionEnd()); |
| 87 } |
| 88 |
| 89 private void assertEquals(RectF expectedRect, RectF actualRect) { |
| 90 if (expectedRect == null) { |
| 91 assertNull(actualRect); |
| 92 return; |
| 93 } |
| 94 assertNotNull(actualRect); |
| 95 assertEquals(actualRect.left, expectedRect.left); |
| 96 assertEquals(actualRect.top, expectedRect.top); |
| 97 assertEquals(actualRect.right, expectedRect.right); |
| 98 assertEquals(actualRect.bottom, expectedRect.bottom); |
| 99 } |
| 100 |
| 101 @SmallTest |
| 102 @Feature({"Input-Text-IME"}) |
| 103 public void testFocusedNodeChanged() { |
| 104 TestInputMethodManagerWrapper immw = |
| 105 new TestInputMethodManagerWrapper(null); |
| 106 TestViewDelegate viewDelegate = new TestViewDelegate(); |
| 107 TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWr
apper.Builder(); |
| 108 CursorAnchorInfoController controller = CursorAnchorInfoController.creat
eForTest( |
| 109 immw, builder, viewDelegate); |
| 110 View view = null; |
| 111 |
| 112 viewDelegate.mLocationX = 0; |
| 113 viewDelegate.mLocationY = 0; |
| 114 |
| 115 assertFalse( |
| 116 "IC#onRequestCursorUpdates() must be rejected if the focused nod
e is not editable.", |
| 117 controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view)); |
| 118 |
| 119 // Make sure that the focused node is considered to be non-editable by d
efault. |
| 120 controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3
.0f}); |
| 121 controller.updateTextAndSelection("0", 0, 1, 0, 1); |
| 122 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 123 true, true, 2.0f, 0.0f, 3.0f, view); |
| 124 assertEquals(0, immw.getUpdateCursorAnchorInfoCounter()); |
| 125 |
| 126 controller.focusedNodeChanged(false); |
| 127 |
| 128 // Make sure that the controller does not crash even if it is called whi
le the focused node |
| 129 // is not editable. |
| 130 controller.setCompositionCharacterBounds(new float[]{30.0f, 1.0f, 32.0f,
3.0f}); |
| 131 controller.updateTextAndSelection("1", 0, 1, 0, 1); |
| 132 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 2.0f, 0.0f, 0
.0f, 0.0f), |
| 133 true, true, 2.0f, 0.0f, 3.0f, view); |
| 134 assertEquals(0, immw.getUpdateCursorAnchorInfoCounter()); |
| 135 } |
| 136 |
| 137 @SmallTest |
| 138 @Feature({"Input-Text-IME"}) |
| 139 public void testImmediateMode() { |
| 140 TestInputMethodManagerWrapper immw = |
| 141 new TestInputMethodManagerWrapper(null); |
| 142 TestViewDelegate viewDelegate = new TestViewDelegate(); |
| 143 TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWr
apper.Builder(); |
| 144 CursorAnchorInfoController controller = CursorAnchorInfoController.creat
eForTest( |
| 145 immw, builder, viewDelegate); |
| 146 View view = null; |
| 147 viewDelegate.mLocationX = 0; |
| 148 viewDelegate.mLocationY = 0; |
| 149 |
| 150 controller.focusedNodeChanged(true); |
| 151 |
| 152 // Make sure that #updateCursorAnchorInfo() is not be called until the m
atrix info becomes |
| 153 // available with #onUpdateFrameInfo(). |
| 154 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_IMMEDIATE, vi
ew)); |
| 155 controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3
.0f}); |
| 156 controller.updateTextAndSelection("0", 0, 1, 0, 1); |
| 157 assertEquals(0, immw.getUpdateCursorAnchorInfoCounter()); |
| 158 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 159 true, true, 2.0f, 0.0f, 3.0f, view); |
| 160 assertEquals(1, immw.getUpdateCursorAnchorInfoCounter()); |
| 161 assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 162 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, 2.0f, 0.0f, 3.0f, |
| 163 3.0f, immw.getLastCursorAnchorInfoWrapper()); |
| 164 assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f), |
| 165 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0)); |
| 166 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 167 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0)
); |
| 168 assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper()); |
| 169 assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 170 immw.clearLastCursorAnchorInfoWrapper(); |
| 171 |
| 172 // Make sure that 2nd call of #onUpdateFrameInfo() is ignored. |
| 173 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 2.0f, 0.0f, 0
.0f, 0.0f), |
| 174 true, true, 2.0f, 0.0f, 3.0f, view); |
| 175 assertEquals(1, immw.getUpdateCursorAnchorInfoCounter()); |
| 176 |
| 177 // Make sure that #onUpdateFrameInfo() is immediately called because the
matrix info is |
| 178 // already available. |
| 179 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_IMMEDIATE, vi
ew)); |
| 180 assertEquals(2, immw.getUpdateCursorAnchorInfoCounter()); |
| 181 assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 182 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, 2.0f, 0.0f, 3.0f, |
| 183 3.0f, immw.getLastCursorAnchorInfoWrapper()); |
| 184 assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f), |
| 185 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0)); |
| 186 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 187 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0)
); |
| 188 assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper()); |
| 189 assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 190 immw.clearLastCursorAnchorInfoWrapper(); |
| 191 |
| 192 // Make sure that CURSOR_UPDATE_IMMEDIATE and CURSOR_UPDATE_MONITOR can
be specified at |
| 193 // the same time. |
| 194 assertTrue(controller.onRequestCursorUpdates( |
| 195 CURSOR_UPDATE_IMMEDIATE | CURSOR_UPDATE_MONITOR, view)); |
| 196 assertEquals(3, immw.getUpdateCursorAnchorInfoCounter()); |
| 197 assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 198 immw.clearLastCursorAnchorInfoWrapper(); |
| 199 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 200 true, true, 2.0f, 0.0f, 3.0f, view); |
| 201 assertEquals(4, immw.getUpdateCursorAnchorInfoCounter()); |
| 202 assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 203 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, 2.0f, 0.0f, 3.0f, |
| 204 3.0f, immw.getLastCursorAnchorInfoWrapper()); |
| 205 assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f), |
| 206 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0)); |
| 207 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 208 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0)
); |
| 209 assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper()); |
| 210 assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 211 immw.clearLastCursorAnchorInfoWrapper(); |
| 212 |
| 213 // Make sure that CURSOR_UPDATE_IMMEDIATE is cleared if the focused node
becomes |
| 214 // non-editable. |
| 215 controller.focusedNodeChanged(false); |
| 216 controller.focusedNodeChanged(true); |
| 217 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_IMMEDIATE, vi
ew)); |
| 218 controller.focusedNodeChanged(false); |
| 219 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 2.0f, 0.0f, 0
.0f, 0.0f), |
| 220 true, true, 2.0f, 0.0f, 3.0f, view); |
| 221 assertEquals(4, immw.getUpdateCursorAnchorInfoCounter()); |
| 222 |
| 223 // Make sure that CURSOR_UPDATE_IMMEDIATE can be enabled again. |
| 224 controller.focusedNodeChanged(true); |
| 225 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_IMMEDIATE, vi
ew)); |
| 226 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 227 true, true, 2.0f, 0.0f, 3.0f, view); |
| 228 assertEquals(5, immw.getUpdateCursorAnchorInfoCounter()); |
| 229 assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 230 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, 2.0f, 0.0f, 3.0f, |
| 231 3.0f, immw.getLastCursorAnchorInfoWrapper()); |
| 232 assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBou
nds(0)); |
| 233 assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds
Flags(0)); |
| 234 assertComposingText(null, -1, immw.getLastCursorAnchorInfoWrapper()); |
| 235 assertSelection(-1, -1, immw.getLastCursorAnchorInfoWrapper()); |
| 236 immw.clearLastCursorAnchorInfoWrapper(); |
| 237 } |
| 238 |
| 239 @SmallTest |
| 240 @Feature({"Input-Text-IME"}) |
| 241 public void testMonitorMode() { |
| 242 TestInputMethodManagerWrapper immw = |
| 243 new TestInputMethodManagerWrapper(null); |
| 244 TestViewDelegate viewDelegate = new TestViewDelegate(); |
| 245 TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWr
apper.Builder(); |
| 246 CursorAnchorInfoController controller = CursorAnchorInfoController.creat
eForTest( |
| 247 immw, builder, viewDelegate); |
| 248 View view = null; |
| 249 viewDelegate.mLocationX = 0; |
| 250 viewDelegate.mLocationY = 0; |
| 251 |
| 252 controller.focusedNodeChanged(true); |
| 253 |
| 254 // Make sure that #updateCursorAnchorInfo() is not be called until the m
atrix info becomes |
| 255 // available with #onUpdateFrameInfo(). |
| 256 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view
)); |
| 257 controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3
.0f}); |
| 258 controller.updateTextAndSelection("0", 0, 1, 0, 1); |
| 259 assertEquals(0, immw.getUpdateCursorAnchorInfoCounter()); |
| 260 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 261 true, true, 2.0f, 0.0f, 3.0f, view); |
| 262 assertEquals(1, immw.getUpdateCursorAnchorInfoCounter()); |
| 263 assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 264 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, 2.0f, 0.0f, 3.0f, |
| 265 3.0f, immw.getLastCursorAnchorInfoWrapper()); |
| 266 assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f), |
| 267 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0)); |
| 268 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 269 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0)
); |
| 270 assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper()); |
| 271 assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 272 immw.clearLastCursorAnchorInfoWrapper(); |
| 273 |
| 274 // Make sure that #updateCursorAnchorInfo() is not be called if any para
meter is changed |
| 275 // for better performance. |
| 276 controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3
.0f}); |
| 277 controller.updateTextAndSelection("0", 0, 1, 0, 1); |
| 278 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 279 true, true, 2.0f, 0.0f, 3.0f, view); |
| 280 assertEquals(1, immw.getUpdateCursorAnchorInfoCounter()); |
| 281 |
| 282 // Make sure that #updateCursorAnchorInfo() is called if #setComposition
CharacterBounds() |
| 283 // is called with a different parameter. |
| 284 controller.setCompositionCharacterBounds(new float[]{30.0f, 1.0f, 32.0f,
3.0f}); |
| 285 assertEquals(1, immw.getUpdateCursorAnchorInfoCounter()); |
| 286 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 287 true, true, 2.0f, 0.0f, 3.0f, view); |
| 288 assertEquals(2, immw.getUpdateCursorAnchorInfoCounter()); |
| 289 assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 290 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, 2.0f, 0.0f, 3.0f, |
| 291 3.0f, immw.getLastCursorAnchorInfoWrapper()); |
| 292 assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f), |
| 293 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0)); |
| 294 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 295 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0)
); |
| 296 assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper()); |
| 297 assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 298 immw.clearLastCursorAnchorInfoWrapper(); |
| 299 |
| 300 // Make sure that #updateCursorAnchorInfo() is called if #updateTextAndS
election() |
| 301 // is called with a different parameter. |
| 302 controller.updateTextAndSelection("1", 0, 1, 0, 1); |
| 303 assertEquals(2, immw.getUpdateCursorAnchorInfoCounter()); |
| 304 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 305 true, true, 2.0f, 0.0f, 3.0f, view); |
| 306 assertEquals(3, immw.getUpdateCursorAnchorInfoCounter()); |
| 307 assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 308 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, 2.0f, 0.0f, 3.0f, |
| 309 3.0f, immw.getLastCursorAnchorInfoWrapper()); |
| 310 assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f), |
| 311 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0)); |
| 312 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 313 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0)
); |
| 314 assertComposingText("1", 0, immw.getLastCursorAnchorInfoWrapper()); |
| 315 assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 316 immw.clearLastCursorAnchorInfoWrapper(); |
| 317 |
| 318 // Make sure that #updateCursorAnchorInfo() is called if #onUpdateFrameI
nfo() |
| 319 // is called with a different parameter. |
| 320 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 2.0f, 0.0f, 0
.0f, 0.0f), |
| 321 true, true, 2.0f, 0.0f, 3.0f, view); |
| 322 assertEquals(4, immw.getUpdateCursorAnchorInfoCounter()); |
| 323 assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 324 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, 2.0f, 0.0f, 3.0f, |
| 325 3.0f, immw.getLastCursorAnchorInfoWrapper()); |
| 326 assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f), |
| 327 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0)); |
| 328 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 329 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0)
); |
| 330 assertComposingText("1", 0, immw.getLastCursorAnchorInfoWrapper()); |
| 331 assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 332 immw.clearLastCursorAnchorInfoWrapper(); |
| 333 |
| 334 // Make sure that #updateCursorAnchorInfo() is called when the view orig
in is changed. |
| 335 viewDelegate.mLocationX = 7; |
| 336 viewDelegate.mLocationY = 9; |
| 337 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 2.0f, 0.0f, 0
.0f, 0.0f), |
| 338 true, true, 2.0f, 0.0f, 3.0f, view); |
| 339 assertEquals(5, immw.getUpdateCursorAnchorInfoCounter()); |
| 340 assertScaleAndTranslate(2.0f, 7.0f, 9.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 341 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, 2.0f, 0.0f, 3.0f, |
| 342 3.0f, immw.getLastCursorAnchorInfoWrapper()); |
| 343 assertEquals(new RectF(30.0f, 1.0f, 32.0f, 3.0f), |
| 344 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0)); |
| 345 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 346 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0)
); |
| 347 assertComposingText("1", 0, immw.getLastCursorAnchorInfoWrapper()); |
| 348 assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 349 immw.clearLastCursorAnchorInfoWrapper(); |
| 350 |
| 351 // Make sure that CURSOR_UPDATE_IMMEDIATE is cleared if the focused node
becomes |
| 352 // non-editable. |
| 353 controller.focusedNodeChanged(false); |
| 354 controller.focusedNodeChanged(true); |
| 355 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view
)); |
| 356 controller.focusedNodeChanged(false); |
| 357 controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3
.0f}); |
| 358 controller.updateTextAndSelection("0", 0, 1, 0, 1); |
| 359 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 360 true, true, 2.0f, 0.0f, 3.0f, view); |
| 361 assertEquals(5, immw.getUpdateCursorAnchorInfoCounter()); |
| 362 |
| 363 // Make sure that CURSOR_UPDATE_MONITOR can be enabled again. |
| 364 controller.focusedNodeChanged(true); |
| 365 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view
)); |
| 366 controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3
.0f}); |
| 367 controller.updateTextAndSelection("0", 0, 1, 0, 1); |
| 368 assertEquals(5, immw.getUpdateCursorAnchorInfoCounter()); |
| 369 viewDelegate.mLocationX = 0; |
| 370 viewDelegate.mLocationY = 0; |
| 371 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 372 true, true, 2.0f, 0.0f, 3.0f, view); |
| 373 assertEquals(6, immw.getUpdateCursorAnchorInfoCounter()); |
| 374 assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 375 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, 2.0f, 0.0f, 3.0f, |
| 376 3.0f, immw.getLastCursorAnchorInfoWrapper()); |
| 377 assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f), |
| 378 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(0)); |
| 379 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 380 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(0)
); |
| 381 assertComposingText("0", 0, immw.getLastCursorAnchorInfoWrapper()); |
| 382 assertSelection(0, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 383 immw.clearLastCursorAnchorInfoWrapper(); |
| 384 } |
| 385 |
| 386 @SmallTest |
| 387 @Feature({"Input-Text-IME"}) |
| 388 public void testSetCompositionCharacterBounds() { |
| 389 TestInputMethodManagerWrapper immw = |
| 390 new TestInputMethodManagerWrapper(null); |
| 391 TestViewDelegate viewDelegate = new TestViewDelegate(); |
| 392 TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWr
apper.Builder(); |
| 393 CursorAnchorInfoController controller = CursorAnchorInfoController.creat
eForTest( |
| 394 immw, builder, viewDelegate); |
| 395 View view = null; |
| 396 |
| 397 viewDelegate.mLocationX = 0; |
| 398 viewDelegate.mLocationY = 0; |
| 399 |
| 400 controller.focusedNodeChanged(true); |
| 401 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view
)); |
| 402 |
| 403 controller.updateTextAndSelection("01234", 1, 3, 1, 1); |
| 404 controller.setCompositionCharacterBounds(new float[]{0.0f, 1.0f, 2.0f, 3
.0f, |
| 405 4.0f, 1.1f, 6.0f, 2.9f}); |
| 406 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 407 false, false, Float.NaN, Float.NaN, Float.NaN, view); |
| 408 assertEquals(1, immw.getUpdateCursorAnchorInfoCounter()); |
| 409 assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBou
nds(0)); |
| 410 assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds
Flags(0)); |
| 411 assertEquals(new RectF(0.0f, 1.0f, 2.0f, 3.0f), |
| 412 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(1)); |
| 413 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 414 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(1)
); |
| 415 assertEquals(new RectF(4.0f, 1.1f, 6.0f, 2.9f), |
| 416 immw.getLastCursorAnchorInfoWrapper().getCharacterBounds(2)); |
| 417 assertEquals(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION, |
| 418 immw.getLastCursorAnchorInfoWrapper().getCharacterBoundsFlags(2)
); |
| 419 assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBou
nds(3)); |
| 420 assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds
Flags(3)); |
| 421 assertComposingText("12", 1, immw.getLastCursorAnchorInfoWrapper()); |
| 422 assertSelection(1, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 423 } |
| 424 |
| 425 @SmallTest |
| 426 @Feature({"Input-Text-IME"}) |
| 427 public void testUpdateTextAndSelection() { |
| 428 TestInputMethodManagerWrapper immw = |
| 429 new TestInputMethodManagerWrapper(null); |
| 430 TestViewDelegate viewDelegate = new TestViewDelegate(); |
| 431 TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWr
apper.Builder(); |
| 432 CursorAnchorInfoController controller = CursorAnchorInfoController.creat
eForTest( |
| 433 immw, builder, viewDelegate); |
| 434 View view = null; |
| 435 |
| 436 viewDelegate.mLocationX = 0; |
| 437 viewDelegate.mLocationY = 0; |
| 438 |
| 439 controller.focusedNodeChanged(true); |
| 440 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view
)); |
| 441 |
| 442 controller.updateTextAndSelection("01234", 3, 3, 1, 1); |
| 443 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 444 false, false, Float.NaN, Float.NaN, Float.NaN, view); |
| 445 assertEquals(1, immw.getUpdateCursorAnchorInfoCounter()); |
| 446 assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBou
nds(0)); |
| 447 assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds
Flags(0)); |
| 448 assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBou
nds(1)); |
| 449 assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds
Flags(1)); |
| 450 assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBou
nds(2)); |
| 451 assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds
Flags(2)); |
| 452 assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBou
nds(3)); |
| 453 assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds
Flags(3)); |
| 454 assertEquals(null, immw.getLastCursorAnchorInfoWrapper().getCharacterBou
nds(4)); |
| 455 assertEquals(0, immw.getLastCursorAnchorInfoWrapper().getCharacterBounds
Flags(4)); |
| 456 assertComposingText("", 3, immw.getLastCursorAnchorInfoWrapper()); |
| 457 assertSelection(1, 1, immw.getLastCursorAnchorInfoWrapper()); |
| 458 } |
| 459 |
| 460 @SmallTest |
| 461 @Feature({"Input-Text-IME"}) |
| 462 public void testInsertionMarker() { |
| 463 TestInputMethodManagerWrapper immw = |
| 464 new TestInputMethodManagerWrapper(null); |
| 465 TestViewDelegate viewDelegate = new TestViewDelegate(); |
| 466 TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWr
apper.Builder(); |
| 467 CursorAnchorInfoController controller = CursorAnchorInfoController.creat
eForTest( |
| 468 immw, builder, viewDelegate); |
| 469 View view = null; |
| 470 |
| 471 controller.focusedNodeChanged(true); |
| 472 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view
)); |
| 473 |
| 474 // Test no insertion marker. |
| 475 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 476 false, false, Float.NaN, Float.NaN, Float.NaN, view); |
| 477 assertEquals(1, immw.getUpdateCursorAnchorInfoCounter()); |
| 478 assertHasNoInsertionMarker(immw.getLastCursorAnchorInfoWrapper()); |
| 479 immw.clearLastCursorAnchorInfoWrapper(); |
| 480 |
| 481 // Test a visible insertion marker. |
| 482 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 483 true, true, 10.0f, 23.0f, 29.0f, view); |
| 484 assertEquals(2, immw.getUpdateCursorAnchorInfoCounter()); |
| 485 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_VISIBLE_REGION
, |
| 486 10.0f, 23.0f, 29.0f, 29.0f, immw.getLastCursorAnchorInfoWrapper(
)); |
| 487 immw.clearLastCursorAnchorInfoWrapper(); |
| 488 |
| 489 // Test a invisible insertion marker. |
| 490 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 491 true, false, 10.0f, 23.0f, 29.0f, view); |
| 492 assertEquals(3, immw.getUpdateCursorAnchorInfoCounter()); |
| 493 assertHasInsertionMarker(CursorAnchorInfoWrapper.FLAG_HAS_INVISIBLE_REGI
ON, |
| 494 10.0f, 23.0f, 29.0f, 29.0f, immw.getLastCursorAnchorInfoWrapper(
)); |
| 495 immw.clearLastCursorAnchorInfoWrapper(); |
| 496 } |
| 497 |
| 498 @SmallTest |
| 499 @Feature({"Input-Text-IME"}) |
| 500 public void testMatrix() { |
| 501 TestInputMethodManagerWrapper immw = |
| 502 new TestInputMethodManagerWrapper(null); |
| 503 TestViewDelegate viewDelegate = new TestViewDelegate(); |
| 504 TestCursorAnchorInfoWrapper.Builder builder = new TestCursorAnchorInfoWr
apper.Builder(); |
| 505 CursorAnchorInfoController controller = CursorAnchorInfoController.creat
eForTest( |
| 506 immw, builder, viewDelegate); |
| 507 View view = null; |
| 508 |
| 509 controller.focusedNodeChanged(true); |
| 510 assertTrue(controller.onRequestCursorUpdates(CURSOR_UPDATE_MONITOR, view
)); |
| 511 |
| 512 // Test no transformation |
| 513 viewDelegate.mLocationX = 0; |
| 514 viewDelegate.mLocationY = 0; |
| 515 controller.onUpdateFrameInfo(createRenderCoordinates(1.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 516 false, false, Float.NaN, Float.NaN, Float.NaN, view); |
| 517 assertEquals(1, immw.getUpdateCursorAnchorInfoCounter()); |
| 518 assertScaleAndTranslate(1.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 519 immw.clearLastCursorAnchorInfoWrapper(); |
| 520 |
| 521 // device scale factor == 2.0 |
| 522 viewDelegate.mLocationX = 0; |
| 523 viewDelegate.mLocationY = 0; |
| 524 controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 525 false, false, Float.NaN, Float.NaN, Float.NaN, view); |
| 526 assertEquals(2, immw.getUpdateCursorAnchorInfoCounter()); |
| 527 assertScaleAndTranslate(2.0f, 0.0f, 0.0f, immw.getLastCursorAnchorInfoWr
apper()); |
| 528 immw.clearLastCursorAnchorInfoWrapper(); |
| 529 |
| 530 // device scale factor == 2.0 |
| 531 // view origin == (10, 141) |
| 532 viewDelegate.mLocationX = 10; |
| 533 viewDelegate.mLocationY = 141; |
| 534 controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 1.0f, 0.0f, 0
.0f, 0.0f), |
| 535 false, false, Float.NaN, Float.NaN, Float.NaN, view); |
| 536 assertEquals(3, immw.getUpdateCursorAnchorInfoCounter()); |
| 537 assertScaleAndTranslate(2.0f, 10.0f, 141.0f, immw.getLastCursorAnchorInf
oWrapper()); |
| 538 immw.clearLastCursorAnchorInfoWrapper(); |
| 539 |
| 540 // device scale factor == 2.0 |
| 541 // root scroll offset == (1.0f, 2.0f) |
| 542 // view origin == (10, 141) |
| 543 viewDelegate.mLocationX = 10; |
| 544 viewDelegate.mLocationY = 141; |
| 545 controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 1.0f, 1.0f, 2
.0f, 0.0f), |
| 546 false, false, Float.NaN, Float.NaN, Float.NaN, view); |
| 547 assertEquals(4, immw.getUpdateCursorAnchorInfoCounter()); |
| 548 assertScaleAndTranslate(2.0f, 8.0f, 137.0f, immw.getLastCursorAnchorInfo
Wrapper()); |
| 549 immw.clearLastCursorAnchorInfoWrapper(); |
| 550 |
| 551 // device scale factor == 2.0 |
| 552 // page scale factor == 3.0f |
| 553 // root scroll offset == (1.0f, 2.0f) |
| 554 // view origin == (10, 141) |
| 555 viewDelegate.mLocationX = 10; |
| 556 viewDelegate.mLocationY = 141; |
| 557 controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 3.0f, 1.0f, 2
.0f, 0.0f), |
| 558 false, false, Float.NaN, Float.NaN, Float.NaN, view); |
| 559 assertEquals(5, immw.getUpdateCursorAnchorInfoCounter()); |
| 560 assertScaleAndTranslate(6.0f, 4.0f, 129.0f, immw.getLastCursorAnchorInfo
Wrapper()); |
| 561 immw.clearLastCursorAnchorInfoWrapper(); |
| 562 |
| 563 // device scale factor == 2.0 |
| 564 // page scale factor == 3.0f |
| 565 // root scroll offset == (1.0f, 2.0f) |
| 566 // content offset Y = 40.0f |
| 567 // view origin == (10, 141) |
| 568 viewDelegate.mLocationX = 10; |
| 569 viewDelegate.mLocationY = 141; |
| 570 controller.onUpdateFrameInfo(createRenderCoordinates(2.0f, 3.0f, 1.0f, 2
.0f, 40.0f), |
| 571 false, false, Float.NaN, Float.NaN, Float.NaN, view); |
| 572 assertEquals(6, immw.getUpdateCursorAnchorInfoCounter()); |
| 573 assertScaleAndTranslate(6.0f, 4.0f, 169.0f, immw.getLastCursorAnchorInfo
Wrapper()); |
| 574 immw.clearLastCursorAnchorInfoWrapper(); |
| 575 } |
| 576 } |
OLD | NEW |