OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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.app.Activity; |
| 9 import android.content.ClipData; |
| 10 import android.content.ClipboardManager; |
| 11 import android.content.Context; |
| 12 import android.os.Handler; |
| 13 import android.text.TextUtils; |
| 14 import android.util.Pair; |
| 15 import android.view.KeyEvent; |
| 16 import android.view.View; |
| 17 import android.view.inputmethod.EditorInfo; |
| 18 import android.view.inputmethod.InputConnection; |
| 19 |
| 20 import org.junit.Assert; |
| 21 |
| 22 import org.chromium.base.ThreadUtils; |
| 23 import org.chromium.content.browser.ContentViewCore; |
| 24 import org.chromium.content.browser.SelectionPopupController; |
| 25 import org.chromium.content.browser.test.util.Criteria; |
| 26 import org.chromium.content.browser.test.util.CriteriaHelper; |
| 27 import org.chromium.content.browser.test.util.DOMUtils; |
| 28 import org.chromium.content.browser.test.util.JavaScriptUtils; |
| 29 import org.chromium.content.browser.test.util.TestCallbackHelperContainer; |
| 30 import org.chromium.content.browser.test.util.TestInputMethodManagerWrapper; |
| 31 import org.chromium.content_public.browser.WebContents; |
| 32 import org.chromium.content_shell_apk.ContentShellActivityTestRule; |
| 33 import org.chromium.ui.base.ime.TextInputType; |
| 34 |
| 35 import java.util.ArrayList; |
| 36 import java.util.Arrays; |
| 37 import java.util.List; |
| 38 import java.util.concurrent.Callable; |
| 39 import java.util.concurrent.ExecutionException; |
| 40 import java.util.concurrent.TimeoutException; |
| 41 |
| 42 /** |
| 43 * Integration tests for text input for Android L (or above) features. |
| 44 */ |
| 45 class ImeActivityTestRule extends ContentShellActivityTestRule { |
| 46 private ChromiumBaseInputConnection mConnection; |
| 47 private TestInputConnectionFactory mConnectionFactory; |
| 48 private ImeAdapter mImeAdapter; |
| 49 |
| 50 static final String INPUT_FORM_HTML = "content/test/data/android/input/input
_forms.html"; |
| 51 |
| 52 private ContentViewCore mContentViewCore; |
| 53 private SelectionPopupController mSelectionPopupController; |
| 54 private TestCallbackHelperContainer mCallbackContainer; |
| 55 private TestInputMethodManagerWrapper mInputMethodManagerWrapper; |
| 56 |
| 57 public void setUp() throws Exception { |
| 58 launchContentShellWithUrlSync(INPUT_FORM_HTML); |
| 59 mContentViewCore = getContentViewCore(); |
| 60 mSelectionPopupController = mContentViewCore.getSelectionPopupController
ForTesting(); |
| 61 mInputMethodManagerWrapper = new TestInputMethodManagerWrapper(mContentV
iewCore) { |
| 62 private boolean mExpectsSelectionOutsideComposition; |
| 63 |
| 64 @Override |
| 65 public void expectsSelectionOutsideComposition() { |
| 66 mExpectsSelectionOutsideComposition = true; |
| 67 } |
| 68 |
| 69 @Override |
| 70 public void onUpdateSelection( |
| 71 Range oldSel, Range oldComp, Range newSel, Range newComp) { |
| 72 // We expect that selection will be outside composition in some
cases. Keyboard |
| 73 // app will not finish composition in this case. |
| 74 if (mExpectsSelectionOutsideComposition) { |
| 75 mExpectsSelectionOutsideComposition = false; |
| 76 return; |
| 77 } |
| 78 if (oldComp == null || oldComp.start() == oldComp.end() |
| 79 || newComp.start() == newComp.end()) { |
| 80 return; |
| 81 } |
| 82 // This emulates keyboard app's behavior that finishes compositi
on when |
| 83 // selection is outside composition. |
| 84 if (!newSel.intersects(newComp)) { |
| 85 try { |
| 86 finishComposingText(); |
| 87 } catch (Exception e) { |
| 88 e.printStackTrace(); |
| 89 Assert.fail(); |
| 90 } |
| 91 } |
| 92 } |
| 93 }; |
| 94 getImeAdapter().setInputMethodManagerWrapperForTest(mInputMethodManagerW
rapper); |
| 95 Assert.assertEquals(0, mInputMethodManagerWrapper.getShowSoftInputCounte
r()); |
| 96 mConnectionFactory = |
| 97 new TestInputConnectionFactory(getImeAdapter().getInputConnectio
nFactoryForTest()); |
| 98 getImeAdapter().setInputConnectionFactory(mConnectionFactory); |
| 99 |
| 100 mCallbackContainer = new TestCallbackHelperContainer(mContentViewCore); |
| 101 DOMUtils.waitForNonZeroNodeBounds(getWebContents(), "input_text"); |
| 102 boolean result = DOMUtils.clickNode(mContentViewCore, "input_text"); |
| 103 |
| 104 Assert.assertEquals("Failed to dispatch touch event.", true, result); |
| 105 assertWaitForKeyboardStatus(true); |
| 106 |
| 107 mConnection = getInputConnection(); |
| 108 mImeAdapter = getImeAdapter(); |
| 109 |
| 110 waitForKeyboardStates(1, 0, 1, new Integer[] {TextInputType.TEXT}); |
| 111 Assert.assertEquals(0, mConnectionFactory.getOutAttrs().initialSelStart)
; |
| 112 Assert.assertEquals(0, mConnectionFactory.getOutAttrs().initialSelEnd); |
| 113 |
| 114 waitForEventLogs("selectionchange"); |
| 115 clearEventLogs(); |
| 116 |
| 117 waitAndVerifyUpdateSelection(0, 0, 0, -1, -1); |
| 118 resetAllStates(); |
| 119 } |
| 120 |
| 121 SelectionPopupController getSelectionPopupController() { |
| 122 return mSelectionPopupController; |
| 123 } |
| 124 |
| 125 TestCallbackHelperContainer getTestCallBackHelperContainer() { |
| 126 return mCallbackContainer; |
| 127 } |
| 128 |
| 129 ChromiumBaseInputConnection getConnection() { |
| 130 return mConnection; |
| 131 } |
| 132 |
| 133 TestInputMethodManagerWrapper getInputMethodManagerWrapper() { |
| 134 return mInputMethodManagerWrapper; |
| 135 } |
| 136 |
| 137 TestInputConnectionFactory getConnectionFactory() { |
| 138 return mConnectionFactory; |
| 139 } |
| 140 |
| 141 void fullyLoadUrl(final String url) throws Throwable { |
| 142 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 143 @Override |
| 144 public void run() { |
| 145 getActivity().getActiveShell().loadUrl(url); |
| 146 } |
| 147 }); |
| 148 waitForActiveShellToBeDoneLoading(); |
| 149 } |
| 150 |
| 151 void clearEventLogs() throws Exception { |
| 152 final String code = "clearEventLogs()"; |
| 153 JavaScriptUtils.executeJavaScriptAndWaitForResult( |
| 154 getContentViewCore().getWebContents(), code); |
| 155 } |
| 156 |
| 157 void waitForEventLogs(String expectedLogs) throws Exception { |
| 158 final String code = "getEventLogs()"; |
| 159 final String sanitizedExpectedLogs = "\"" + expectedLogs + "\""; |
| 160 Assert.assertEquals(sanitizedExpectedLogs, |
| 161 JavaScriptUtils.executeJavaScriptAndWaitForResult( |
| 162 getContentViewCore().getWebContents(), code)); |
| 163 } |
| 164 |
| 165 void assertTextsAroundCursor(CharSequence before, CharSequence selected, Cha
rSequence after) |
| 166 throws Exception { |
| 167 Assert.assertEquals(before, getTextBeforeCursor(100, 0)); |
| 168 Assert.assertEquals(selected, getSelectedText(0)); |
| 169 Assert.assertEquals(after, getTextAfterCursor(100, 0)); |
| 170 } |
| 171 |
| 172 void waitForKeyboardStates(int show, int hide, int restart, Integer[] histor
y) { |
| 173 final String expected = stringifyKeyboardStates(show, hide, restart, his
tory); |
| 174 CriteriaHelper.pollUiThread(Criteria.equals(expected, new Callable<Strin
g>() { |
| 175 @Override |
| 176 public String call() { |
| 177 return getKeyboardStates(); |
| 178 } |
| 179 })); |
| 180 } |
| 181 |
| 182 void resetAllStates() { |
| 183 mInputMethodManagerWrapper.reset(); |
| 184 mConnectionFactory.clearTextInputTypeHistory(); |
| 185 } |
| 186 |
| 187 String getKeyboardStates() { |
| 188 int showCount = mInputMethodManagerWrapper.getShowSoftInputCounter(); |
| 189 int hideCount = mInputMethodManagerWrapper.getHideSoftInputCounter(); |
| 190 int restartCount = mInputMethodManagerWrapper.getRestartInputCounter(); |
| 191 Integer[] history = mConnectionFactory.getTextInputTypeHistory(); |
| 192 return stringifyKeyboardStates(showCount, hideCount, restartCount, histo
ry); |
| 193 } |
| 194 |
| 195 String stringifyKeyboardStates(int show, int hide, int restart, Integer[] hi
story) { |
| 196 return "show count: " + show + ", hide count: " + hide + ", restart coun
t: " + restart |
| 197 + ", input type history: " + Arrays.deepToString(history); |
| 198 } |
| 199 |
| 200 void performGo(TestCallbackHelperContainer testCallbackHelperContainer) thro
ws Throwable { |
| 201 final InputConnection inputConnection = mConnection; |
| 202 final Callable<Void> callable = new Callable<Void>() { |
| 203 @Override |
| 204 public Void call() throws Exception { |
| 205 inputConnection.performEditorAction(EditorInfo.IME_ACTION_GO); |
| 206 return null; |
| 207 } |
| 208 }; |
| 209 |
| 210 handleBlockingCallbackAction( |
| 211 testCallbackHelperContainer.getOnPageFinishedHelper(), new Runna
ble() { |
| 212 @Override |
| 213 public void run() { |
| 214 try { |
| 215 runBlockingOnImeThread(callable); |
| 216 } catch (Exception e) { |
| 217 e.printStackTrace(); |
| 218 Assert.fail(); |
| 219 } |
| 220 } |
| 221 }); |
| 222 } |
| 223 |
| 224 void assertWaitForKeyboardStatus(final boolean show) { |
| 225 CriteriaHelper.pollUiThread(new Criteria() { |
| 226 @Override |
| 227 public boolean isSatisfied() { |
| 228 // We do not check the other way around: in some cases we need t
o keep |
| 229 // input connection even when the last known status is 'hidden'. |
| 230 if (show && getInputConnection() == null) { |
| 231 updateFailureReason("input connection should not be null."); |
| 232 return false; |
| 233 } |
| 234 updateFailureReason("expected show: " + show); |
| 235 return show == mInputMethodManagerWrapper.isShowWithoutHideOutst
anding(); |
| 236 } |
| 237 }); |
| 238 } |
| 239 |
| 240 void assertWaitForSelectActionBarStatus(final boolean show) { |
| 241 CriteriaHelper.pollUiThread(Criteria.equals(show, new Callable<Boolean>(
) { |
| 242 @Override |
| 243 public Boolean call() { |
| 244 return mContentViewCore.isSelectActionBarShowing(); |
| 245 } |
| 246 })); |
| 247 } |
| 248 |
| 249 void waitAndVerifyUpdateSelection(final int index, final int selectionStart, |
| 250 final int selectionEnd, final int compositionStart, final int compos
itionEnd) { |
| 251 final List<Pair<Range, Range>> states = mInputMethodManagerWrapper.getUp
dateSelectionList(); |
| 252 CriteriaHelper.pollUiThread(new Criteria() { |
| 253 @Override |
| 254 public boolean isSatisfied() { |
| 255 return states.size() > index; |
| 256 } |
| 257 }); |
| 258 Pair<Range, Range> selection = states.get(index); |
| 259 Assert.assertEquals(selectionStart, selection.first.start()); |
| 260 Assert.assertEquals(selectionEnd, selection.first.end()); |
| 261 Assert.assertEquals(compositionStart, selection.second.start()); |
| 262 Assert.assertEquals(compositionEnd, selection.second.end()); |
| 263 } |
| 264 |
| 265 void resetUpdateSelectionList() { |
| 266 mInputMethodManagerWrapper.getUpdateSelectionList().clear(); |
| 267 } |
| 268 |
| 269 void assertClipboardContents(final Activity activity, final String expectedC
ontents) { |
| 270 CriteriaHelper.pollUiThread(new Criteria() { |
| 271 @Override |
| 272 public boolean isSatisfied() { |
| 273 ClipboardManager clipboardManager = |
| 274 (ClipboardManager) activity.getSystemService(Context.CLI
PBOARD_SERVICE); |
| 275 ClipData clip = clipboardManager.getPrimaryClip(); |
| 276 return clip != null && clip.getItemCount() == 1 |
| 277 && TextUtils.equals(clip.getItemAt(0).getText(), expecte
dContents); |
| 278 } |
| 279 }); |
| 280 } |
| 281 |
| 282 ImeAdapter getImeAdapter() { |
| 283 return mContentViewCore.getImeAdapterForTest(); |
| 284 } |
| 285 |
| 286 ChromiumBaseInputConnection getInputConnection() { |
| 287 try { |
| 288 return ThreadUtils.runOnUiThreadBlocking(new Callable<ChromiumBaseIn
putConnection>() { |
| 289 @Override |
| 290 public ChromiumBaseInputConnection call() { |
| 291 return mContentViewCore.getImeAdapterForTest().getInputConne
ctionForTest(); |
| 292 } |
| 293 }); |
| 294 } catch (ExecutionException e) { |
| 295 e.printStackTrace(); |
| 296 Assert.fail(); |
| 297 return null; |
| 298 } |
| 299 } |
| 300 |
| 301 void restartInput() { |
| 302 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 303 @Override |
| 304 public void run() { |
| 305 mImeAdapter.restartInput(); |
| 306 } |
| 307 }); |
| 308 } |
| 309 |
| 310 // After calling this method, we should call assertClipboardContents() to wa
it for the clipboard |
| 311 // to get updated. See cubug.com/621046 |
| 312 void copy() { |
| 313 final WebContents webContents = getWebContents(); |
| 314 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 315 @Override |
| 316 public void run() { |
| 317 webContents.copy(); |
| 318 } |
| 319 }); |
| 320 } |
| 321 |
| 322 void cut() { |
| 323 final WebContents webContents = getWebContents(); |
| 324 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 325 @Override |
| 326 public void run() { |
| 327 webContents.cut(); |
| 328 } |
| 329 }); |
| 330 } |
| 331 |
| 332 void setClip(final CharSequence text) { |
| 333 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 334 @Override |
| 335 public void run() { |
| 336 final ClipboardManager clipboardManager = |
| 337 (ClipboardManager) getActivity().getSystemService( |
| 338 Context.CLIPBOARD_SERVICE); |
| 339 clipboardManager.setPrimaryClip(ClipData.newPlainText(null, text
)); |
| 340 } |
| 341 }); |
| 342 } |
| 343 |
| 344 void paste() { |
| 345 final WebContents webContents = getWebContents(); |
| 346 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 347 @Override |
| 348 public void run() { |
| 349 webContents.paste(); |
| 350 } |
| 351 }); |
| 352 } |
| 353 |
| 354 void selectAll() { |
| 355 final WebContents webContents = getWebContents(); |
| 356 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 357 @Override |
| 358 public void run() { |
| 359 webContents.selectAll(); |
| 360 } |
| 361 }); |
| 362 } |
| 363 |
| 364 void collapseSelection() { |
| 365 final WebContents webContents = getWebContents(); |
| 366 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 367 @Override |
| 368 public void run() { |
| 369 webContents.collapseSelection(); |
| 370 } |
| 371 }); |
| 372 } |
| 373 |
| 374 /** |
| 375 * Run the {@Callable} on IME thread (or UI thread if not applicable). |
| 376 * @param c The callable |
| 377 * @return The result from running the callable. |
| 378 */ |
| 379 <T> T runBlockingOnImeThread(Callable<T> c) throws Exception { |
| 380 return ImeTestUtils.runBlockingOnHandler(mConnectionFactory.getHandler()
, c); |
| 381 } |
| 382 |
| 383 boolean beginBatchEdit() throws Exception { |
| 384 final ChromiumBaseInputConnection connection = mConnection; |
| 385 return runBlockingOnImeThread(new Callable<Boolean>() { |
| 386 @Override |
| 387 public Boolean call() { |
| 388 return connection.beginBatchEdit(); |
| 389 } |
| 390 }); |
| 391 } |
| 392 |
| 393 boolean endBatchEdit() throws Exception { |
| 394 final ChromiumBaseInputConnection connection = mConnection; |
| 395 return runBlockingOnImeThread(new Callable<Boolean>() { |
| 396 @Override |
| 397 public Boolean call() { |
| 398 return connection.endBatchEdit(); |
| 399 } |
| 400 }); |
| 401 } |
| 402 |
| 403 boolean commitText(final CharSequence text, final int newCursorPosition) thr
ows Exception { |
| 404 final ChromiumBaseInputConnection connection = mConnection; |
| 405 return runBlockingOnImeThread(new Callable<Boolean>() { |
| 406 @Override |
| 407 public Boolean call() { |
| 408 return connection.commitText(text, newCursorPosition); |
| 409 } |
| 410 }); |
| 411 } |
| 412 |
| 413 boolean setSelection(final int start, final int end) throws Exception { |
| 414 final ChromiumBaseInputConnection connection = mConnection; |
| 415 return runBlockingOnImeThread(new Callable<Boolean>() { |
| 416 @Override |
| 417 public Boolean call() { |
| 418 return connection.setSelection(start, end); |
| 419 } |
| 420 }); |
| 421 } |
| 422 |
| 423 boolean setComposingRegion(final int start, final int end) throws Exception
{ |
| 424 final ChromiumBaseInputConnection connection = mConnection; |
| 425 return runBlockingOnImeThread(new Callable<Boolean>() { |
| 426 @Override |
| 427 public Boolean call() { |
| 428 return connection.setComposingRegion(start, end); |
| 429 } |
| 430 }); |
| 431 } |
| 432 |
| 433 protected boolean setComposingText(final CharSequence text, final int newCur
sorPosition) |
| 434 throws Exception { |
| 435 final ChromiumBaseInputConnection connection = mConnection; |
| 436 return runBlockingOnImeThread(new Callable<Boolean>() { |
| 437 @Override |
| 438 public Boolean call() { |
| 439 return connection.setComposingText(text, newCursorPosition); |
| 440 } |
| 441 }); |
| 442 } |
| 443 |
| 444 boolean finishComposingText() throws Exception { |
| 445 final ChromiumBaseInputConnection connection = mConnection; |
| 446 return runBlockingOnImeThread(new Callable<Boolean>() { |
| 447 @Override |
| 448 public Boolean call() { |
| 449 return connection.finishComposingText(); |
| 450 } |
| 451 }); |
| 452 } |
| 453 |
| 454 boolean deleteSurroundingText(final int before, final int after) throws Exce
ption { |
| 455 final ChromiumBaseInputConnection connection = mConnection; |
| 456 return runBlockingOnImeThread(new Callable<Boolean>() { |
| 457 @Override |
| 458 public Boolean call() { |
| 459 return connection.deleteSurroundingText(before, after); |
| 460 } |
| 461 }); |
| 462 } |
| 463 |
| 464 // Note that deleteSurroundingTextInCodePoints() was introduced in Android N
(Api level 24), but |
| 465 // the Android repository used in Chrome is behind that (level 23). So this
function can't be |
| 466 // called by keyboard apps currently. |
| 467 @TargetApi(24) |
| 468 boolean deleteSurroundingTextInCodePoints(final int before, final int after)
throws Exception { |
| 469 final ThreadedInputConnection connection = (ThreadedInputConnection) mCo
nnection; |
| 470 return runBlockingOnImeThread(new Callable<Boolean>() { |
| 471 @Override |
| 472 public Boolean call() { |
| 473 return connection.deleteSurroundingTextInCodePoints(before, afte
r); |
| 474 } |
| 475 }); |
| 476 } |
| 477 |
| 478 CharSequence getTextBeforeCursor(final int length, final int flags) throws E
xception { |
| 479 final ChromiumBaseInputConnection connection = mConnection; |
| 480 return runBlockingOnImeThread(new Callable<CharSequence>() { |
| 481 @Override |
| 482 public CharSequence call() { |
| 483 return connection.getTextBeforeCursor(length, flags); |
| 484 } |
| 485 }); |
| 486 } |
| 487 |
| 488 CharSequence getSelectedText(final int flags) throws Exception { |
| 489 final ChromiumBaseInputConnection connection = mConnection; |
| 490 return runBlockingOnImeThread(new Callable<CharSequence>() { |
| 491 @Override |
| 492 public CharSequence call() { |
| 493 return connection.getSelectedText(flags); |
| 494 } |
| 495 }); |
| 496 } |
| 497 |
| 498 CharSequence getTextAfterCursor(final int length, final int flags) throws Ex
ception { |
| 499 final ChromiumBaseInputConnection connection = mConnection; |
| 500 return runBlockingOnImeThread(new Callable<CharSequence>() { |
| 501 @Override |
| 502 public CharSequence call() { |
| 503 return connection.getTextAfterCursor(length, flags); |
| 504 } |
| 505 }); |
| 506 } |
| 507 |
| 508 int getCursorCapsMode(final int reqModes) throws Throwable { |
| 509 final ChromiumBaseInputConnection connection = mConnection; |
| 510 return runBlockingOnImeThread(new Callable<Integer>() { |
| 511 @Override |
| 512 public Integer call() { |
| 513 return connection.getCursorCapsMode(reqModes); |
| 514 } |
| 515 }); |
| 516 } |
| 517 |
| 518 void dispatchKeyEvent(final KeyEvent event) { |
| 519 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 520 @Override |
| 521 public void run() { |
| 522 mImeAdapter.dispatchKeyEvent(event); |
| 523 } |
| 524 }); |
| 525 } |
| 526 |
| 527 /** |
| 528 * Focus element, wait for a single state update, reset state update list. |
| 529 * @param id ID of the element to focus. |
| 530 */ |
| 531 void focusElementAndWaitForStateUpdate(String id) |
| 532 throws InterruptedException, TimeoutException { |
| 533 resetUpdateSelectionList(); |
| 534 focusElement(id); |
| 535 waitAndVerifyUpdateSelection(0, 0, 0, -1, -1); |
| 536 resetUpdateSelectionList(); |
| 537 } |
| 538 |
| 539 void focusElement(final String id) throws InterruptedException, TimeoutExcep
tion { |
| 540 focusElement(id, true); |
| 541 } |
| 542 |
| 543 void focusElement(final String id, boolean shouldShowKeyboard) |
| 544 throws InterruptedException, TimeoutException { |
| 545 DOMUtils.focusNode(getWebContents(), id); |
| 546 assertWaitForKeyboardStatus(shouldShowKeyboard); |
| 547 CriteriaHelper.pollInstrumentationThread(Criteria.equals(id, new Callabl
e<String>() { |
| 548 @Override |
| 549 public String call() throws Exception { |
| 550 return DOMUtils.getFocusedNode(getWebContents()); |
| 551 } |
| 552 })); |
| 553 // When we focus another element, the connection may be recreated. |
| 554 mConnection = getInputConnection(); |
| 555 } |
| 556 |
| 557 static class TestInputConnectionFactory implements ChromiumBaseInputConnecti
on.Factory { |
| 558 private final ChromiumBaseInputConnection.Factory mFactory; |
| 559 |
| 560 private final List<Integer> mTextInputTypeList = new ArrayList<>(); |
| 561 private EditorInfo mOutAttrs; |
| 562 |
| 563 public TestInputConnectionFactory(ChromiumBaseInputConnection.Factory fa
ctory) { |
| 564 mFactory = factory; |
| 565 } |
| 566 |
| 567 @Override |
| 568 public ChromiumBaseInputConnection initializeAndGet(View view, ImeAdapte
r imeAdapter, |
| 569 int inputType, int inputFlags, int inputMode, int selectionStart
, int selectionEnd, |
| 570 EditorInfo outAttrs) { |
| 571 mTextInputTypeList.add(inputType); |
| 572 mOutAttrs = outAttrs; |
| 573 return mFactory.initializeAndGet(view, imeAdapter, inputType, inputM
ode, inputFlags, |
| 574 selectionStart, selectionEnd, outAttrs); |
| 575 } |
| 576 |
| 577 @Override |
| 578 public Handler getHandler() { |
| 579 return mFactory.getHandler(); |
| 580 } |
| 581 |
| 582 public Integer[] getTextInputTypeHistory() { |
| 583 Integer[] result = new Integer[mTextInputTypeList.size()]; |
| 584 mTextInputTypeList.toArray(result); |
| 585 return result; |
| 586 } |
| 587 |
| 588 public void clearTextInputTypeHistory() { |
| 589 mTextInputTypeList.clear(); |
| 590 } |
| 591 |
| 592 public EditorInfo getOutAttrs() { |
| 593 return mOutAttrs; |
| 594 } |
| 595 |
| 596 @Override |
| 597 public void onWindowFocusChanged(boolean gainFocus) { |
| 598 mFactory.onWindowFocusChanged(gainFocus); |
| 599 } |
| 600 |
| 601 @Override |
| 602 public void onViewFocusChanged(boolean gainFocus) { |
| 603 mFactory.onViewFocusChanged(gainFocus); |
| 604 } |
| 605 |
| 606 @Override |
| 607 public void onViewAttachedToWindow() { |
| 608 mFactory.onViewAttachedToWindow(); |
| 609 } |
| 610 |
| 611 @Override |
| 612 public void onViewDetachedFromWindow() { |
| 613 mFactory.onViewDetachedFromWindow(); |
| 614 } |
| 615 } |
| 616 } |
OLD | NEW |