OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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.Handler; | 7 import android.os.Handler; |
8 import android.os.ResultReceiver; | 8 import android.os.ResultReceiver; |
9 import android.os.SystemClock; | 9 import android.os.SystemClock; |
10 import android.text.Editable; | 10 import android.text.Editable; |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 } | 331 } |
332 | 332 |
333 /** | 333 /** |
334 * @return true if the selected text is of password. | 334 * @return true if the selected text is of password. |
335 */ | 335 */ |
336 public boolean isSelectionPassword() { | 336 public boolean isSelectionPassword() { |
337 return mTextInputType == sTextInputTypePassword; | 337 return mTextInputType == sTextInputTypePassword; |
338 } | 338 } |
339 | 339 |
340 public boolean dispatchKeyEvent(KeyEvent event) { | 340 public boolean dispatchKeyEvent(KeyEvent event) { |
341 return translateAndSendNativeEvents(event); | 341 // Physical keyboards have their events come through here instead of |
| 342 // AdapterInputConnection. |
| 343 if (mInputConnection != null) { |
| 344 return mInputConnection.sendKeyEvent(event); |
| 345 } |
| 346 return translateAndSendNativeEvents(event, 0); |
342 } | 347 } |
343 | 348 |
344 private int shouldSendKeyEventWithKeyCode(String text) { | 349 private int shouldSendKeyEventWithKeyCode(String text) { |
345 if (text.length() != 1) return COMPOSITION_KEY_CODE; | 350 if (text.length() != 1) return COMPOSITION_KEY_CODE; |
346 | 351 |
347 if (text.equals("\n")) return KeyEvent.KEYCODE_ENTER; | 352 if (text.equals("\n")) return KeyEvent.KEYCODE_ENTER; |
348 else if (text.equals("\t")) return KeyEvent.KEYCODE_TAB; | 353 else if (text.equals("\t")) return KeyEvent.KEYCODE_TAB; |
349 else return COMPOSITION_KEY_CODE; | 354 else return COMPOSITION_KEY_CODE; |
350 } | 355 } |
351 | 356 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 // modification) so return an unknown key-code. | 405 // modification) so return an unknown key-code. |
401 return null; | 406 return null; |
402 } | 407 } |
403 | 408 |
404 void sendKeyEventWithKeyCode(int keyCode, int flags) { | 409 void sendKeyEventWithKeyCode(int keyCode, int flags) { |
405 long eventTime = SystemClock.uptimeMillis(); | 410 long eventTime = SystemClock.uptimeMillis(); |
406 mLastSyntheticKeyCode = keyCode; | 411 mLastSyntheticKeyCode = keyCode; |
407 translateAndSendNativeEvents(new KeyEvent(eventTime, eventTime, | 412 translateAndSendNativeEvents(new KeyEvent(eventTime, eventTime, |
408 KeyEvent.ACTION_DOWN, keyCode, 0, 0, | 413 KeyEvent.ACTION_DOWN, keyCode, 0, 0, |
409 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, | 414 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, |
410 flags)); | 415 flags), 0); |
411 translateAndSendNativeEvents(new KeyEvent(SystemClock.uptimeMillis(), ev
entTime, | 416 translateAndSendNativeEvents(new KeyEvent(SystemClock.uptimeMillis(), ev
entTime, |
412 KeyEvent.ACTION_UP, keyCode, 0, 0, | 417 KeyEvent.ACTION_UP, keyCode, 0, 0, |
413 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, | 418 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, |
414 flags)); | 419 flags), 0); |
415 } | 420 } |
416 | 421 |
417 // Calls from Java to C++ | 422 // Calls from Java to C++ |
418 // TODO: Add performance tracing to more complicated functions. | 423 // TODO: Add performance tracing to more complicated functions. |
419 | 424 |
420 boolean checkCompositionQueueAndCallNative(CharSequence text, int newCursorP
osition, | 425 boolean checkCompositionQueueAndCallNative(CharSequence text, int newCursorP
osition, |
421 boolean isCommit) { | 426 boolean isCommit) { |
422 if (mNativeImeAdapterAndroid == 0) return false; | 427 if (mNativeImeAdapterAndroid == 0) return false; |
423 mViewEmbedder.onImeEvent(); | 428 mViewEmbedder.onImeEvent(); |
424 | 429 |
(...skipping 14 matching lines...) Expand all Loading... |
439 keyCode = KeyEvent.KEYCODE_UNKNOWN; | 444 keyCode = KeyEvent.KEYCODE_UNKNOWN; |
440 } else { | 445 } else { |
441 keyCode = -1; | 446 keyCode = -1; |
442 } | 447 } |
443 | 448 |
444 // If this is a commit with no previous composition, then treat it a
s a native | 449 // If this is a commit with no previous composition, then treat it a
s a native |
445 // KeyDown/KeyUp pair with no composition rather than a synthetic pa
ir with | 450 // KeyDown/KeyUp pair with no composition rather than a synthetic pa
ir with |
446 // composition below. | 451 // composition below. |
447 if (keyCode > 0 && isCommit && mLastComposeText == null) { | 452 if (keyCode > 0 && isCommit && mLastComposeText == null) { |
448 mLastSyntheticKeyCode = keyCode; | 453 mLastSyntheticKeyCode = keyCode; |
449 return translateAndSendNativeEvents(keyEvent) && | 454 return translateAndSendNativeEvents(keyEvent, 0) |
450 translateAndSendNativeEvents(KeyEvent.changeAction( | 455 && translateAndSendNativeEvents( |
451 keyEvent, KeyEvent.ACTION_UP)); | 456 KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_
UP), 0); |
452 } | 457 } |
453 | 458 |
454 // When typing, there is no issue sending KeyDown and KeyUp events a
round the | 459 // When typing, there is no issue sending KeyDown and KeyUp events a
round the |
455 // composition event because those key events do nothing (other than
call JS | 460 // composition event because those key events do nothing (other than
call JS |
456 // handlers). Typing does not cause changes outside of a KeyPress e
vent which | 461 // handlers). Typing does not cause changes outside of a KeyPress e
vent which |
457 // we don't call here. However, if the key-code is a control key su
ch as | 462 // we don't call here. However, if the key-code is a control key su
ch as |
458 // KEYCODE_DEL then there never is an associated KeyPress event and
the KeyDown | 463 // KEYCODE_DEL then there never is an associated KeyPress event and
the KeyDown |
459 // event itself causes the action. The net result below is that the
Renderer calls | 464 // event itself causes the action. The net result below is that the
Renderer calls |
460 // cancelComposition() and then Android starts anew with setComposin
gRegion(). | 465 // cancelComposition() and then Android starts anew with setComposin
gRegion(). |
461 // This stopping and restarting of composition could be a source of
problems | 466 // This stopping and restarting of composition could be a source of
problems |
(...skipping 30 matching lines...) Expand all Loading... |
492 mLastComposeText = textStr; | 497 mLastComposeText = textStr; |
493 return true; | 498 return true; |
494 } | 499 } |
495 | 500 |
496 void finishComposingText() { | 501 void finishComposingText() { |
497 mLastComposeText = null; | 502 mLastComposeText = null; |
498 if (mNativeImeAdapterAndroid == 0) return; | 503 if (mNativeImeAdapterAndroid == 0) return; |
499 nativeFinishComposingText(mNativeImeAdapterAndroid); | 504 nativeFinishComposingText(mNativeImeAdapterAndroid); |
500 } | 505 } |
501 | 506 |
502 boolean translateAndSendNativeEvents(KeyEvent event) { | 507 boolean translateAndSendNativeEvents(KeyEvent event, int accentChar) { |
503 if (mNativeImeAdapterAndroid == 0) return false; | 508 if (mNativeImeAdapterAndroid == 0) return false; |
504 | 509 |
505 int action = event.getAction(); | 510 int action = event.getAction(); |
506 if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_UP) { | 511 if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_UP) { |
507 // action == KeyEvent.ACTION_MULTIPLE | 512 // action == KeyEvent.ACTION_MULTIPLE |
508 // TODO(bulach): confirm the actual behavior. Apparently: | 513 // TODO(bulach): confirm the actual behavior. Apparently: |
509 // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a | 514 // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a |
510 // composition key down (229) followed by a commit text with the | 515 // composition key down (229) followed by a commit text with the |
511 // string from event.getUnicodeChars(). | 516 // string from event.getUnicodeChars(). |
512 // Otherwise, we'd need to send an event with a | 517 // Otherwise, we'd need to send an event with a |
513 // WebInputEvent::IsAutoRepeat modifier. We also need to verify when | 518 // WebInputEvent::IsAutoRepeat modifier. We also need to verify when |
514 // we receive ACTION_MULTIPLE: we may receive it after an ACTION_DOW
N, | 519 // we receive ACTION_MULTIPLE: we may receive it after an ACTION_DOW
N, |
515 // and if that's the case, we'll need to review when to send the Cha
r | 520 // and if that's the case, we'll need to review when to send the Cha
r |
516 // event. | 521 // event. |
517 return false; | 522 return false; |
518 } | 523 } |
519 mViewEmbedder.onImeEvent(); | 524 mViewEmbedder.onImeEvent(); |
| 525 int unicodeChar = AdapterInputConnection.maybeAddAccentToCharacter( |
| 526 accentChar, event.getUnicodeChar()); |
520 return nativeSendKeyEvent(mNativeImeAdapterAndroid, event, event.getActi
on(), | 527 return nativeSendKeyEvent(mNativeImeAdapterAndroid, event, event.getActi
on(), |
521 getModifiers(event.getMetaState()), event.getEventTime(), event.
getKeyCode(), | 528 getModifiers(event.getMetaState()), event.getEventTime(), event.
getKeyCode(), |
522 /*isSystemKey=*/false, event.getUnicodeChar()); | 529 /*isSystemKey=*/false, unicodeChar); |
523 } | 530 } |
524 | 531 |
525 boolean sendSyntheticKeyEvent(int eventType, long timestampMs, int keyCode,
int modifiers, | 532 boolean sendSyntheticKeyEvent(int eventType, long timestampMs, int keyCode,
int modifiers, |
526 int unicodeChar) { | 533 int unicodeChar) { |
527 if (mNativeImeAdapterAndroid == 0) return false; | 534 if (mNativeImeAdapterAndroid == 0) return false; |
528 | 535 |
529 nativeSendSyntheticKeyEvent( | 536 nativeSendSyntheticKeyEvent( |
530 mNativeImeAdapterAndroid, eventType, timestampMs, keyCode, modif
iers, unicodeChar); | 537 mNativeImeAdapterAndroid, eventType, timestampMs, keyCode, modif
iers, unicodeChar); |
531 return true; | 538 return true; |
532 } | 539 } |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid
, | 748 private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid
, |
742 int before, int after); | 749 int before, int after); |
743 | 750 |
744 private native void nativeUnselect(long nativeImeAdapterAndroid); | 751 private native void nativeUnselect(long nativeImeAdapterAndroid); |
745 private native void nativeSelectAll(long nativeImeAdapterAndroid); | 752 private native void nativeSelectAll(long nativeImeAdapterAndroid); |
746 private native void nativeCut(long nativeImeAdapterAndroid); | 753 private native void nativeCut(long nativeImeAdapterAndroid); |
747 private native void nativeCopy(long nativeImeAdapterAndroid); | 754 private native void nativeCopy(long nativeImeAdapterAndroid); |
748 private native void nativePaste(long nativeImeAdapterAndroid); | 755 private native void nativePaste(long nativeImeAdapterAndroid); |
749 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); | 756 private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); |
750 } | 757 } |
OLD | NEW |