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

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/input/ChromiumInputConnection.java

Issue 1278593004: Introduce ThreadedInputConnection behind a switch (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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.os.Bundle;
8 import android.os.Handler;
9 import android.os.SystemClock;
10 import android.text.InputType;
11 import android.view.KeyEvent;
12 import android.view.View;
13 import android.view.inputmethod.CompletionInfo;
14 import android.view.inputmethod.CorrectionInfo;
15 import android.view.inputmethod.EditorInfo;
16 import android.view.inputmethod.ExtractedText;
17 import android.view.inputmethod.ExtractedTextRequest;
18 import android.view.inputmethod.InputConnection;
19
20 import org.chromium.base.Log;
21 import org.chromium.base.ThreadUtils;
22 import org.chromium.base.VisibleForTesting;
23 import org.chromium.blink_public.web.WebInputEventType;
24 import org.chromium.blink_public.web.WebTextInputFlags;
25 import org.chromium.ui.base.ime.TextInputType;
26
27 import java.util.concurrent.BlockingQueue;
28 import java.util.concurrent.Callable;
29 import java.util.concurrent.ExecutionException;
30 import java.util.concurrent.FutureTask;
31 import java.util.concurrent.LinkedBlockingQueue;
32 import java.util.concurrent.TimeUnit;
33 import java.util.concurrent.atomic.AtomicBoolean;
34
35 /**
36 * TODO(changwan): add a description
37 */
38 public class ChromiumInputConnection implements ChromiumBaseInputConnection {
39 private static final String TAG = "cr.Ime";
40
41 // Android will raise TimeoutException to IME if bound call takes 2 seconds.
42 private static final long MAX_TIMEOUT = 1900;
43 private static final long MIN_TIMEOUT = 15;
44
45 private final Handler mHandler;
46 private final View mInternalView;
47 private final ImeAdapter mImeAdapter;
48
49 private int mNumNestedBatchEdits = 0;
50
51 // TODO(changwan): this value is used in two threads.
52 private final AtomicBoolean mSingleLine = new AtomicBoolean(true);
aelias_OOO_until_Jul13 2015/09/30 00:10:04 How about making this one of the TextInputState fi
Changwan Ryu 2016/01/19 07:31:53 Good idea! Done.
53 private final BlockingQueue<TextInputState> mQueue = new LinkedBlockingQueue <>();
54 private TextInputState mLastTextInputState;
55
56 @VisibleForTesting
57 ChromiumInputConnection(View view, ImeAdapter imeAdapter) {
58 ImeUtils.assertOnUiThread();
59
60 mHandler = InputConnectionHandlerFactory.getInputConnectionHandler();
61 mInternalView = view;
62 mImeAdapter = imeAdapter;
63 mImeAdapter.setInputConnection(ChromiumInputConnection.this);
64
65 // Make sure the previous composition is finished. There is no proper wa y to
66 // tell IME about the previous composition by the time this call ends, a nyways.
67 // finishComposingText();
aelias_OOO_until_Jul13 2015/09/30 00:10:04 Can this be deleted? Was this useful for anything
Changwan Ryu 2016/01/19 07:31:53 Done.
68
69 Log.d(TAG, "%d Constructor called", System.identityHashCode(this));
70 }
71
72 private void updateToInputMethodManager(TextInputState textInputState) {
73 ImeUtils.assertNotOnUiThread();
74 if (mNumNestedBatchEdits != 0) {
75 mLastTextInputState = textInputState;
76 return;
77 }
78 ImeUtils.assertReally(textInputState != null);
79 if (textInputState.equals(mLastTextInputState)) return;
80 Range selection = textInputState.selection();
81 Range composition = textInputState.composition();
82 getInputMethodManagerWrapper().updateSelection(mInternalView, selection. start(),
83 selection.end(), composition.start(), composition.end());
84 mLastTextInputState = textInputState;
85 }
86
87 public void updateEditorInfo(EditorInfo outAttrs, int inputType, int inputFl ags) {
aelias_OOO_until_Jul13 2015/09/30 00:10:04 Please rename this to updateEditorInfoOnUiThread a
Changwan Ryu 2016/01/19 07:31:53 Done.
88 Log.d(TAG, "updateEditorInfo");
89 mSingleLine.set(true);
90 outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME _FLAG_NO_EXTRACT_UI;
91 outAttrs.inputType =
92 EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_WEB_ EDIT_TEXT;
93
94 if ((inputFlags & WebTextInputFlags.AutocompleteOff) != 0) {
95 outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
96 }
97
98 if (inputType == TextInputType.TEXT) {
aelias_OOO_until_Jul13 2015/09/30 00:10:04 Please move most of this logic into a private stat
Changwan Ryu 2016/01/19 07:31:53 Done.
99 // Normal text field
100 outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
101 if ((inputFlags & WebTextInputFlags.AutocorrectOff) == 0) {
102 outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT;
103 }
104 } else if (inputType == TextInputType.TEXT_AREA
105 || inputType == TextInputType.CONTENT_EDITABLE) {
106 outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
107 mSingleLine.set(false);
108 if ((inputFlags & WebTextInputFlags.AutocorrectOff) == 0) {
109 outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT;
110 }
111 outAttrs.imeOptions |= EditorInfo.IME_ACTION_NONE;
112 } else if (inputType == TextInputType.PASSWORD) {
113 // Password
114 outAttrs.inputType =
115 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WE B_PASSWORD;
116 outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
117 } else if (inputType == TextInputType.SEARCH) {
118 // Search
119 outAttrs.imeOptions |= EditorInfo.IME_ACTION_SEARCH;
120 } else if (inputType == TextInputType.URL) {
121 // Url
122 outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT _VARIATION_URI;
123 outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
124 } else if (inputType == TextInputType.EMAIL) {
125 // Email
126 outAttrs.inputType =
127 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WE B_EMAIL_ADDRESS;
128 outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
129 } else if (inputType == TextInputType.TELEPHONE) {
130 // Telephone
131 // Number and telephone do not have both a Tab key and an
132 // action in default OSK, so set the action to NEXT
133 outAttrs.inputType = InputType.TYPE_CLASS_PHONE;
134 outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT;
135 } else if (inputType == TextInputType.NUMBER) {
136 // Number
137 outAttrs.inputType = InputType.TYPE_CLASS_NUMBER
138 | InputType.TYPE_NUMBER_VARIATION_NORMAL | InputType.TYPE_NU MBER_FLAG_DECIMAL;
139 outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT;
140 }
141
142 // Handling of autocapitalize. Blink will send the flag taking into acco unt the element's
143 // type. This is not using AutocapitalizeNone because Android does not a utocapitalize by
144 // default and there is no way to express no capitalization.
145 // Autocapitalize is meant as a hint to the virtual keyboard.
146 if ((inputFlags & WebTextInputFlags.AutocapitalizeCharacters) != 0) {
147 outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
148 } else if ((inputFlags & WebTextInputFlags.AutocapitalizeWords) != 0) {
149 outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_CAP_WORDS;
150 } else if ((inputFlags & WebTextInputFlags.AutocapitalizeSentences) != 0 ) {
151 outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
152 }
153 // Content editable doesn't use autocapitalize so we need to set it manu ally.
154 if (inputType == TextInputType.CONTENT_EDITABLE) {
155 outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
156 }
157
158 Range selection = getSelection();
159 outAttrs.initialSelStart = selection.start();
160 outAttrs.initialSelEnd = selection.end();
161 }
162
163 @Override
164 public void updateState(final String text, final int selectionStart, final i nt selectionEnd,
165 final int compositionStart, final int compositionEnd, final boolean isNonImeChange) {
166 Log.d(TAG, "updateState [%s] [%s %s] [%s %s] [%b]", text, selectionStart , selectionEnd,
167 compositionStart, compositionEnd, isNonImeChange);
168 ImeUtils.assertOnUiThread();
169
170 // TODO(changwan): this should be called at the end of each call, not af ter it.
171 final TextInputState newState =
172 new TextInputState(text, new Range(selectionStart, selectionEnd) ,
173 new Range(compositionStart, compositionEnd));
174
175 if (isNonImeChange) {
176 mHandler.post(new Runnable() {
177 @Override
178 public void run() {
179 updateToInputMethodManager(newState);
180 }
181 });
182 } else {
183 onStateUpdateOriginatingFromIme(newState);
184 }
185 Log.d(TAG, "updateState finished");
186 }
187
188 private TextInputState updateTextInputState() {
189 ThreadUtils.postOnUiThread(new Runnable() {
190 @Override
191 public void run() {
192 boolean result = mImeAdapter.requestTextInputStateUpdate();
193 if (!result) unblock();
194 }
195 });
196 return blockAndGetStateUpdate();
197 }
198
199 private Range getSelection() {
200 Log.d(TAG, "getSelection");
201 return new Range(0, 0);
aelias_OOO_until_Jul13 2015/09/30 00:10:04 Looks like this needs to be fixed to work properly
Changwan Ryu 2016/01/19 07:31:53 Applied the logic from AdapterInputConnection. BT
202 // TextInputState textInputState = updateTextInputState();
203 // if (textInputState == null) return new Range(0, 0);
204 // return textInputState.selection();
205 }
206
207 private void onStateUpdateOriginatingFromIme(TextInputState textInputState) {
208 ImeUtils.assertOnUiThread();
209 try {
210 mQueue.put(textInputState);
211 } catch (InterruptedException e) {
212 Log.w(TAG, "onStateUpdateOriginatingFromIme interrupted", e);
213 }
214 Log.d(TAG, "%d onStateUpdateOriginatingFromIme finished: %d", System.ide ntityHashCode(this),
215 mQueue.size());
216 }
217
218 /**
219 * TODO(changwan): simplify calls using this.
220 * @param c
221 * @return
222 */
223 private TextInputState runAndGetStateUpdate(final Callable<Boolean> c) {
224 ImeUtils.assertNotOnUiThread();
225 mQueue.clear();
226 ThreadUtils.postOnUiThread(new Runnable() {
227 @Override
228 public void run() {
229 // TODO(changwan): remove this.
230 Boolean result = null;
231 try {
232 result = c.call();
233 } catch (Exception e) {
234 e.printStackTrace();
235 }
236 if (result == null || !result.booleanValue()) {
237 // Now we know that updateState() will never be called.
238 unblock();
239 }
240 }
241 });
242
243 return blockAndGetStateUpdate();
244 }
245
246 /**
247 * TODO(changwan): simplify calls using this.
248 * @param c
249 * @return
250 */
251 private TextInputState runAndGetStateUpdate2(final Callable<Boolean> c) {
aelias_OOO_until_Jul13 2015/09/30 00:10:04 This has no callers, can it be deleted?
Changwan Ryu 2016/01/19 07:31:53 Done.
252 mQueue.clear();
253 ThreadUtils.postOnUiThread(new Runnable() {
254 @Override
255 public void run() {
256 Boolean result = null;
257 try {
258 result = c.call();
259 } catch (Exception e) {
260 e.printStackTrace();
261 }
262 if (result == null || !result.booleanValue()) {
263 // Now we know that updateState() will never be called.
264 unblock();
265 }
266 }
267 });
268 FutureTask<TextInputState> task = new FutureTask<>(new Callable<TextInpu tState>() {
269 @Override
270 public TextInputState call() throws Exception {
271 TextInputState result = blockAndGetStateUpdate();
272 // if (result != null) updateToInputMethodManager(result);
273 return result;
274 }
275 });
276 mHandler.post(task);
277 if (!ThreadUtils.runningOnUiThread()) {
278 try {
279 return task.get();
280 } catch (InterruptedException | ExecutionException e) {
281 // TODO(changwan): Auto-generated catch block
282 e.printStackTrace();
283 }
284 }
285 return null;
286 }
287
288 /**
289 * Unblock the blockAndGetStateUpdate() function if we found that we will
290 * never get state update.
291 */
292 private void unblock() {
293 ImeUtils.assertOnUiThread();
294 onStateUpdateOriginatingFromIme(new TextInputState.Dummy());
295 }
296
297 private void postConsumeStateUpdate() {
298 mHandler.post(new Runnable() {
299 @Override
300 public void run() {
301 blockAndGetStateUpdate();
302 }
303 });
304 }
305
306 /**
307 * Block until we get the expected state update.
308 * @return TextInputState if we get it successfully. null otherwise.
309 */
310 private TextInputState blockAndGetStateUpdate() {
311 ImeUtils.assertNotOnUiThread();
312 long timeout = MAX_TIMEOUT;
313 try {
314 while (true) {
315 long startTime = System.currentTimeMillis();
316 TextInputState result = mQueue.poll(timeout, TimeUnit.MILLISECON DS);
317
318 if (result != null) {
319 if (result.isDummy()) {
320 Log.d(TAG, "blockAndGetStateUpdate: failed, got dummy");
321 return null;
322 }
323 updateToInputMethodManager(result);
324 return result;
325 }
326
327 long polledTime = System.currentTimeMillis() - startTime;
328 timeout -= polledTime + 10;
329 if (timeout < MIN_TIMEOUT) {
aelias_OOO_until_Jul13 2015/09/30 00:10:04 This doesn't seem useful, how about simply having
Changwan Ryu 2016/01/19 07:31:53 Done.
330 Log.e(TAG, "%d blockAndGetStateUpdate: failed %d",
331 System.identityHashCode(this), mQueue.size());
332 ImeUtils.assertReally(false);
333 return null;
334 }
335 }
336 } catch (InterruptedException e) {
337 e.printStackTrace();
338 Log.d(TAG, "blockAndGetStateUpdate: failed due to interruption");
339 return null;
340 }
341 }
342
343 /**
344 * @see InputConnection#setComposingText(java.lang.CharSequence, int)
345 */
346 @Override
347 public boolean setComposingText(final CharSequence text, final int newCursor Position) {
348 Log.d(TAG, "setComposingText [%s] [%d]", text, newCursorPosition);
349 ImeUtils.assertNotOnUiThread();
350 mQueue.clear(); // TODO(changwan): remove
aelias_OOO_until_Jul13 2015/09/30 00:10:04 Can all these be removed yet?
Changwan Ryu 2016/01/19 07:31:53 Done.
351 ThreadUtils.postOnUiThread(new Runnable() {
352 @Override
353 public void run() {
354 boolean result = mImeAdapter.checkCompositionQueueAndCallNative(
355 text, newCursorPosition, false);
356 if (!result) unblock();
357 }
358 });
359 return blockAndGetStateUpdate() != null;
360 }
361
362 /**
363 * @see InputConnection#commitText(java.lang.CharSequence, int)
364 */
365 @Override
366 public boolean commitText(final CharSequence text, final int newCursorPositi on) {
367 Log.d(TAG, "commitText [%s] [%d]", text, newCursorPosition);
368 ImeUtils.assertNotOnUiThread();
369 mQueue.clear(); // TODO(changwan): remove
370 ThreadUtils.postOnUiThread(new Runnable() {
371 @Override
372 public void run() {
373 boolean result = mImeAdapter.checkCompositionQueueAndCallNative(
374 text, newCursorPosition, text.length() > 0);
375 if (!result) unblock();
376 }
377 });
378 return blockAndGetStateUpdate() != null;
379 }
380
381 @Override
382 public void restartInput() {
383 Log.d(TAG, "restartInput");
384 if (ThreadUtils.runningOnUiThread()) {
aelias_OOO_until_Jul13 2015/09/30 00:10:03 After this is renamed restartInputOnUiThread, this
Changwan Ryu 2016/01/19 07:31:53 The logic here has been refactored into ImeAdapter
385 unblock();
386 mHandler.post(new Runnable() {
387 @Override
388 public void run() {
389 getInputMethodManagerWrapper().restartInput(mInternalView);
390 }
391 });
392 } else {
393 getInputMethodManagerWrapper().restartInput(mInternalView);
394 }
395 }
396
397 /**
398 * @see InputConnection#performEditorAction(int)
399 */
400 @Override
401 public boolean performEditorAction(int actionCode) {
402 Log.d(TAG, "performEditorAction [%d]", actionCode);
403 ImeUtils.assertNotOnUiThread();
404 if (actionCode == EditorInfo.IME_ACTION_NEXT) {
405 restartInput();
aelias_OOO_until_Jul13 2015/09/30 00:10:04 This is the only IME-thread caller of restartInput
Changwan Ryu 2016/01/19 07:31:53 Thanks for pointing that out. It's already been mo
406 mQueue.clear(); // TODO(changwan): remove
407 // Send TAB key event
408 ThreadUtils.postOnUiThread(new Runnable() {
409 @Override
410 public void run() {
411 long timeStampMs = SystemClock.uptimeMillis();
412 boolean result = mImeAdapter.sendSyntheticKeyEvent(
413 WebInputEventType.RawKeyDown, timeStampMs, KeyEvent. KEYCODE_TAB, 0, 0);
414 if (!result) unblock();
415 }
416 });
417 return blockAndGetStateUpdate() != null;
418 } else {
419 mQueue.clear(); // TODO(changwan): remove
420 ThreadUtils.postOnUiThread(new Runnable() {
421 @Override
422 public void run() {
423 boolean result = mImeAdapter.sendKeyEventWithKeyCode(
424 KeyEvent.KEYCODE_ENTER, KeyEvent.FLAG_SOFT_KEYBOARD
425 | KeyEvent.FLAG_KEEP_TOUCH_MODE | KeyEvent.F LAG_EDITOR_ACTION);
426 if (!result) unblock();
427 }
428 });
429 return blockAndGetStateUpdate() != null;
430 }
431 }
432
433 /**
434 * @see InputConnection#performContextMenuAction(int)
435 */
436 @Override
437 public boolean performContextMenuAction(final int id) {
438 Log.d(TAG, "performContextMenuAction [%d]", id);
439 ImeUtils.assertNotOnUiThread();
440 ThreadUtils.postOnUiThread(new Runnable() {
441 @Override
442 public void run() {
443 mImeAdapter.performContextMenuAction(id);
444 }
445 });
446 // TODO(changwan): return correct value
447 return true;
448 }
449
450 /**
451 * @see InputConnection#getExtractedText(android.view.inputmethod.ExtractedT extRequest,
452 * int)
453 */
454 @Override
455 public ExtractedText getExtractedText(ExtractedTextRequest request, int flag s) {
456 Log.d(TAG, "getExtractedText");
457 ImeUtils.assertNotOnUiThread();
458 mQueue.clear(); // TODO(changwan): remove
459 TextInputState textInputState = updateTextInputState();
460 if (textInputState == null) return null;
461 ExtractedText extractedText = new ExtractedText();
462 extractedText.text = textInputState.text();
463 extractedText.partialEndOffset = textInputState.text().length();
464 extractedText.selectionStart = textInputState.selection().start();
465 extractedText.selectionEnd = textInputState.selection().end();
466 extractedText.flags = mSingleLine.get() ? ExtractedText.FLAG_SINGLE_LINE : 0;
467 return extractedText;
468 }
469
470 /**
471 * @see InputConnection#beginBatchEdit()
472 */
473 @Override
474 public boolean beginBatchEdit() {
475 Log.d(TAG, "beginBatchEdit [%b]", (mNumNestedBatchEdits == 0));
476 ImeUtils.assertNotOnUiThread();
477 mNumNestedBatchEdits++;
478 return true;
479 }
480
481 /**
482 * @see InputConnection#endBatchEdit()
483 */
484 @Override
485 public boolean endBatchEdit() {
486 ImeUtils.assertNotOnUiThread();
487 if (mNumNestedBatchEdits == 0) return false;
488 --mNumNestedBatchEdits;
489 Log.d(TAG, "endBatchEdit [%b]", (mNumNestedBatchEdits == 0));
490 if (mNumNestedBatchEdits == 0 && mLastTextInputState != null) {
491 updateToInputMethodManager(mLastTextInputState);
aelias_OOO_until_Jul13 2015/09/30 00:10:04 I don't think this works as you intended, this is
Changwan Ryu 2016/01/19 07:31:53 You're correct. Now we have mLastUpdatedTextInputS
492 }
493 return mNumNestedBatchEdits != 0;
494 }
495
496 /**
497 * @see InputConnection#deleteSurroundingText(int, int)
498 */
499 @Override
500 public boolean deleteSurroundingText(final int beforeLength, final int after Length) {
501 Log.d(TAG, "deleteSurroundingText [%d %d]", beforeLength, afterLength);
502 ImeUtils.assertNotOnUiThread();
503 mQueue.clear(); // TODO(changwan): remove
504 ThreadUtils.postOnUiThread(new Runnable() {
505 @Override
506 public void run() {
507 boolean result = mImeAdapter.deleteSurroundingText(beforeLength, afterLength);
508 if (!result) unblock();
509 }
510 });
511 return blockAndGetStateUpdate() != null;
512 }
513
514 /**
515 * @see ChromiumBaseInputConnection#dispatchKeyEvent(KeyEvent)
516 */
517 @Override
518 public boolean dispatchKeyEvent(final KeyEvent event) {
519 // TODO(changwan): check if we need to post to IME handler first.
520 ImeUtils.assertOnUiThread();
521 // This should not happen.
522 if (!mImeAdapter.translateAndSendNativeEvents(event)) return false;
523 postConsumeStateUpdate();
524 return true;
525 }
526
527 /**
528 * @see InputConnection#sendKeyEvent(android.view.KeyEvent)
529 */
530 @Override
531 public boolean sendKeyEvent(final KeyEvent event) {
532 Log.d(TAG, "sendKeyEvent [%d %d]", event.getAction(), event.getKeyCode() );
533 ImeUtils.assertNotOnUiThread();
534 mQueue.clear(); // TODO(changwan): remove
535 ThreadUtils.postOnUiThread(new Runnable() {
536 @Override
537 public void run() {
538 boolean result = mImeAdapter.translateAndSendNativeEvents(event) ;
539 if (!result) unblock();
540 }
541 });
542 return blockAndGetStateUpdate() != null;
543 }
544
545 /**
546 * @see InputConnection#finishComposingText()
547 */
548 @Override
549 public boolean finishComposingText() {
550 Log.d(TAG, "%d finishComposingText", System.identityHashCode(this));
551 mQueue.clear(); // TODO(changwan): remove
552 // This is the only function that may be called on UI thread because
553 // of direct calls from InputMethodManager.
554
555 ThreadUtils.postOnUiThread(new Runnable() {
556 @Override
557 public void run() {
558 boolean result = mImeAdapter.finishComposingText();
559 if (!result) unblock();
560 }
561 });
562
563 if (ThreadUtils.runningOnUiThread()) {
aelias_OOO_until_Jul13 2015/09/30 00:10:04 There doesn't appear to be any (non-unit-test) cod
Changwan Ryu 2016/01/19 07:31:53 Hmm.. How about InputMethodManager#reportFinishInp
564 postConsumeStateUpdate();
565 return true;
566 } else {
567 return blockAndGetStateUpdate() != null;
568 }
569 }
570
571 /**
572 * @see InputConnection#setSelection(int, int)
573 */
574 @Override
575 public boolean setSelection(final int start, final int end) {
576 Log.d(TAG, "setSelection [%d %d]", start, end);
577 ImeUtils.assertNotOnUiThread();
578 mQueue.clear(); // TODO(changwan): remove
579 ThreadUtils.postOnUiThread(new Runnable() {
580 @Override
581 public void run() {
582 boolean result = mImeAdapter.setEditableSelectionOffsets(start, end);
583 if (!result) unblock();
584 }
585 });
586 return blockAndGetStateUpdate() != null;
587 }
588
589 /**
590 * @see InputConnection#setComposingRegion(int, int)
591 */
592 @Override
593 public boolean setComposingRegion(final int start, final int end) {
594 Log.d(TAG, "setComposingRegion [%d %d]", start, end);
595 ImeUtils.assertNotOnUiThread();
596 mQueue.clear(); // TODO(changwan): remove
597 ThreadUtils.postOnUiThread(new Runnable() {
598 @Override
599 public void run() {
600 boolean result = mImeAdapter.setComposingRegion("", start, end);
601 if (!result) unblock();
602 }
603 });
604 return blockAndGetStateUpdate() != null;
605 }
606
607 private InputMethodManagerWrapper getInputMethodManagerWrapper() {
608 return mImeAdapter.getInputMethodManagerWrapper();
609 }
610
611 /**
612 * @see InputConnection#getTextBeforeCursor(int, int)
613 */
614 @Override
615 public CharSequence getTextBeforeCursor(int maxChars, int flags) {
616 Log.d(TAG, "getTextBeforeCursor [%d %x]", maxChars, flags);
617 ImeUtils.assertNotOnUiThread();
618 mQueue.clear(); // TODO(changwan): remove
619 TextInputState textInputState = updateTextInputState();
620 if (textInputState == null) return null;
621 return textInputState.getTextBeforeSelection(maxChars);
622 }
623
624 /**
625 * @see InputConnection#getTextAfterCursor(int, int)
626 */
627 @Override
628 public CharSequence getTextAfterCursor(int maxChars, int flags) {
629 Log.d(TAG, "getTextAfterCursor [%d %x]", maxChars, flags);
630 mQueue.clear(); // TODO(changwan): remove
631 ImeUtils.assertNotOnUiThread();
632 TextInputState textInputState = updateTextInputState();
633 if (textInputState == null) return null;
634 return textInputState.getTextAfterSelection(maxChars);
635 }
636
637 /**
638 * @see InputConnection#getSelectedText(int)
639 */
640 @Override
641 public CharSequence getSelectedText(int flags) {
642 Log.d(TAG, "getSelectedText [%x]", flags);
643 ImeUtils.assertNotOnUiThread();
644 mQueue.clear(); // TODO(changwan): remove
645 TextInputState textInputState = updateTextInputState();
646 if (textInputState == null) return null;
647 return textInputState.getSelectedText();
648 }
649
650 /**
651 * @see InputConnection#getCursorCapsMode(int)
652 */
653 @Override
654 public int getCursorCapsMode(int reqModes) {
655 Log.d(TAG, "getCursorCapsMode [%x]", reqModes);
656 ImeUtils.assertNotOnUiThread();
657 // TODO(changwan): Auto-generated method stub
aelias_OOO_until_Jul13 2015/09/30 00:10:04 Looks like you have several rarely called methods
Changwan Ryu 2016/01/19 07:31:53 Since InputConnection is an interface, we still ne
658 return 0;
659 }
660
661 /**
662 * @see InputConnection#commitCompletion(android.view.inputmethod.Completion Info)
663 */
664 @Override
665 public boolean commitCompletion(CompletionInfo text) {
666 Log.d(TAG, "commitCompletion [%s]", text);
667 ImeUtils.assertNotOnUiThread();
668 // TODO(changwan): Auto-generated method stub
669 return false;
670 }
671
672 /**
673 * @see InputConnection#commitCorrection(android.view.inputmethod.Correction Info)
674 */
675 @Override
676 public boolean commitCorrection(CorrectionInfo correctionInfo) {
677 Log.d(TAG, "commitCorrection [%s]", ImeUtils.dumpCorrectionInfo(correcti onInfo));
678 ImeUtils.assertNotOnUiThread();
679 // TODO(changwan): Auto-generated method stub
680 return false;
681 }
682
683 /**
684 * @see InputConnection#clearMetaKeyStates(int)
685 */
686 @Override
687 public boolean clearMetaKeyStates(int states) {
688 Log.d(TAG, "clearMetaKeyStates [%x]", states);
689 ImeUtils.assertNotOnUiThread();
690 // TODO(changwan): Auto-generated method stub
691 return false;
692 }
693
694 /**
695 * @see InputConnection#reportFullscreenMode(boolean)
696 */
697 @Override
698 public boolean reportFullscreenMode(boolean enabled) {
699 Log.d(TAG, "reportFullscreenMode [%b]", enabled);
700 ImeUtils.assertNotOnUiThread();
701 // We ignore fullscreen mode for now. That's why we set
702 // EditorInfo.IME_FLAG_NO_FULLSCREEN in constructor.
703 return false;
704 }
705
706 /**
707 * @see InputConnection#performPrivateCommand(java.lang.String, android.os.B undle)
708 */
709 @Override
710 public boolean performPrivateCommand(String action, Bundle data) {
711 Log.d(TAG, "performPrivateCommand [%s]", action);
712 ImeUtils.assertNotOnUiThread();
713 // TODO(changwan): Auto-generated method stub
714 return false;
715 }
716
717 /**
718 * @see InputConnection#requestCursorUpdates(int)
719 */
720 @Override
721 public boolean requestCursorUpdates(int cursorUpdateMode) {
722 Log.d(TAG, "requestCursorUpdates [%x]", cursorUpdateMode);
723 ImeUtils.assertNotOnUiThread();
724 // TODO(changwan): Auto-generated method stub
725 return false;
726 }
727
728 /**
729 * TODO(changwan): add description
730 */
731 public void reset() {
732 ImeUtils.assertOnUiThread();
733 finishComposingText();
734 }
735 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698