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

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

Issue 1162863007: Translate physical keyboard accents to IME compositions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move mPendingAccent = 0 before finishComposingText early return Created 5 years, 6 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
« no previous file with comments | « no previous file | content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.content.browser.input; 5 package org.chromium.content.browser.input;
6 6
7 import android.os.SystemClock; 7 import android.os.SystemClock;
8 import android.text.Editable; 8 import android.text.Editable;
9 import android.text.InputType; 9 import android.text.InputType;
10 import android.text.Selection; 10 import android.text.Selection;
11 import android.text.TextUtils; 11 import android.text.TextUtils;
12 import android.util.Log; 12 import android.util.Log;
13 import android.view.KeyCharacterMap;
13 import android.view.KeyEvent; 14 import android.view.KeyEvent;
14 import android.view.View; 15 import android.view.View;
15 import android.view.inputmethod.BaseInputConnection; 16 import android.view.inputmethod.BaseInputConnection;
16 import android.view.inputmethod.EditorInfo; 17 import android.view.inputmethod.EditorInfo;
17 import android.view.inputmethod.ExtractedText; 18 import android.view.inputmethod.ExtractedText;
18 import android.view.inputmethod.ExtractedTextRequest; 19 import android.view.inputmethod.ExtractedTextRequest;
19 20
20 import org.chromium.base.VisibleForTesting; 21 import org.chromium.base.VisibleForTesting;
21 import org.chromium.blink_public.web.WebInputEventType; 22 import org.chromium.blink_public.web.WebInputEventType;
22 import org.chromium.blink_public.web.WebTextInputFlags; 23 import org.chromium.blink_public.web.WebTextInputFlags;
(...skipping 12 matching lines...) Expand all
35 */ 36 */
36 public static final int INVALID_SELECTION = -1; 37 public static final int INVALID_SELECTION = -1;
37 public static final int INVALID_COMPOSITION = -1; 38 public static final int INVALID_COMPOSITION = -1;
38 39
39 private final View mInternalView; 40 private final View mInternalView;
40 private final ImeAdapter mImeAdapter; 41 private final ImeAdapter mImeAdapter;
41 private final Editable mEditable; 42 private final Editable mEditable;
42 43
43 private boolean mSingleLine; 44 private boolean mSingleLine;
44 private int mNumNestedBatchEdits = 0; 45 private int mNumNestedBatchEdits = 0;
46 private int mPendingAccent;
45 47
46 private int mLastUpdateSelectionStart = INVALID_SELECTION; 48 private int mLastUpdateSelectionStart = INVALID_SELECTION;
47 private int mLastUpdateSelectionEnd = INVALID_SELECTION; 49 private int mLastUpdateSelectionEnd = INVALID_SELECTION;
48 private int mLastUpdateCompositionStart = INVALID_COMPOSITION; 50 private int mLastUpdateCompositionStart = INVALID_COMPOSITION;
49 private int mLastUpdateCompositionEnd = INVALID_COMPOSITION; 51 private int mLastUpdateCompositionEnd = INVALID_COMPOSITION;
50 52
51 @VisibleForTesting 53 @VisibleForTesting
52 AdapterInputConnection(View view, ImeAdapter imeAdapter, Editable editable, 54 AdapterInputConnection(View view, ImeAdapter imeAdapter, Editable editable,
53 EditorInfo outAttrs) { 55 EditorInfo outAttrs) {
54 super(view, true); 56 super(view, true);
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 mLastUpdateCompositionEnd = compositionEnd; 237 mLastUpdateCompositionEnd = compositionEnd;
236 } 238 }
237 239
238 /** 240 /**
239 * @see BaseInputConnection#setComposingText(java.lang.CharSequence, int) 241 * @see BaseInputConnection#setComposingText(java.lang.CharSequence, int)
240 */ 242 */
241 @Override 243 @Override
242 public boolean setComposingText(CharSequence text, int newCursorPosition) { 244 public boolean setComposingText(CharSequence text, int newCursorPosition) {
243 if (DEBUG) Log.w(TAG, "setComposingText [" + text + "] [" + newCursorPos ition + "]"); 245 if (DEBUG) Log.w(TAG, "setComposingText [" + text + "] [" + newCursorPos ition + "]");
244 if (maybePerformEmptyCompositionWorkaround(text)) return true; 246 if (maybePerformEmptyCompositionWorkaround(text)) return true;
247 mPendingAccent = 0;
245 super.setComposingText(text, newCursorPosition); 248 super.setComposingText(text, newCursorPosition);
246 updateSelectionIfRequired(); 249 updateSelectionIfRequired();
247 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos ition, false); 250 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos ition, false);
248 } 251 }
249 252
250 /** 253 /**
251 * @see BaseInputConnection#commitText(java.lang.CharSequence, int) 254 * @see BaseInputConnection#commitText(java.lang.CharSequence, int)
252 */ 255 */
253 @Override 256 @Override
254 public boolean commitText(CharSequence text, int newCursorPosition) { 257 public boolean commitText(CharSequence text, int newCursorPosition) {
255 if (DEBUG) Log.w(TAG, "commitText [" + text + "] [" + newCursorPosition + "]"); 258 if (DEBUG) Log.w(TAG, "commitText [" + text + "] [" + newCursorPosition + "]");
256 if (maybePerformEmptyCompositionWorkaround(text)) return true; 259 if (maybePerformEmptyCompositionWorkaround(text)) return true;
260 mPendingAccent = 0;
257 super.commitText(text, newCursorPosition); 261 super.commitText(text, newCursorPosition);
258 updateSelectionIfRequired(); 262 updateSelectionIfRequired();
259 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos ition, 263 return mImeAdapter.checkCompositionQueueAndCallNative(text, newCursorPos ition,
260 text.length() > 0); 264 text.length() > 0);
261 } 265 }
262 266
263 /** 267 /**
264 * @see BaseInputConnection#performEditorAction(int) 268 * @see BaseInputConnection#performEditorAction(int)
265 */ 269 */
266 @Override 270 @Override
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 @Override 348 @Override
345 public boolean deleteSurroundingText(int beforeLength, int afterLength) { 349 public boolean deleteSurroundingText(int beforeLength, int afterLength) {
346 return deleteSurroundingTextImpl(beforeLength, afterLength, false); 350 return deleteSurroundingTextImpl(beforeLength, afterLength, false);
347 } 351 }
348 352
349 private boolean deleteSurroundingTextImpl( 353 private boolean deleteSurroundingTextImpl(
350 int beforeLength, int afterLength, boolean fromPhysicalKey) { 354 int beforeLength, int afterLength, boolean fromPhysicalKey) {
351 if (DEBUG) { 355 if (DEBUG) {
352 Log.w(TAG, "deleteSurroundingText [" + beforeLength + " " + afterLen gth + "]"); 356 Log.w(TAG, "deleteSurroundingText [" + beforeLength + " " + afterLen gth + "]");
353 } 357 }
358
359 if (mPendingAccent != 0) {
360 finishComposingText();
361 }
362
354 int originalBeforeLength = beforeLength; 363 int originalBeforeLength = beforeLength;
355 int originalAfterLength = afterLength; 364 int originalAfterLength = afterLength;
356 int availableBefore = Selection.getSelectionStart(mEditable); 365 int availableBefore = Selection.getSelectionStart(mEditable);
357 int availableAfter = mEditable.length() - Selection.getSelectionEnd(mEdi table); 366 int availableAfter = mEditable.length() - Selection.getSelectionEnd(mEdi table);
358 beforeLength = Math.min(beforeLength, availableBefore); 367 beforeLength = Math.min(beforeLength, availableBefore);
359 afterLength = Math.min(afterLength, availableAfter); 368 afterLength = Math.min(afterLength, availableAfter);
360 super.deleteSurroundingText(beforeLength, afterLength); 369 super.deleteSurroundingText(beforeLength, afterLength);
361 updateSelectionIfRequired(); 370 updateSelectionIfRequired();
362 371
363 // If this was called due to a physical key, no need to generate a key e vent here as 372 // If this was called due to a physical key, no need to generate a key e vent here as
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 @Override 405 @Override
397 public boolean sendKeyEvent(KeyEvent event) { 406 public boolean sendKeyEvent(KeyEvent event) {
398 if (DEBUG) { 407 if (DEBUG) {
399 Log.w(TAG, "sendKeyEvent [" + event.getAction() + "] [" + event.getK eyCode() + "]"); 408 Log.w(TAG, "sendKeyEvent [" + event.getAction() + "] [" + event.getK eyCode() + "]");
400 } 409 }
401 410
402 int action = event.getAction(); 411 int action = event.getAction();
403 int keycode = event.getKeyCode(); 412 int keycode = event.getKeyCode();
404 int unicodeChar = event.getUnicodeChar(); 413 int unicodeChar = event.getUnicodeChar();
405 414
415 // If this isn't a KeyDown event, no need to update composition state; j ust pass the key
416 // event through and return.
417 if (action != KeyEvent.ACTION_DOWN) {
418 mImeAdapter.translateAndSendNativeEvents(event);
419 return true;
420 }
421
406 // If this is backspace/del or if the key has a character representation , 422 // If this is backspace/del or if the key has a character representation ,
407 // need to update the underlying Editable (i.e. the local representation of the text 423 // need to update the underlying Editable (i.e. the local representation of the text
408 // being edited). Some IMEs like Jellybean stock IME and Samsung IME mi x in delete 424 // being edited). Some IMEs like Jellybean stock IME and Samsung IME mi x in delete
409 // KeyPress events instead of calling deleteSurroundingText. 425 // KeyPress events instead of calling deleteSurroundingText.
410 if (action == KeyEvent.ACTION_DOWN && keycode == KeyEvent.KEYCODE_DEL) { 426 if (keycode == KeyEvent.KEYCODE_DEL) {
411 deleteSurroundingTextImpl(1, 0, true); 427 deleteSurroundingTextImpl(1, 0, true);
412 } else if (action == KeyEvent.ACTION_DOWN && keycode == KeyEvent.KEYCODE _FORWARD_DEL) { 428 } else if (keycode == KeyEvent.KEYCODE_FORWARD_DEL) {
413 deleteSurroundingTextImpl(0, 1, true); 429 deleteSurroundingTextImpl(0, 1, true);
414 } else if (action == KeyEvent.ACTION_DOWN && keycode == KeyEvent.KEYCODE _ENTER) { 430 } else if (keycode == KeyEvent.KEYCODE_ENTER) {
415 // Finish text composition when pressing enter, as that may submit a form field. 431 // Finish text composition when pressing enter, as that may submit a form field.
416 // TODO(aurimas): remove this workaround when crbug.com/278584 is fi xed. 432 // TODO(aurimas): remove this workaround when crbug.com/278584 is fi xed.
417 beginBatchEdit(); 433 beginBatchEdit();
418 finishComposingText(); 434 finishComposingText();
419 mImeAdapter.translateAndSendNativeEvents(event); 435 mImeAdapter.translateAndSendNativeEvents(event);
420 endBatchEdit(); 436 endBatchEdit();
421 return true; 437 return true;
422 } else if (action == KeyEvent.ACTION_UP && unicodeChar != 0) { 438 } else if ((unicodeChar & KeyCharacterMap.COMBINING_ACCENT) != 0) {
439 // Store a pending accent character and make it the current composit ion.
440 int pendingAccent = unicodeChar & KeyCharacterMap.COMBINING_ACCENT_M ASK;
441 StringBuilder builder = new StringBuilder();
442 builder.appendCodePoint(pendingAccent);
443 setComposingText(builder.toString(), 1);
444 mPendingAccent = pendingAccent;
445 return true;
446 }
447
448 if (unicodeChar != 0) {
449 if (mPendingAccent != 0) {
450 int combined = KeyEvent.getDeadChar(mPendingAccent, unicodeChar) ;
451 if (combined != 0) {
452 StringBuilder builder = new StringBuilder();
453 builder.appendCodePoint(combined);
454 commitText(builder.toString(), 1);
455 return true;
456 }
457 // Noncombinable character; commit the accent character and fall through to sending
458 // the key event for the character afterwards.
459 finishComposingText();
460 }
461
462 // Update the mEditable state to reflect what Blink will do in respo nse to the KeyDown
463 // for a unicode-mapped key event.
423 int selectionStart = Selection.getSelectionStart(mEditable); 464 int selectionStart = Selection.getSelectionStart(mEditable);
424 int selectionEnd = Selection.getSelectionEnd(mEditable); 465 int selectionEnd = Selection.getSelectionEnd(mEditable);
425 if (selectionStart > selectionEnd) { 466 if (selectionStart > selectionEnd) {
426 int temp = selectionStart; 467 int temp = selectionStart;
427 selectionStart = selectionEnd; 468 selectionStart = selectionEnd;
428 selectionEnd = temp; 469 selectionEnd = temp;
429 } 470 }
430 mEditable.replace(selectionStart, selectionEnd, 471 mEditable.replace(selectionStart, selectionEnd,
431 Character.toString((char) unicodeChar)); 472 Character.toString((char) unicodeChar));
432 } 473 }
474
433 mImeAdapter.translateAndSendNativeEvents(event); 475 mImeAdapter.translateAndSendNativeEvents(event);
434 return true; 476 return true;
435 } 477 }
436 478
437 /** 479 /**
438 * @see BaseInputConnection#finishComposingText() 480 * @see BaseInputConnection#finishComposingText()
439 */ 481 */
440 @Override 482 @Override
441 public boolean finishComposingText() { 483 public boolean finishComposingText() {
442 if (DEBUG) Log.w(TAG, "finishComposingText"); 484 if (DEBUG) Log.w(TAG, "finishComposingText");
485
486 mPendingAccent = 0;
487
443 if (getComposingSpanStart(mEditable) == getComposingSpanEnd(mEditable)) { 488 if (getComposingSpanStart(mEditable) == getComposingSpanEnd(mEditable)) {
444 return true; 489 return true;
445 } 490 }
446 491
447 super.finishComposingText(); 492 super.finishComposingText();
448 updateSelectionIfRequired(); 493 updateSelectionIfRequired();
449 mImeAdapter.finishComposingText(); 494 mImeAdapter.finishComposingText();
450 495
451 return true; 496 return true;
452 } 497 }
(...skipping 12 matching lines...) Expand all
465 } 510 }
466 511
467 /** 512 /**
468 * Informs the InputMethodManager and InputMethodSession (i.e. the IME) that the text 513 * Informs the InputMethodManager and InputMethodSession (i.e. the IME) that the text
469 * state is no longer what the IME has and that it needs to be updated. 514 * state is no longer what the IME has and that it needs to be updated.
470 */ 515 */
471 void restartInput() { 516 void restartInput() {
472 if (DEBUG) Log.w(TAG, "restartInput"); 517 if (DEBUG) Log.w(TAG, "restartInput");
473 getInputMethodManagerWrapper().restartInput(mInternalView); 518 getInputMethodManagerWrapper().restartInput(mInternalView);
474 mNumNestedBatchEdits = 0; 519 mNumNestedBatchEdits = 0;
520 mPendingAccent = 0;
475 } 521 }
476 522
477 /** 523 /**
478 * @see BaseInputConnection#setComposingRegion(int, int) 524 * @see BaseInputConnection#setComposingRegion(int, int)
479 */ 525 */
480 @Override 526 @Override
481 public boolean setComposingRegion(int start, int end) { 527 public boolean setComposingRegion(int start, int end) {
482 if (DEBUG) Log.w(TAG, "setComposingRegion [" + start + " " + end + "]"); 528 if (DEBUG) Log.w(TAG, "setComposingRegion [" + start + " " + end + "]");
483 int textLength = mEditable.length(); 529 int textLength = mEditable.length();
484 int a = Math.min(start, end); 530 int a = Math.min(start, end);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 @VisibleForTesting 604 @VisibleForTesting
559 ImeState getImeStateForTesting() { 605 ImeState getImeStateForTesting() {
560 String text = mEditable.toString(); 606 String text = mEditable.toString();
561 int selectionStart = Selection.getSelectionStart(mEditable); 607 int selectionStart = Selection.getSelectionStart(mEditable);
562 int selectionEnd = Selection.getSelectionEnd(mEditable); 608 int selectionEnd = Selection.getSelectionEnd(mEditable);
563 int compositionStart = getComposingSpanStart(mEditable); 609 int compositionStart = getComposingSpanStart(mEditable);
564 int compositionEnd = getComposingSpanEnd(mEditable); 610 int compositionEnd = getComposingSpanEnd(mEditable);
565 return new ImeState(text, selectionStart, selectionEnd, compositionStart , compositionEnd); 611 return new ImeState(text, selectionStart, selectionEnd, compositionStart , compositionEnd);
566 } 612 }
567 } 613 }
OLDNEW
« no previous file with comments | « no previous file | content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698