1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.text.method.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertSame; 24 import static org.junit.Assert.assertTrue; 25 26 import android.app.Activity; 27 import android.app.Instrumentation; 28 import android.os.SystemClock; 29 import android.support.test.InstrumentationRegistry; 30 import android.support.test.annotation.UiThreadTest; 31 import android.support.test.filters.MediumTest; 32 import android.support.test.rule.ActivityTestRule; 33 import android.support.test.runner.AndroidJUnit4; 34 import android.text.Editable; 35 import android.text.Selection; 36 import android.text.Spannable; 37 import android.text.SpannableString; 38 import android.text.method.ArrowKeyMovementMethod; 39 import android.text.method.MetaKeyKeyListener; 40 import android.text.method.MovementMethod; 41 import android.util.TypedValue; 42 import android.view.KeyEvent; 43 import android.view.MotionEvent; 44 import android.view.View; 45 import android.view.WindowManager; 46 import android.widget.TextView; 47 import android.widget.TextView.BufferType; 48 49 import com.android.compatibility.common.util.PollingCheck; 50 51 import org.junit.Before; 52 import org.junit.Rule; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 56 /** 57 * Test {@link ArrowKeyMovementMethod}. The class is an implementation of interface 58 * {@link MovementMethod}. The typical usage of {@link MovementMethod} is tested in 59 * {@link android.widget.cts.TextViewTest} and this test case is only focused on the 60 * implementation of the methods. 61 * 62 * @see android.widget.cts.TextViewTest 63 */ 64 @MediumTest 65 @RunWith(AndroidJUnit4.class) 66 public class ArrowKeyMovementMethodTest { 67 private static final String THREE_LINES_TEXT = "first line\nsecond line\nlast line"; 68 private static final int END_OF_ALL_TEXT = THREE_LINES_TEXT.length(); 69 private static final int END_OF_1ST_LINE = THREE_LINES_TEXT.indexOf('\n'); 70 private static final int START_OF_2ND_LINE = END_OF_1ST_LINE + 1; 71 private static final int END_OF_2ND_LINE = THREE_LINES_TEXT.indexOf('\n', START_OF_2ND_LINE); 72 private static final int START_OF_3RD_LINE = END_OF_2ND_LINE + 1; 73 private static final int SPACE_IN_2ND_LINE = THREE_LINES_TEXT.indexOf(' ', START_OF_2ND_LINE); 74 75 private Instrumentation mInstrumentation; 76 private TextView mTextView; 77 private ArrowKeyMovementMethod mArrowKeyMovementMethod; 78 private Editable mEditable; 79 private MyMetaKeyKeyListener mMetaListener; 80 81 @Rule 82 public ActivityTestRule<CtsActivity> mActivityRule = new ActivityTestRule<>(CtsActivity.class); 83 84 @Before 85 public void setup() throws Throwable { 86 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 87 mMetaListener = new MyMetaKeyKeyListener(); 88 mArrowKeyMovementMethod = new ArrowKeyMovementMethod(); 89 90 mActivityRule.runOnUiThread(() -> {; 91 initTextViewWithNullLayout(); 92 93 Activity activity = mActivityRule.getActivity(); 94 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | 95 WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); 96 97 activity.setContentView(mTextView); 98 mTextView.setFocusable(true); 99 mTextView.requestFocus(); 100 }); 101 PollingCheck.waitFor(() -> mTextView.isFocused() && (mTextView.getLayout() != null)); 102 } 103 104 @Test 105 public void testConstructor() { 106 new ArrowKeyMovementMethod(); 107 } 108 109 @Test 110 public void testCanSelectArbitrarily() { 111 assertTrue(new ArrowKeyMovementMethod().canSelectArbitrarily()); 112 } 113 114 @Test 115 public void testGetInstance() { 116 MovementMethod method0 = ArrowKeyMovementMethod.getInstance(); 117 assertNotNull(method0); 118 119 MovementMethod method1 = ArrowKeyMovementMethod.getInstance(); 120 assertNotNull(method1); 121 assertSame(method0, method1); 122 } 123 124 @Test 125 public void testOnTakeFocus() throws Throwable { 126 /* 127 * The following assertions depend on whether the TextView has a layout. 128 * The text view will not get layout in setContent method but in other 129 * handler's function. Assertion which is following the setContent will 130 * not get the expecting result. It have to wait all the handlers' 131 * operations on the UiTread to finish. So all these cases are divided 132 * into several steps, setting the content at first, waiting the layout, 133 * and checking the assertion at last. 134 */ 135 verifySelection(-1); 136 mActivityRule.runOnUiThread(() -> { 137 Selection.removeSelection(mEditable); 138 mArrowKeyMovementMethod.onTakeFocus(mTextView, mEditable, View.FOCUS_UP); 139 }); 140 mInstrumentation.waitForIdleSync(); 141 verifySelection(END_OF_ALL_TEXT); 142 143 mActivityRule.runOnUiThread(() -> { 144 Selection.removeSelection(mEditable); 145 mArrowKeyMovementMethod.onTakeFocus(mTextView, mEditable, View.FOCUS_LEFT); 146 }); 147 mInstrumentation.waitForIdleSync(); 148 verifySelection(END_OF_ALL_TEXT); 149 150 mActivityRule.runOnUiThread(mTextView::setSingleLine); 151 // wait until the textView gets layout 152 mInstrumentation.waitForIdleSync(); 153 assertNotNull(mTextView.getLayout()); 154 assertEquals(1, mTextView.getLayout().getLineCount()); 155 156 mActivityRule.runOnUiThread(() -> { 157 Selection.removeSelection(mEditable); 158 mArrowKeyMovementMethod.onTakeFocus(mTextView, mEditable, View.FOCUS_UP); 159 }); 160 verifySelection(END_OF_ALL_TEXT); 161 162 mActivityRule.runOnUiThread(() -> { 163 Selection.removeSelection(mEditable); 164 mArrowKeyMovementMethod.onTakeFocus(mTextView, mEditable, View.FOCUS_LEFT); 165 }); 166 verifySelection(END_OF_ALL_TEXT); 167 } 168 169 @UiThreadTest 170 @Test 171 public void testOnTakeFocusWithNullLayout() { 172 initTextViewWithNullLayout(); 173 verifySelectEndOfContent(); 174 } 175 176 @UiThreadTest 177 @Test(expected=NullPointerException.class) 178 public void testOnTakeFocusNullView() { 179 // Should throw NullPointerException when param textView is null 180 mArrowKeyMovementMethod.onTakeFocus(null, mEditable, View.FOCUS_DOWN); 181 } 182 183 @UiThreadTest 184 @Test(expected=NullPointerException.class) 185 public void testOnTakeFocusNullSpannable() { 186 initTextViewWithNullLayout(); 187 // Should throw NullPointerException when param spannable is null 188 mArrowKeyMovementMethod.onTakeFocus(mTextView, null, View.FOCUS_DOWN); 189 } 190 191 @UiThreadTest 192 @Test 193 public void testOnKeyDownWithKeyCodeUp() { 194 // shift+alt tests 195 final KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 196 KeyEvent.KEYCODE_DPAD_UP, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON); 197 198 // first line 199 // second |line 200 // last line 201 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 202 pressBothShiftAlt(); 203 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 204 KeyEvent.KEYCODE_DPAD_UP, shiftAltEvent)); 205 // |first line 206 // second |line 207 // last line 208 verifySelection(SPACE_IN_2ND_LINE, 0); 209 210 // shift tests 211 KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP, 0, 212 KeyEvent.META_SHIFT_ON); 213 214 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 215 pressShift(); 216 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 217 KeyEvent.KEYCODE_DPAD_UP, shiftEvent)); 218 // first lin|e 219 // second |line 220 // last line 221 assertEquals(SPACE_IN_2ND_LINE, Selection.getSelectionStart(mEditable)); 222 int correspondingIn1stLine = Selection.getSelectionEnd(mEditable); 223 assertTrue(correspondingIn1stLine >= 0); 224 assertTrue(correspondingIn1stLine <= END_OF_1ST_LINE); 225 226 pressShift(); 227 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 228 KeyEvent.KEYCODE_DPAD_UP, shiftEvent)); 229 // |first line 230 // second |line 231 // last line 232 verifySelection(SPACE_IN_2ND_LINE, 0); 233 234 // alt tests 235 KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP, 0, 236 KeyEvent.META_ALT_ON); 237 238 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 239 pressAlt(); 240 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 241 KeyEvent.KEYCODE_DPAD_UP, altEvent)); 242 // |first line 243 // second line 244 // last line 245 verifySelection(0); 246 247 // no-meta tests 248 KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP, 249 0, 0); 250 251 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 252 MetaKeyKeyListener.resetMetaState(mEditable); 253 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 254 KeyEvent.KEYCODE_DPAD_UP, noMetaEvent)); 255 // first lin|e 256 // second line 257 // last line 258 verifySelection(correspondingIn1stLine); 259 260 // Move to beginning of first line (behavior changed in L) 261 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 262 KeyEvent.KEYCODE_DPAD_UP, noMetaEvent)); 263 // |first line 264 // second line 265 // last line 266 verifySelection(0); 267 268 assertFalse(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 269 KeyEvent.KEYCODE_DPAD_UP, noMetaEvent)); 270 // first lin|e 271 // second line 272 // last line 273 verifySelection(0); 274 } 275 276 @UiThreadTest 277 @Test 278 public void testOnKeyDownWithKeyCodeDown() { 279 // shift+alt tests 280 KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 281 KeyEvent.KEYCODE_DPAD_DOWN, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON); 282 283 // first line 284 // second |line 285 // last line 286 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 287 pressBothShiftAlt(); 288 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 289 KeyEvent.KEYCODE_DPAD_DOWN, shiftAltEvent)); 290 // first line 291 // second |line 292 // last line| 293 verifySelection(SPACE_IN_2ND_LINE, END_OF_ALL_TEXT); 294 295 // shift tests 296 KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN, 297 0, KeyEvent.META_SHIFT_ON); 298 299 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 300 pressShift(); 301 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 302 KeyEvent.KEYCODE_DPAD_DOWN, shiftEvent)); 303 // first line 304 // second |line 305 // last lin|e 306 assertEquals(SPACE_IN_2ND_LINE, Selection.getSelectionStart(mEditable)); 307 int correspondingIn3rdLine = Selection.getSelectionEnd(mEditable); 308 assertTrue(correspondingIn3rdLine >= START_OF_3RD_LINE); 309 assertTrue(correspondingIn3rdLine <= END_OF_ALL_TEXT); 310 311 pressShift(); 312 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 313 KeyEvent.KEYCODE_DPAD_DOWN, shiftEvent)); 314 // first line 315 // second |line 316 // last line| 317 verifySelection(SPACE_IN_2ND_LINE, END_OF_ALL_TEXT); 318 319 // alt tests 320 KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN, 0, 321 KeyEvent.META_ALT_ON); 322 323 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 324 pressAlt(); 325 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 326 KeyEvent.KEYCODE_DPAD_DOWN, altEvent)); 327 // first line 328 // second line 329 // last line| 330 verifySelection(END_OF_ALL_TEXT); 331 332 // no-meta tests 333 KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN, 334 0, 0); 335 336 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 337 MetaKeyKeyListener.resetMetaState(mEditable); 338 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 339 KeyEvent.KEYCODE_DPAD_DOWN, noMetaEvent)); 340 // first line 341 // second line 342 // last lin|e 343 verifySelection(correspondingIn3rdLine); 344 345 // move to end of last line (behavior changed in L) 346 Selection.setSelection(mEditable, END_OF_ALL_TEXT - 1); 347 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 348 KeyEvent.KEYCODE_DPAD_DOWN, noMetaEvent)); 349 // first line 350 // second line 351 // last line| 352 verifySelection(END_OF_ALL_TEXT); 353 354 assertFalse(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 355 KeyEvent.KEYCODE_DPAD_DOWN, noMetaEvent)); 356 // first line 357 // second line 358 // last line| 359 verifySelection(END_OF_ALL_TEXT); 360 } 361 362 @UiThreadTest 363 @Test 364 public void testOnKeyDownWithKeyCodeLeft() { 365 // shift+alt tests 366 KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 367 KeyEvent.KEYCODE_DPAD_LEFT, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON); 368 369 // first line 370 // second |line 371 // last line 372 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 373 pressBothShiftAlt(); 374 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 375 KeyEvent.KEYCODE_DPAD_LEFT, shiftAltEvent)); 376 // first line 377 // |second |line 378 // last line 379 verifySelection(SPACE_IN_2ND_LINE, START_OF_2ND_LINE); 380 381 pressBothShiftAlt(); 382 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 383 KeyEvent.KEYCODE_DPAD_LEFT, shiftAltEvent)); 384 // first line 385 // |second |line 386 // last line 387 verifySelection(SPACE_IN_2ND_LINE, START_OF_2ND_LINE); 388 389 // shift tests 390 KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT, 391 0, KeyEvent.META_SHIFT_ON); 392 393 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 394 pressShift(); 395 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 396 KeyEvent.KEYCODE_DPAD_LEFT, shiftEvent)); 397 // first line 398 // second| |line 399 // last line 400 verifySelection(SPACE_IN_2ND_LINE, SPACE_IN_2ND_LINE - 1); 401 402 pressShift(); 403 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 404 KeyEvent.KEYCODE_DPAD_LEFT, shiftEvent)); 405 // first line 406 // secon|d |line 407 // last line 408 verifySelection(SPACE_IN_2ND_LINE, SPACE_IN_2ND_LINE - 2); 409 410 // alt tests 411 KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT, 0, 412 KeyEvent.META_ALT_ON); 413 414 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 415 pressAlt(); 416 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 417 KeyEvent.KEYCODE_DPAD_LEFT, altEvent)); 418 // first line 419 // |second line 420 // last line 421 verifySelection(START_OF_2ND_LINE); 422 423 pressAlt(); 424 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 425 KeyEvent.KEYCODE_DPAD_LEFT, altEvent)); 426 // first line 427 // |second line 428 // last line 429 verifySelection(START_OF_2ND_LINE); 430 431 // no-meta tests 432 KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT, 433 0, 0); 434 435 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 436 MetaKeyKeyListener.resetMetaState(mEditable); 437 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 438 KeyEvent.KEYCODE_DPAD_LEFT, noMetaEvent)); 439 // first line 440 // second| line 441 // last line 442 verifySelection(SPACE_IN_2ND_LINE - 1); 443 444 Selection.setSelection(mEditable, START_OF_2ND_LINE); 445 // first line 446 // |second line 447 // last line 448 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 449 KeyEvent.KEYCODE_DPAD_LEFT, noMetaEvent)); 450 // first line| 451 // second line 452 // last line 453 verifySelection(END_OF_1ST_LINE); 454 } 455 456 @UiThreadTest 457 @Test 458 public void testOnKeyDownWithKeyCodeRight() { 459 // shift+alt tests 460 KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 461 KeyEvent.KEYCODE_DPAD_RIGHT, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON); 462 463 // first line 464 // second |line 465 // last line 466 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 467 pressBothShiftAlt(); 468 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 469 KeyEvent.KEYCODE_DPAD_RIGHT, shiftAltEvent)); 470 // first line 471 // second |line| 472 // last line 473 verifySelection(SPACE_IN_2ND_LINE, END_OF_2ND_LINE); 474 475 pressBothShiftAlt(); 476 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 477 KeyEvent.KEYCODE_DPAD_RIGHT, shiftAltEvent)); 478 // first line 479 // second |line| 480 // last line 481 verifySelection(SPACE_IN_2ND_LINE, END_OF_2ND_LINE); 482 483 // shift tests 484 KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT, 485 0, KeyEvent.META_SHIFT_ON); 486 487 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 488 pressShift(); 489 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 490 KeyEvent.KEYCODE_DPAD_RIGHT, shiftEvent)); 491 // first line 492 // second |l|ine 493 // last line 494 verifySelection(SPACE_IN_2ND_LINE, SPACE_IN_2ND_LINE + 1); 495 496 pressShift(); 497 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 498 KeyEvent.KEYCODE_DPAD_RIGHT, shiftEvent)); 499 // first line 500 // second |li|ne 501 // last line 502 verifySelection(SPACE_IN_2ND_LINE, SPACE_IN_2ND_LINE + 2); 503 504 // alt tests 505 KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT, 506 0, KeyEvent.META_ALT_ON); 507 508 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 509 pressAlt(); 510 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 511 KeyEvent.KEYCODE_DPAD_RIGHT, altEvent)); 512 // first line 513 // second line| 514 // last line 515 verifySelection(END_OF_2ND_LINE); 516 517 pressAlt(); 518 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 519 KeyEvent.KEYCODE_DPAD_RIGHT, altEvent)); 520 // first line 521 // second line| 522 // last line 523 verifySelection(END_OF_2ND_LINE); 524 525 // no-meta tests 526 KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 527 KeyEvent.KEYCODE_DPAD_RIGHT, 0, 0); 528 529 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 530 MetaKeyKeyListener.resetMetaState(mEditable); 531 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 532 KeyEvent.KEYCODE_DPAD_RIGHT, noMetaEvent)); 533 // first line 534 // second l|ine 535 // last line 536 verifySelection(SPACE_IN_2ND_LINE + 1); 537 538 Selection.setSelection(mEditable, END_OF_2ND_LINE); 539 // first line 540 // second line| 541 // last line 542 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 543 KeyEvent.KEYCODE_DPAD_RIGHT, noMetaEvent)); 544 // first line 545 // second line 546 // |last line 547 verifySelection(START_OF_3RD_LINE); 548 } 549 550 @UiThreadTest 551 @Test 552 public void testOnKeyDownWithKeyCodePageUp() { 553 // shift+alt tests 554 KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 555 KeyEvent.KEYCODE_PAGE_UP, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON); 556 557 // first line 558 // second |line 559 // last line 560 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 561 pressBothShiftAlt(); 562 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 563 KeyEvent.KEYCODE_PAGE_UP, shiftAltEvent)); 564 // |first line 565 // second |line 566 // last line 567 verifySelection(SPACE_IN_2ND_LINE, 0); 568 569 // shift tests 570 KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_PAGE_UP, 571 0, KeyEvent.META_SHIFT_ON); 572 573 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 574 pressShift(); 575 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 576 KeyEvent.KEYCODE_PAGE_UP, shiftEvent)); 577 // |first line 578 // second |line 579 // last line 580 verifySelection(SPACE_IN_2ND_LINE, 0); 581 582 // alt tests 583 KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_PAGE_UP, 0, 584 KeyEvent.META_ALT_ON); 585 586 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 587 pressAlt(); 588 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 589 KeyEvent.KEYCODE_PAGE_UP, altEvent)); 590 // |first line 591 // second line 592 // last line 593 verifySelection(0); 594 595 // no-meta tests 596 KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_PAGE_UP, 597 0, 0); 598 599 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 600 MetaKeyKeyListener.resetMetaState(mEditable); 601 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 602 KeyEvent.KEYCODE_PAGE_UP, noMetaEvent)); 603 // |first line 604 // second line 605 // last line 606 verifySelection(0); 607 } 608 609 @UiThreadTest 610 @Test 611 public void testOnKeyDownWithKeyCodePageDown() { 612 // shift+alt tests 613 KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 614 KeyEvent.KEYCODE_PAGE_DOWN, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON); 615 616 // first line 617 // second |line 618 // last line 619 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 620 pressBothShiftAlt(); 621 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 622 KeyEvent.KEYCODE_PAGE_DOWN, shiftAltEvent)); 623 // first line 624 // second |line 625 // last line| 626 verifySelection(SPACE_IN_2ND_LINE, END_OF_ALL_TEXT); 627 628 // shift tests 629 KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_PAGE_DOWN, 630 0, KeyEvent.META_SHIFT_ON); 631 632 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 633 pressShift(); 634 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 635 KeyEvent.KEYCODE_PAGE_DOWN, shiftEvent)); 636 // first line 637 // second |line 638 // last line| 639 verifySelection(SPACE_IN_2ND_LINE, END_OF_ALL_TEXT); 640 641 // alt tests 642 KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_PAGE_DOWN, 0, 643 KeyEvent.META_ALT_ON); 644 645 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 646 pressAlt(); 647 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 648 KeyEvent.KEYCODE_PAGE_DOWN, altEvent)); 649 // first line 650 // second line 651 // last line| 652 verifySelection(END_OF_ALL_TEXT); 653 654 // no-meta tests 655 KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_PAGE_DOWN, 656 0, 0); 657 658 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 659 MetaKeyKeyListener.resetMetaState(mEditable); 660 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 661 KeyEvent.KEYCODE_PAGE_DOWN, noMetaEvent)); 662 // first line 663 // second line 664 // last line| 665 verifySelection(END_OF_ALL_TEXT); 666 } 667 668 @UiThreadTest 669 @Test 670 public void testOnKeyDownWithKeyCodeMoveHome() { 671 // shift+ctrl tests 672 KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 673 KeyEvent.KEYCODE_MOVE_HOME, 0, KeyEvent.META_SHIFT_ON | KeyEvent.META_CTRL_ON); 674 675 // first line 676 // second |line 677 // last line 678 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 679 pressShift(); 680 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 681 KeyEvent.KEYCODE_MOVE_HOME, shiftAltEvent)); 682 // |first line 683 // second |line 684 // last line 685 verifySelection(SPACE_IN_2ND_LINE, 0); 686 687 // shift tests 688 KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MOVE_HOME, 689 0, KeyEvent.META_SHIFT_ON); 690 691 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 692 pressShift(); 693 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 694 KeyEvent.KEYCODE_MOVE_HOME, shiftEvent)); 695 // first line 696 // |second |line 697 // last line 698 verifySelection(SPACE_IN_2ND_LINE, START_OF_2ND_LINE); 699 700 pressShift(); 701 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 702 KeyEvent.KEYCODE_MOVE_HOME, shiftEvent)); 703 // first line 704 // |second |line 705 // last line 706 verifySelection(SPACE_IN_2ND_LINE, START_OF_2ND_LINE); 707 708 // ctrl tests 709 KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MOVE_HOME, 0, 710 KeyEvent.META_CTRL_ON); 711 712 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 713 MetaKeyKeyListener.resetMetaState(mEditable); 714 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 715 KeyEvent.KEYCODE_MOVE_HOME, altEvent)); 716 // |first line 717 // second line 718 // last line 719 verifySelection(0); 720 721 // no-meta tests 722 KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MOVE_HOME, 723 0, 0); 724 725 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 726 MetaKeyKeyListener.resetMetaState(mEditable); 727 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 728 KeyEvent.KEYCODE_MOVE_HOME, noMetaEvent)); 729 // first line 730 // |second line 731 // last line 732 verifySelection(START_OF_2ND_LINE); 733 734 MetaKeyKeyListener.resetMetaState(mEditable); 735 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 736 KeyEvent.KEYCODE_MOVE_HOME, noMetaEvent)); 737 // first line 738 // |second line 739 // last line 740 verifySelection(START_OF_2ND_LINE); 741 } 742 743 @UiThreadTest 744 @Test 745 public void testOnKeyDownWithKeyCodeMoveEnd() { 746 // shift+ctrl tests 747 KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 748 KeyEvent.KEYCODE_MOVE_END, 0, KeyEvent.META_SHIFT_ON | KeyEvent.META_CTRL_ON); 749 750 // first line 751 // second |line 752 // last line 753 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 754 pressShift(); 755 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 756 KeyEvent.KEYCODE_MOVE_END, shiftAltEvent)); 757 // first line 758 // second |line 759 // last line| 760 verifySelection(SPACE_IN_2ND_LINE, END_OF_ALL_TEXT); 761 762 // shift tests 763 KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MOVE_END, 764 0, KeyEvent.META_SHIFT_ON); 765 766 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 767 pressShift(); 768 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 769 KeyEvent.KEYCODE_MOVE_END, shiftEvent)); 770 // first line 771 // second |line| 772 // last line 773 verifySelection(SPACE_IN_2ND_LINE, END_OF_2ND_LINE); 774 775 pressShift(); 776 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 777 KeyEvent.KEYCODE_MOVE_END, shiftEvent)); 778 // first line 779 // second |line| 780 // last line 781 verifySelection(SPACE_IN_2ND_LINE, END_OF_2ND_LINE); 782 783 // ctrl tests 784 KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MOVE_END, 0, 785 KeyEvent.META_CTRL_ON); 786 787 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 788 MetaKeyKeyListener.resetMetaState(mEditable); 789 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 790 KeyEvent.KEYCODE_MOVE_END, altEvent)); 791 // first line 792 // second line 793 // last line| 794 verifySelection(END_OF_ALL_TEXT); 795 796 // no-meta tests 797 KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MOVE_END, 798 0, 0); 799 800 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 801 MetaKeyKeyListener.resetMetaState(mEditable); 802 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 803 KeyEvent.KEYCODE_MOVE_END, noMetaEvent)); 804 // first line 805 // second line| 806 // last line 807 verifySelection(END_OF_2ND_LINE); 808 809 MetaKeyKeyListener.resetMetaState(mEditable); 810 assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 811 KeyEvent.KEYCODE_MOVE_END, noMetaEvent)); 812 // first line 813 // second line| 814 // last line 815 verifySelection(END_OF_2ND_LINE); 816 } 817 818 @UiThreadTest 819 @Test(expected=NullPointerException.class) 820 public void testOnKeyDownWithNullLayout() { 821 initTextViewWithNullLayout(); 822 // Should throw NullPointerException when layout of the view is null 823 mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, KeyEvent.KEYCODE_DPAD_RIGHT, null); 824 } 825 826 @UiThreadTest 827 @Test 828 public void testOnKeyOther() { 829 // first line 830 // second |line 831 // last line 832 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 833 834 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 835 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_DPAD_CENTER, 2))); 836 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 837 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_0, 2))); 838 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 839 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_E, 2))); 840 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 841 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_UNKNOWN, 2))); 842 843 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 844 new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP, 0))); 845 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 846 new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN, 0))); 847 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 848 new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT, 0))); 849 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 850 new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT, 0))); 851 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 852 new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_PAGE_UP, 0))); 853 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 854 new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_PAGE_DOWN, 0))); 855 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 856 new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MOVE_HOME, 0))); 857 assertFalse(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 858 new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MOVE_END, 0))); 859 860 // only repeat arrow key, page up/down and move home/end events get handled 861 assertTrue(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 862 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_DPAD_UP, 2))); 863 assertTrue(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 864 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_DPAD_DOWN, 2))); 865 assertTrue(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 866 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_DPAD_LEFT, 2))); 867 assertTrue(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 868 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_DPAD_RIGHT, 2))); 869 assertTrue(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 870 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_PAGE_UP, 2))); 871 assertTrue(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 872 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_PAGE_DOWN, 2))); 873 assertTrue(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 874 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_MOVE_HOME, 2))); 875 assertTrue(mArrowKeyMovementMethod.onKeyOther(mTextView, mEditable, 876 new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_MOVE_END, 2))); 877 } 878 879 @UiThreadTest 880 @Test 881 public void testOnKeyDownWithOtherKeyCode() { 882 // first line 883 // second |line 884 // last line 885 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 886 887 assertFalse(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 888 KeyEvent.KEYCODE_DPAD_CENTER, new KeyEvent(KeyEvent.ACTION_DOWN, 889 KeyEvent.KEYCODE_DPAD_CENTER))); 890 assertFalse(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 891 KeyEvent.KEYCODE_0, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0))); 892 assertFalse(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 893 KeyEvent.KEYCODE_E, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_E))); 894 assertFalse(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, 895 KeyEvent.KEYCODE_UNKNOWN, new KeyEvent(KeyEvent.ACTION_DOWN, 896 KeyEvent.KEYCODE_UNKNOWN))); 897 } 898 899 @UiThreadTest 900 @Test 901 public void testOnTouchEvent() throws Throwable { 902 long now = SystemClock.currentThreadTimeMillis(); 903 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 904 assertFalse(mArrowKeyMovementMethod.onTouchEvent(mTextView, mEditable, 905 MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 1, 1, 0))); 906 verifySelection(SPACE_IN_2ND_LINE); 907 908 assertFalse(mArrowKeyMovementMethod.onTouchEvent(mTextView, mEditable, 909 MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 1, 1, 910 KeyEvent.META_SHIFT_ON))); 911 verifySelection(SPACE_IN_2ND_LINE); 912 } 913 914 @UiThreadTest 915 @Test 916 public void testOnTouchEventWithNullLayout() { 917 initTextViewWithNullLayout(); 918 mTextView.setFocusable(true); 919 mTextView.requestFocus(); 920 assertTrue(mTextView.isFocused()); 921 922 long now = SystemClock.currentThreadTimeMillis(); 923 assertFalse(mArrowKeyMovementMethod.onTouchEvent(mTextView, mEditable, 924 MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 1, 1, 0))); 925 } 926 927 @UiThreadTest 928 @Test 929 public void testOnTouchEventWithoutFocus() { 930 long now = SystemClock.currentThreadTimeMillis(); 931 Selection.setSelection(mEditable, SPACE_IN_2ND_LINE); 932 assertFalse(mArrowKeyMovementMethod.onTouchEvent(mTextView, mEditable, 933 MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 1, 1, 0))); 934 verifySelection(SPACE_IN_2ND_LINE); 935 } 936 937 @UiThreadTest 938 @Test(expected=NullPointerException.class) 939 public void testOnTouchEventNullView() { 940 // Should throw NullPointerException when param textView is null 941 mArrowKeyMovementMethod.onTouchEvent(null, mEditable, MotionEvent.obtain(0, 0, 0, 1, 1, 0)); 942 } 943 944 @UiThreadTest 945 @Test(expected=NullPointerException.class) 946 public void testOnTouchEventNullSpannable() { 947 initTextViewWithNullLayout(); 948 // Should throw NullPointerException when param spannable is null 949 mArrowKeyMovementMethod.onTouchEvent(mTextView, null, MotionEvent.obtain(0, 0, 0, 1, 1, 0)); 950 } 951 952 @UiThreadTest 953 @Test(expected=NullPointerException.class) 954 public void testOnTouchEventNullEvent() { 955 initTextViewWithNullLayout(); 956 // Should throw NullPointerException when param motionEvent is null 957 mArrowKeyMovementMethod.onTouchEvent(mTextView, mEditable, null); 958 } 959 960 @Test 961 public void testInitialize() { 962 Spannable spannable = new SpannableString("test content"); 963 ArrowKeyMovementMethod method = new ArrowKeyMovementMethod(); 964 965 assertEquals(-1, Selection.getSelectionStart(spannable)); 966 assertEquals(-1, Selection.getSelectionEnd(spannable)); 967 method.initialize(null, spannable); 968 assertEquals(0, Selection.getSelectionStart(spannable)); 969 assertEquals(0, Selection.getSelectionEnd(spannable)); 970 971 Selection.setSelection(spannable, 2); 972 assertEquals(2, Selection.getSelectionStart(spannable)); 973 assertEquals(2, Selection.getSelectionEnd(spannable)); 974 method.initialize(null, spannable); 975 assertEquals(0, Selection.getSelectionStart(spannable)); 976 assertEquals(0, Selection.getSelectionEnd(spannable)); 977 } 978 979 @Test(expected=NullPointerException.class) 980 public void testIntializeNullSpannable() { 981 ArrowKeyMovementMethod method = new ArrowKeyMovementMethod(); 982 // Should throw NullPointerException when param spannable is null 983 method.initialize(mTextView, null); 984 } 985 986 @UiThreadTest 987 @Test 988 public void testOnTrackballEven() { 989 assertFalse(mArrowKeyMovementMethod.onTrackballEvent(mTextView, mEditable, 990 MotionEvent.obtain(0, 0, 0, 1, 1, 0))); 991 992 initTextViewWithNullLayout(); 993 994 assertFalse(mArrowKeyMovementMethod.onTrackballEvent(mTextView, mEditable, 995 MotionEvent.obtain(0, 0, 0, 1, 1, 0))); 996 997 assertFalse(mArrowKeyMovementMethod.onTrackballEvent(mTextView, null, 998 MotionEvent.obtain(0, 0, 0, 1, 1, 0))); 999 1000 assertFalse(mArrowKeyMovementMethod.onTrackballEvent(mTextView, mEditable, null)); 1001 } 1002 1003 @UiThreadTest 1004 @Test 1005 public void testOnKeyUp() { 1006 ArrowKeyMovementMethod method = new ArrowKeyMovementMethod(); 1007 SpannableString spannable = new SpannableString("Test Content"); 1008 KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0); 1009 TextView view = new TextViewNoIme(mActivityRule.getActivity()); 1010 view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10); 1011 1012 assertFalse(method.onKeyUp(view, spannable, KeyEvent.KEYCODE_0, event)); 1013 assertFalse(method.onKeyUp(null, null, 0, null)); 1014 assertFalse(method.onKeyUp(null, spannable, KeyEvent.KEYCODE_0, event)); 1015 assertFalse(method.onKeyUp(view, null, KeyEvent.KEYCODE_0, event)); 1016 assertFalse(method.onKeyUp(view, spannable, 0, event)); 1017 assertFalse(method.onKeyUp(view, spannable, KeyEvent.KEYCODE_0, null)); 1018 } 1019 1020 private static final String TEXT_WORDS = 1021 "Lorem ipsum; dolor sit \u00e4met, conse\u0ca0_\u0ca0ctetur? Adipiscing" 1022 + ".elit.integ\u00e9r. Etiam tristique\ntortor nec ?:? \n\n" 1023 + "lectus porta consequ\u00e4t... LOReM iPSuM"; 1024 1025 @UiThreadTest 1026 @Test 1027 public void testFollowingWordStartToEnd() { 1028 1029 // NOTE: there seems to be much variation in how word boundaries are 1030 // navigated; the behaviors asserted here were derived from Google 1031 // Chrome 10.0.648.133 beta. 1032 1033 initTextViewWithNullLayout(TEXT_WORDS); 1034 1035 // |Lorem ipsum; dolor sit $met, 1036 Selection.setSelection(mEditable, 0); 1037 verifySelection(0); 1038 1039 // Lorem| ipsum; dolor sit $met, 1040 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1041 verifySelection(5); 1042 1043 // Lorem ipsum|; dolor sit $met, 1044 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1045 verifySelection(11); 1046 1047 // Lorem ipsum; dolor| sit $met, 1048 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1049 verifySelection(18); 1050 1051 // Lorem ipsum; dolor sit| $met, 1052 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1053 verifySelection(22); 1054 1055 // $met|, conse$_$ctetur$ Adipiscing.elit.integ$r. 1056 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1057 verifySelection(27); 1058 1059 // $met, conse$_$ctetur|$ Adipiscing.elit.integ$r. 1060 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1061 verifySelection(43); 1062 1063 // TODO: enable these two additional word breaks when implemented 1064 // // $met, conse$_$ctetur$ Adipiscing|.elit.integ$r. 1065 // assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1066 // verifySelection(61); 1067 // 1068 // // $met, conse$_$ctetur$ Adipiscing.elit|.integ$r. 1069 // assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1070 // verifySelection(66); 1071 1072 // $met, conse$_$ctetur$ Adipiscing.elit.integ$r|. 1073 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1074 verifySelection(74); 1075 1076 // integ$r. Etiam| tristique$tortor nec ?:? $$lectus porta 1077 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1078 verifySelection(81); 1079 1080 // integ$r. Etiam tristique|$tortor nec ?:? $$lectus porta 1081 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1082 verifySelection(94); 1083 1084 // integ$r. Etiam tristique$tortor| nec ?:? $$lectus porta 1085 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1086 verifySelection(101); 1087 1088 // integ$r. Etiam tristique$tortor nec| ?:? $$lectus porta 1089 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1090 verifySelection(105); 1091 1092 // integ$r. Etiam tristique$tortor nec ?:? $$lectus| porta 1093 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1094 verifySelection(123); 1095 1096 // $$lectus porta| consequ$t... LOReM iPSuM 1097 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1098 verifySelection(129); 1099 1100 // $$lectus porta consequ$t|... LOReM iPSuM 1101 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1102 verifySelection(139); 1103 1104 // $$lectus porta consequ$t... LOReM| iPSuM 1105 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1106 verifySelection(149); 1107 1108 // $$lectus porta consequ$t... LOReM iPSuM| 1109 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1110 verifySelection(155); 1111 1112 // keep trying to push beyond end, which should fail 1113 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1114 verifySelection(155); 1115 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1116 verifySelection(155); 1117 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1118 verifySelection(155); 1119 1120 } 1121 1122 @UiThreadTest 1123 @Test 1124 public void testPrecedingWordEndToStart() { 1125 1126 // NOTE: there seems to be much variation in how word boundaries are 1127 // navigated; the behaviors asserted here were derived from Google 1128 // Chrome 10.0.648.133 beta. 1129 1130 initTextViewWithNullLayout(TEXT_WORDS); 1131 1132 // $$lectus porta consequ$t... LOReM iPSuM| 1133 Selection.setSelection(mEditable, mEditable.length()); 1134 verifySelection(155); 1135 1136 // $$lectus porta consequ$t... LOReM |iPSuM 1137 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1138 verifySelection(150); 1139 1140 // $$lectus porta consequ$t... |LOReM iPSuM 1141 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1142 verifySelection(144); 1143 1144 // $$lectus porta |consequ$t... LOReM iPSuM 1145 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1146 verifySelection(130); 1147 1148 // $$lectus |porta consequ$t... LOReM iPSuM 1149 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1150 verifySelection(124); 1151 1152 // integ$r. Etiam tristique$tortor nec ?:? $$|lectus 1153 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1154 verifySelection(117); 1155 1156 // integ$r. Etiam tristique$tortor |nec ?:? $$lectus 1157 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1158 verifySelection(102); 1159 1160 // integ$r. Etiam tristique$|tortor nec ?:? $$lectus 1161 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1162 verifySelection(95); 1163 1164 // integ$r. Etiam |tristique$tortor nec ?:? $$lectus 1165 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1166 verifySelection(85); 1167 1168 // integ$r. |Etiam tristique$tortor nec ?:? $$lectus 1169 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1170 verifySelection(76); 1171 1172 // TODO: enable these two additional word breaks when implemented 1173 // // dolor sit $met, conse$_$ctetur$ Adipiscing.elit.|integ$r. 1174 // assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1175 // verifySelection(67); 1176 // 1177 // // dolor sit $met, conse$_$ctetur$ Adipiscing.|elit.integ$r. 1178 // assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1179 // verifySelection(62); 1180 1181 // dolor sit $met, conse$_$ctetur$ |Adipiscing.elit.integ$r. 1182 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1183 verifySelection(51); 1184 1185 // dolor sit $met, |conse$_$ctetur$ Adipiscing.elit.integ$r. 1186 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1187 verifySelection(29); 1188 1189 // dolor sit |$met, conse$_$ctetur$ Adipiscing.elit.integ$r. 1190 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1191 verifySelection(23); 1192 1193 // Lorem ipsum; dolor |sit $met 1194 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1195 verifySelection(19); 1196 1197 // Lorem ipsum; |dolor sit $met 1198 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1199 verifySelection(13); 1200 1201 // Lorem |ipsum; dolor sit $met 1202 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1203 verifySelection(6); 1204 1205 // |Lorem ipsum; dolor sit $met 1206 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1207 verifySelection(0); 1208 1209 // keep trying to push before beginning, which should fail 1210 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1211 verifySelection(0); 1212 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1213 verifySelection(0); 1214 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1215 verifySelection(0); 1216 1217 } 1218 1219 private static final String TEXT_WORDS_WITH_NUMBERS = 1220 "Lorem ipsum123,456.90 dolor sit.. 4-0.0=2 ADipiscing4"; 1221 1222 @UiThreadTest 1223 @Test 1224 public void testFollowingWordStartToEndWithNumbers() { 1225 1226 initTextViewWithNullLayout(TEXT_WORDS_WITH_NUMBERS); 1227 1228 // |Lorem ipsum123,456.90 dolor sit.. 4-0.0=2 ADipiscing4 1229 Selection.setSelection(mEditable, 0); 1230 verifySelection(0); 1231 1232 // Lorem| ipsum123,456.90 dolor sit.. 4-0.0=2 ADipiscing4 1233 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1234 verifySelection(5); 1235 1236 // Lorem ipsum123,456.90| dolor sit.. 4-0.0=2 ADipiscing4 1237 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1238 verifySelection(21); 1239 1240 // Lorem ipsum123,456.90 dolor| sit.. 4-0.0=2 ADipiscing4 1241 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1242 verifySelection(29); 1243 1244 // Lorem ipsum123,456.90 dolor sit|.. 4-0.0=2 ADipiscing4 1245 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1246 verifySelection(33); 1247 1248 // Lorem ipsum123,456.90 dolor sit.. 4|-0.0=2 ADipiscing4 1249 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1250 verifySelection(37); 1251 1252 // Lorem ipsum123,456.90 dolor sit.. 4-0.0|=2 ADipiscing4 1253 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1254 verifySelection(41); 1255 1256 // Lorem ipsum123,456.90 dolor sit.. 4-0.0=2| ADipiscing4 1257 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1258 verifySelection(43); 1259 1260 // Lorem ipsum123,456.90 dolor sit.. 4-0.0=2 ADipiscing4| 1261 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1262 verifySelection(55); 1263 1264 // keep trying to push beyond end, which should fail 1265 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1266 verifySelection(55); 1267 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1268 verifySelection(55); 1269 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1270 verifySelection(55); 1271 1272 } 1273 1274 @UiThreadTest 1275 @Test 1276 public void testFollowingWordEndToStartWithNumbers() { 1277 1278 initTextViewWithNullLayout(TEXT_WORDS_WITH_NUMBERS); 1279 1280 // Lorem ipsum123,456.90 dolor sit.. 4-0.0=2 ADipiscing4| 1281 Selection.setSelection(mEditable, mEditable.length()); 1282 verifySelection(55); 1283 1284 // Lorem ipsum123,456.90 dolor sit.. 4-0.0=2 |ADipiscing4 1285 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1286 verifySelection(44); 1287 1288 // Lorem ipsum123,456.90 dolor sit.. 4-0.0=|2 ADipiscing4 1289 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1290 verifySelection(42); 1291 1292 // Lorem ipsum123,456.90 dolor sit.. 4-|0.0=2 ADipiscing4 1293 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1294 verifySelection(38); 1295 1296 // Lorem ipsum123,456.90 dolor sit.. |4-0.0=2 ADipiscing4 1297 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1298 verifySelection(36); 1299 1300 // Lorem ipsum123,456.90 dolor |sit.. 4-0.0=2 ADipiscing4 1301 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1302 verifySelection(30); 1303 1304 // Lorem ipsum123,456.90 |dolor sit.. 4-0.0=2 ADipiscing4 1305 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1306 verifySelection(24); 1307 1308 // Lorem |ipsum123,456.90 dolor sit.. 4-0.0=2 ADipiscing4 1309 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1310 verifySelection(6); 1311 1312 // |Lorem ipsum123,456.90 dolor sit.. 4-0.0=2 ADipiscing4 1313 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1314 verifySelection(0); 1315 1316 // keep trying to push before beginning, which should fail 1317 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1318 verifySelection(0); 1319 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1320 verifySelection(0); 1321 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1322 verifySelection(0); 1323 1324 } 1325 1326 private static final String TEXT_WORDS_WITH_1CHAR_FINAL_WORD = "abc d"; 1327 1328 @UiThreadTest 1329 @Test 1330 public void testFollowingWordStartToEndWithOneCharFinalWord() { 1331 1332 initTextViewWithNullLayout(TEXT_WORDS_WITH_1CHAR_FINAL_WORD); 1333 1334 // |abc d 1335 Selection.setSelection(mEditable, 0); 1336 verifySelection(0); 1337 1338 // abc| d 1339 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1340 verifySelection(3); 1341 1342 // abc d| 1343 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1344 verifySelection(mEditable.length()); 1345 1346 } 1347 1348 @UiThreadTest 1349 @Test 1350 public void testFollowingWordEndToStartWithOneCharFinalWord() { 1351 1352 initTextViewWithNullLayout(TEXT_WORDS_WITH_1CHAR_FINAL_WORD); 1353 1354 // abc d| 1355 Selection.setSelection(mEditable, mEditable.length()); 1356 verifySelection(5); 1357 1358 // abc |d 1359 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1360 verifySelection(4); 1361 1362 // |abc d 1363 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1364 verifySelection(0); 1365 1366 } 1367 1368 @UiThreadTest 1369 @Test 1370 public void testMovementFromMiddleOfWord() { 1371 1372 initTextViewWithNullLayout("before word after"); 1373 verifyMoveFromInsideWord(7, 10); 1374 1375 // Surrogate characters: bairkan should be considered as a standard letter 1376 final String BAIRKAN = "\uD800\uDF31"; 1377 1378 initTextViewWithNullLayout("before wo" + BAIRKAN + "rd after"); 1379 verifyMoveFromInsideWord(7, 12); 1380 1381 initTextViewWithNullLayout("before " + BAIRKAN + BAIRKAN + "xx after"); 1382 verifyMoveFromInsideWord(7, 12); 1383 1384 initTextViewWithNullLayout("before xx" + BAIRKAN + BAIRKAN + " after"); 1385 verifyMoveFromInsideWord(7, 12); 1386 1387 initTextViewWithNullLayout("before x" + BAIRKAN + "x" + BAIRKAN + " after"); 1388 verifyMoveFromInsideWord(7, 12); 1389 1390 initTextViewWithNullLayout("before " + BAIRKAN + "x" + BAIRKAN + "x after"); 1391 verifyMoveFromInsideWord(7, 12); 1392 1393 initTextViewWithNullLayout("before " + BAIRKAN + BAIRKAN + BAIRKAN + " after"); 1394 verifyMoveFromInsideWord(7, 12); 1395 } 1396 1397 private void verifyMoveFromInsideWord(int wordStart, int wordEnd) { 1398 1399 CharSequence text = mTextView.getText(); 1400 1401 // Check following always goes at the end of the word 1402 for (int offset = wordStart; offset != wordEnd + 1; offset++) { 1403 // Skip positions located between a pair of surrogate characters 1404 if (Character.isSurrogatePair(text.charAt(offset - 1), text.charAt(offset))) { 1405 continue; 1406 } 1407 Selection.setSelection(mEditable, offset); 1408 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_RIGHT)); 1409 verifySelection(wordEnd + 1); 1410 } 1411 1412 // Check preceding always goes at the beginning of the word 1413 for (int offset = wordEnd + 1; offset != wordStart; offset--) { 1414 if (Character.isSurrogatePair(text.charAt(offset - 1), text.charAt(offset))) { 1415 continue; 1416 } 1417 Selection.setSelection(mEditable, offset); 1418 assertTrue(pressCtrlChord(KeyEvent.KEYCODE_DPAD_LEFT)); 1419 verifySelection(wordStart); 1420 } 1421 } 1422 1423 private void initTextViewWithNullLayout() { 1424 initTextViewWithNullLayout(THREE_LINES_TEXT); 1425 } 1426 1427 private void initTextViewWithNullLayout(CharSequence text) { 1428 mTextView = new TextViewNoIme(mActivityRule.getActivity()); 1429 mTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10); 1430 mTextView.setText(text, BufferType.EDITABLE); 1431 assertNull(mTextView.getLayout()); 1432 mEditable = (Editable) mTextView.getText(); 1433 } 1434 1435 private void pressMetaKey(int metakey, int expectedState) { 1436 mMetaListener.onKeyDown(null, mEditable, metakey, null); 1437 assertEquals(1, MetaKeyKeyListener.getMetaState(mEditable, expectedState)); 1438 } 1439 1440 private void pressShift() { 1441 MetaKeyKeyListener.resetMetaState(mEditable); 1442 pressMetaKey(KeyEvent.KEYCODE_SHIFT_LEFT, MetaKeyKeyListener.META_SHIFT_ON); 1443 } 1444 1445 private void pressAlt() { 1446 MetaKeyKeyListener.resetMetaState(mEditable); 1447 pressMetaKey(KeyEvent.KEYCODE_ALT_LEFT, MetaKeyKeyListener.META_ALT_ON); 1448 } 1449 1450 private void pressBothShiftAlt() { 1451 MetaKeyKeyListener.resetMetaState(mEditable); 1452 pressMetaKey(KeyEvent.KEYCODE_SHIFT_LEFT, MetaKeyKeyListener.META_SHIFT_ON); 1453 pressMetaKey(KeyEvent.KEYCODE_ALT_LEFT, MetaKeyKeyListener.META_ALT_ON); 1454 } 1455 1456 private boolean pressCtrlChord(int keyCode) { 1457 final long now = System.currentTimeMillis(); 1458 final KeyEvent keyEvent = new KeyEvent( 1459 now, now, KeyEvent.ACTION_DOWN, keyCode, 0, KeyEvent.META_CTRL_LEFT_ON); 1460 return mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable, keyCode, keyEvent); 1461 } 1462 1463 private void verifySelection(int expectedPosition) { 1464 verifySelection(expectedPosition, expectedPosition); 1465 } 1466 1467 private void verifySelection(int expectedStart, int expectedEnd) { 1468 final int actualStart = Selection.getSelectionStart(mEditable); 1469 final int actualEnd = Selection.getSelectionEnd(mEditable); 1470 1471 verifyCharSequenceIndexEquals(mEditable, expectedStart, actualStart); 1472 verifyCharSequenceIndexEquals(mEditable, expectedEnd, actualEnd); 1473 } 1474 1475 private static void verifyCharSequenceIndexEquals(CharSequence text, int expected, int actual) { 1476 final String message = "expected <" + getCursorSnippet(text, expected) + "> but was <" 1477 + getCursorSnippet(text, actual) + ">"; 1478 assertEquals(message, expected, actual); 1479 } 1480 1481 private static String getCursorSnippet(CharSequence text, int index) { 1482 if (index >= 0 && index < text.length()) { 1483 return text.subSequence(Math.max(0, index - 5), index) + "|" 1484 + text.subSequence(index, Math.min(text.length() - 1, index + 5)); 1485 } else { 1486 return null; 1487 } 1488 } 1489 1490 private void verifySelectEndOfContent() { 1491 Selection.removeSelection(mEditable); 1492 mArrowKeyMovementMethod.onTakeFocus(mTextView, mEditable, View.FOCUS_DOWN); 1493 verifySelection(END_OF_ALL_TEXT); 1494 1495 Selection.removeSelection(mEditable); 1496 mArrowKeyMovementMethod.onTakeFocus(mTextView, mEditable, View.FOCUS_RIGHT); 1497 verifySelection(END_OF_ALL_TEXT); 1498 1499 verifySelectEndOfContentExceptFocusForward(); 1500 } 1501 1502 private void verifySelectEndOfContentExceptFocusForward() { 1503 Selection.removeSelection(mEditable); 1504 mArrowKeyMovementMethod.onTakeFocus(mTextView, mEditable, View.FOCUS_UP); 1505 verifySelection(END_OF_ALL_TEXT); 1506 1507 Selection.removeSelection(mEditable); 1508 mArrowKeyMovementMethod.onTakeFocus(mTextView, mEditable, View.FOCUS_LEFT); 1509 verifySelection(END_OF_ALL_TEXT); 1510 } 1511 1512 private static class MyMetaKeyKeyListener extends MetaKeyKeyListener { 1513 } 1514 } 1515