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