10f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)package org.chromium.content.browser.input; 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.os.Handler; 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.os.ResultReceiver; 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)import android.os.SystemClock; 1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.text.Editable; 116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)import android.text.SpannableString; 126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)import android.text.style.BackgroundColorSpan; 136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)import android.text.style.CharacterStyle; 146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)import android.text.style.UnderlineSpan; 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.view.KeyCharacterMap; 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.view.KeyEvent; 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.view.View; 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.view.inputmethod.EditorInfo; 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import org.chromium.base.CalledByNative; 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import org.chromium.base.JNINamespace; 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.base.VisibleForTesting; 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.ui.picker.InputDialogContainer; 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport java.lang.CharSequence; 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Adapts and plumbs android IME service onto the chrome text input API. 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * ImeAdapter provides an interface in both ways native <-> java: 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 1. InputConnectionAdapter notifies native code of text composition state and 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * dispatch key events from java -> WebKit. 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 2. Native ImeAdapter notifies java side to clear composition text. 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * The basic flow is: 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 1. When InputConnectionAdapter gets called with composition or result text: 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * If we receive a composition text or a result text, then we just need to 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * dispatch a synthetic key event with special keycode 229, and then dispatch 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the composition or result text. 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 2. Intercept dispatchKeyEvent() method for key events not handled by IME, we 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * need to dispatch them to webkit and check webkit's reply. Then inject a 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * new key event for further processing if webkit didn't handle it. 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Note that the native peer object does not take any strong reference onto the 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * instance of this java object, hence it is up to the client of this class (e.g. 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the ViewEmbedder implementor) to hold a strong reference to it for the required 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * lifetime of the object. 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)@JNINamespace("content") 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public class ImeAdapter { 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /** 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Interface for the delegate that needs to be notified of IME changes. 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public interface ImeAdapterDelegate { 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Called to notify the delegate about synthetic/real key events before sending to renderer. 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void onImeEvent(); 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called when a request to hide the keyboard is sent to InputMethodManager. 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void onDismissInput(); 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** 665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @return View that the keyboard should be attached to. 675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) View getAttachedView(); 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @return Object that should be called for all keyboard show and hide requests. 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ResultReceiver getNewShowKeyboardReceiver(); 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private class DelayedDismissInput implements Runnable { 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private long mNativeImeAdapter; 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DelayedDismissInput(long nativeImeAdapter) { 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mNativeImeAdapter = nativeImeAdapter; 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // http://crbug.com/413744 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void detach() { 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mNativeImeAdapter = 0; 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) @Override 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public void run() { 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mNativeImeAdapter != 0) { 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci attach(mNativeImeAdapter, sTextInputTypeNone, sTextInputFlagNone); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dismissInput(true); 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private static final int COMPOSITION_KEY_CODE = 229; 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Delay introduced to avoid hiding the keyboard if new show requests are received. 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The time required by the unfocus-focus events triggered by tab has been measured in soju: 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Mean: 18.633 ms, Standard deviation: 7.9837 ms. 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The value here should be higher enough to cover these cases, but not too high to avoid 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // letting the user perceiving important delays. 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private static final int INPUT_DISMISS_DELAY = 150; 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // All the constants that are retrieved from the C++ code. 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // They get set through initializeWebInputEvents and initializeTextInputTypes calls. 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sEventTypeRawKeyDown; 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sEventTypeKeyUp; 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sEventTypeChar; 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sTextInputTypeNone; 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sTextInputTypeText; 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sTextInputTypeTextArea; 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sTextInputTypePassword; 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sTextInputTypeSearch; 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sTextInputTypeUrl; 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sTextInputTypeEmail; 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sTextInputTypeTel; 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sTextInputTypeNumber; 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sTextInputTypeContentEditable; 1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static int sTextInputFlagNone = 0; 1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static int sTextInputFlagAutocompleteOn; 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static int sTextInputFlagAutocompleteOff; 1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static int sTextInputFlagAutocorrectOn; 1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static int sTextInputFlagAutocorrectOff; 1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static int sTextInputFlagSpellcheckOn; 1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static int sTextInputFlagSpellcheckOff; 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sModifierShift; 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sModifierAlt; 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sModifierCtrl; 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sModifierCapsLockOn; 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int sModifierNumLockOn; 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static char[] sSingleCharArray = new char[1]; 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static KeyCharacterMap sKeyCharacterMap; 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private long mNativeImeAdapterAndroid; 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private InputMethodManagerWrapper mInputMethodManagerWrapper; 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private AdapterInputConnection mInputConnection; 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private final ImeAdapterDelegate mViewEmbedder; 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private final Handler mHandler; 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private DelayedDismissInput mDismissInput = null; 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private int mTextInputType; 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private int mTextInputFlags; 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private String mLastComposeText; 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) @VisibleForTesting 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int mLastSyntheticKeyCode; 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) @VisibleForTesting 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) boolean mIsShowWithoutHideOutstanding = false; 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * @param wrapper InputMethodManagerWrapper that should receive all the call directed to 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * InputMethodManager. 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param embedder The view that is used for callbacks from ImeAdapter. 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embedder) { 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mInputMethodManagerWrapper = wrapper; 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mViewEmbedder = embedder; 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mHandler = new Handler(); 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /** 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Default factory for AdapterInputConnection classes. 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public static class AdapterInputConnectionFactory { 16723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public AdapterInputConnection get(View view, ImeAdapter imeAdapter, 16823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) Editable editable, EditorInfo outAttrs) { 16923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return new AdapterInputConnection(view, imeAdapter, editable, outAttrs); 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** 1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Overrides the InputMethodManagerWrapper that ImeAdapter uses to make calls to 1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * InputMethodManager. 1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param immw InputMethodManagerWrapper that should be used to call InputMethodManager. 1775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) @VisibleForTesting 1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) { 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mInputMethodManagerWrapper = immw; 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Should be only used by AdapterInputConnection. 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return InputMethodManagerWrapper that should receive all the calls directed to 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * InputMethodManager. 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) InputMethodManagerWrapper getInputMethodManagerWrapper() { 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return mInputMethodManagerWrapper; 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Set the current active InputConnection when a new InputConnection is constructed. 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param inputConnection The input connection that is currently used with IME. 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void setInputConnection(AdapterInputConnection inputConnection) { 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mInputConnection = inputConnection; 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mLastComposeText = null; 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * Should be used only by AdapterInputConnection. 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return The input type of currently focused element. 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int getTextInputType() { 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return mTextInputType; 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** 2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * Should be used only by AdapterInputConnection. 2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * @return The input flags of the currently focused element. 2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) */ 2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int getTextInputFlags() { 2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return mTextInputFlags; 2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) /** 2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @return Constant representing that a focused node is not an input field. 2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public static int getTextInputTypeNone() { 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return sTextInputTypeNone; 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private static int getModifiers(int metaState) { 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int modifiers = 0; 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ((metaState & KeyEvent.META_SHIFT_ON) != 0) { 227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) modifiers |= sModifierShift; 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ((metaState & KeyEvent.META_ALT_ON) != 0) { 230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) modifiers |= sModifierAlt; 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ((metaState & KeyEvent.META_CTRL_ON) != 0) { 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) modifiers |= sModifierCtrl; 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ((metaState & KeyEvent.META_CAPS_LOCK_ON) != 0) { 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) modifiers |= sModifierCapsLockOn; 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ((metaState & KeyEvent.META_NUM_LOCK_ON) != 0) { 239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) modifiers |= sModifierNumLockOn; 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return modifiers; 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** 2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Shows or hides the keyboard based on passed parameters. 2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param nativeImeAdapter Pointer to the ImeAdapterAndroid object that is sending the update. 2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param textInputType Text input type for the currently focused field in renderer. 2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param showIfNeeded Whether the keyboard should be shown if it is currently hidden. 2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public void updateKeyboardVisibility(long nativeImeAdapter, int textInputType, 2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int textInputFlags, boolean showIfNeeded) { 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mHandler.removeCallbacks(mDismissInput); 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If current input type is none and showIfNeeded is false, IME should not be shown 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // and input type should remain as none. 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mTextInputType == sTextInputTypeNone && !showIfNeeded) { 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (mNativeImeAdapterAndroid != nativeImeAdapter || mTextInputType != textInputType) { 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set a delayed task to perform unfocus. This avoids hiding the keyboard when tabbing 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // through text inputs or when JS rapidly changes focus to another text element. 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (textInputType == sTextInputTypeNone) { 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mDismissInput = new DelayedDismissInput(nativeImeAdapter); 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mHandler.postDelayed(mDismissInput, INPUT_DISMISS_DELAY); 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) attach(nativeImeAdapter, textInputType, textInputFlags); 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView()); 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (showIfNeeded) { 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) showKeyboard(); 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (hasInputType() && showIfNeeded) { 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) showKeyboard(); 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public void attach(long nativeImeAdapter, int textInputType, int textInputFlags) { 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid != 0) { 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) nativeResetImeAdapter(mNativeImeAdapterAndroid); 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mNativeImeAdapterAndroid = nativeImeAdapter; 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mTextInputType = textInputType; 2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mTextInputFlags = textInputFlags; 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mLastComposeText = null; 288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (nativeImeAdapter != 0) { 289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) nativeAttachImeAdapter(mNativeImeAdapterAndroid); 290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (mTextInputType == sTextInputTypeNone) { 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dismissInput(false); 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Attaches the imeAdapter to its native counterpart. This is needed to start forwarding 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * keyboard events to WebKit. 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param nativeImeAdapter The pointer to the native ImeAdapter object. 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void attach(long nativeImeAdapter) { 3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) attach(nativeImeAdapter, sTextInputTypeNone, sTextInputFlagNone); 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private void showKeyboard() { 306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mIsShowWithoutHideOutstanding = true; 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mInputMethodManagerWrapper.showSoftInput(mViewEmbedder.getAttachedView(), 0, 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mViewEmbedder.getNewShowKeyboardReceiver()); 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private void dismissInput(boolean unzoomIfNeeded) { 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mIsShowWithoutHideOutstanding = false; 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) View view = mViewEmbedder.getAttachedView(); 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mInputMethodManagerWrapper.isActive(view)) { 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mInputMethodManagerWrapper.hideSoftInputFromWindow(view.getWindowToken(), 0, 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unzoomIfNeeded ? mViewEmbedder.getNewShowKeyboardReceiver() : null); 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) mViewEmbedder.onDismissInput(); 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private boolean hasInputType() { 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return mTextInputType != sTextInputTypeNone; 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) private static boolean isTextInputType(int type) { 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return type != sTextInputTypeNone && !InputDialogContainer.isDialogInputType(type); 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public boolean hasTextInputType() { 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return isTextInputType(mTextInputType); 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /** 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return true if the selected text is of password. 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public boolean isSelectionPassword() { 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return mTextInputType == sTextInputTypePassword; 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public boolean dispatchKeyEvent(KeyEvent event) { 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return translateAndSendNativeEvents(event); 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private int shouldSendKeyEventWithKeyCode(String text) { 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (text.length() != 1) return COMPOSITION_KEY_CODE; 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (text.equals("\n")) return KeyEvent.KEYCODE_ENTER; 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else if (text.equals("\t")) return KeyEvent.KEYCODE_TAB; 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else return COMPOSITION_KEY_CODE; 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 3536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * @return Android KeyEvent for a single unicode character. Only one KeyEvent is returned 3546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * even if the system determined that various modifier keys (like Shift) would also have 3556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * been pressed. 3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 3576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private static KeyEvent androidKeyEventForCharacter(char chr) { 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (sKeyCharacterMap == null) { 3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sKeyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); 3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sSingleCharArray[0] = chr; 3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO: Evaluate cost of this system call. 3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) KeyEvent[] events = sKeyCharacterMap.getEvents(sSingleCharArray); 3646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (events == null) { // No known key sequence will create that character. 3656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return null; 3666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (int i = 0; i < events.length; ++i) { 3696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (events[i].getAction() == KeyEvent.ACTION_DOWN && 3706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) !KeyEvent.isModifierKey(events[i].getKeyCode())) { 3716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return events[i]; 3726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return null; // No printing characters were found. 3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) @VisibleForTesting 3796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public static KeyEvent getTypedKeyEventGuess(String oldtext, String newtext) { 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Starting typing a new composition should add only a single character. Any composition 3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // beginning with text longer than that must come from something other than typing so 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // return 0. 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (oldtext == null) { 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (newtext.length() == 1) { 3856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return androidKeyEventForCharacter(newtext.charAt(0)); 3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 3876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return null; 3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The content has grown in length: assume the last character is the key that caused it. 3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (newtext.length() > oldtext.length() && newtext.startsWith(oldtext)) 3936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return androidKeyEventForCharacter(newtext.charAt(newtext.length() - 1)); 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The content has shrunk in length: assume that backspace was pressed. 3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (oldtext.length() > newtext.length() && oldtext.startsWith(newtext)) 3976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL); 3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The content is unchanged or has undergone a complex change (i.e. not a simple tail 4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // modification) so return an unknown key-code. 4016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return null; 4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void sendKeyEventWithKeyCode(int keyCode, int flags) { 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) long eventTime = SystemClock.uptimeMillis(); 4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mLastSyntheticKeyCode = keyCode; 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) translateAndSendNativeEvents(new KeyEvent(eventTime, eventTime, 408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KeyEvent.ACTION_DOWN, keyCode, 0, 0, 409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) flags)); 411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) translateAndSendNativeEvents(new KeyEvent(SystemClock.uptimeMillis(), eventTime, 412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KeyEvent.ACTION_UP, keyCode, 0, 0, 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) flags)); 415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Calls from Java to C++ 4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO: Add performance tracing to more complicated functions. 419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) boolean checkCompositionQueueAndCallNative(CharSequence text, int newCursorPosition, 421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) boolean isCommit) { 422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mViewEmbedder.onImeEvent(); 424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) String textStr = text.toString(); 4266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int keyCode = shouldSendKeyEventWithKeyCode(textStr); 427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) long timeStampMs = SystemClock.uptimeMillis(); 428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (keyCode != COMPOSITION_KEY_CODE) { 430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sendKeyEventWithKeyCode(keyCode, 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE); 432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 4336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) KeyEvent keyEvent = getTypedKeyEventGuess(mLastComposeText, textStr); 4346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int modifiers = 0; 4356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (keyEvent != null) { 4366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) keyCode = keyEvent.getKeyCode(); 4376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) modifiers = getModifiers(keyEvent.getMetaState()); 4386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if (!textStr.equals(mLastComposeText)) { 4396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) keyCode = KeyEvent.KEYCODE_UNKNOWN; 4406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 4416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) keyCode = -1; 4426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 4436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If this is a commit with no previous composition, then treat it as a native 4456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // KeyDown/KeyUp pair with no composition rather than a synthetic pair with 4466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // composition below. 4476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (keyCode > 0 && isCommit && mLastComposeText == null) { 4486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mLastSyntheticKeyCode = keyCode; 4496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return translateAndSendNativeEvents(keyEvent) && 4506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) translateAndSendNativeEvents(KeyEvent.changeAction( 4516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) keyEvent, KeyEvent.ACTION_UP)); 4526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // When typing, there is no issue sending KeyDown and KeyUp events around the 4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // composition event because those key events do nothing (other than call JS 4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // handlers). Typing does not cause changes outside of a KeyPress event which 4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // we don't call here. However, if the key-code is a control key such as 4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // KEYCODE_DEL then there never is an associated KeyPress event and the KeyDown 4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // event itself causes the action. The net result below is that the Renderer calls 4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // cancelComposition() and then Android starts anew with setComposingRegion(). 4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This stopping and restarting of composition could be a source of problems 4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // with 3rd party keyboards. 4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // 4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // An alternative is to *not* call nativeSetComposingText() in the non-commit case 4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // below. This avoids the restart of composition described above but fails to send 4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // an update to the composition while in composition which, strictly speaking, 4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // does not match the spec. 4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // 4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // For now, the solution is to endure the restarting of composition and only dive 4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // into the alternate solution should there be problems in the field. --bcwhite 4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (keyCode >= 0) { 4736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawKeyDown, 4746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) timeStampMs, keyCode, modifiers, 0); 4756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (isCommit) { 4786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) nativeCommitText(mNativeImeAdapterAndroid, textStr); 4796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) textStr = null; 480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 4816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) nativeSetComposingText(mNativeImeAdapterAndroid, text, textStr, newCursorPosition); 482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (keyCode >= 0) { 4856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyUp, 4866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) timeStampMs, keyCode, modifiers, 0); 4876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 4886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mLastSyntheticKeyCode = keyCode; 490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mLastComposeText = textStr; 493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch void finishComposingText() { 4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mLastComposeText = null; 498c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (mNativeImeAdapterAndroid == 0) return; 4997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch nativeFinishComposingText(mNativeImeAdapterAndroid); 5007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 5017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) boolean translateAndSendNativeEvents(KeyEvent event) { 503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int action = event.getAction(); 506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (action != KeyEvent.ACTION_DOWN && 507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) action != KeyEvent.ACTION_UP) { 508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // action == KeyEvent.ACTION_MULTIPLE 509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(bulach): confirm the actual behavior. Apparently: 510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // composition key down (229) followed by a commit text with the 512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // string from event.getUnicodeChars(). 513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Otherwise, we'd need to send an event with a 514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // WebInputEvent::IsAutoRepeat modifier. We also need to verify when 515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we receive ACTION_MULTIPLE: we may receive it after an ACTION_DOWN, 516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // and if that's the case, we'll need to review when to send the Char 517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // event. 518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mViewEmbedder.onImeEvent(); 521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return nativeSendKeyEvent(mNativeImeAdapterAndroid, event, event.getAction(), 522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) getModifiers(event.getMetaState()), event.getEventTime(), event.getKeyCode(), 52308c107de54178bb0990a09adec724924e8bc9486Primiano Tucci /*isSystemKey=*/false, event.getUnicodeChar()); 524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) boolean sendSyntheticKeyEvent(int eventType, long timestampMs, int keyCode, int modifiers, 5276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int unicodeChar) { 528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) nativeSendSyntheticKeyEvent( 5316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mNativeImeAdapterAndroid, eventType, timestampMs, keyCode, modifiers, unicodeChar); 532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** 5365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Send a request to the native counterpart to delete a given range of characters. 5375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param beforeLength Number of characters to extend the selection by before the existing 5385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * selection. 5395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param afterLength Number of characters to extend the selection by after the existing 5405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * selection. 5415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @return Whether the native counterpart of ImeAdapter received the call. 5425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 5430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) boolean deleteSurroundingText(int beforeLength, int afterLength) { 5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mViewEmbedder.onImeEvent(); 545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 5460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) nativeDeleteSurroundingText(mNativeImeAdapterAndroid, beforeLength, afterLength); 547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** 5515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Send a request to the native counterpart to set the selection to given range. 5525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param start Selection start index. 5535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param end Selection end index. 5545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @return Whether the native counterpart of ImeAdapter received the call. 5555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 5560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) boolean setEditableSelectionOffsets(int start, int end) { 557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end); 559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 5635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Send a request to the native counterpart to set composing region to given indices. 564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param start The start of the composition. 565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param end The end of the composition. 566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return Whether the native counterpart of ImeAdapter received the call. 567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) boolean setComposingRegion(CharSequence text, int start, int end) { 569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end); 5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mLastComposeText = text != null ? text.toString() : null; 572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Send a request to the native counterpart to unselect text. 577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return Whether the native counterpart of ImeAdapter received the call. 578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public boolean unselect() { 580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) nativeUnselect(mNativeImeAdapterAndroid); 582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Send a request to the native counterpart of ImeAdapter to select all the text. 587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return Whether the native counterpart of ImeAdapter received the call. 588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public boolean selectAll() { 590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) nativeSelectAll(mNativeImeAdapterAndroid); 592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Send a request to the native counterpart of ImeAdapter to cut the selected text. 597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return Whether the native counterpart of ImeAdapter received the call. 598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public boolean cut() { 600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) nativeCut(mNativeImeAdapterAndroid); 602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Send a request to the native counterpart of ImeAdapter to copy the selected text. 607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return Whether the native counterpart of ImeAdapter received the call. 608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public boolean copy() { 610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) nativeCopy(mNativeImeAdapterAndroid); 612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Send a request to the native counterpart of ImeAdapter to paste the text from the clipboard. 617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @return Whether the native counterpart of ImeAdapter received the call. 618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public boolean paste() { 620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mNativeImeAdapterAndroid == 0) return false; 621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) nativePaste(mNativeImeAdapterAndroid); 622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Calls from C++ to Java 626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) @CalledByNative 628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private static void initializeWebInputEvents(int eventTypeRawKeyDown, int eventTypeKeyUp, 629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int eventTypeChar, int modifierShift, int modifierAlt, int modifierCtrl, 630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int modifierCapsLockOn, int modifierNumLockOn) { 631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sEventTypeRawKeyDown = eventTypeRawKeyDown; 632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sEventTypeKeyUp = eventTypeKeyUp; 633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sEventTypeChar = eventTypeChar; 634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sModifierShift = modifierShift; 635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sModifierAlt = modifierAlt; 636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sModifierCtrl = modifierCtrl; 637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sModifierCapsLockOn = modifierCapsLockOn; 638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sModifierNumLockOn = modifierNumLockOn; 639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) @CalledByNative 642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private static void initializeTextInputTypes(int textInputTypeNone, int textInputTypeText, 643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int textInputTypeTextArea, int textInputTypePassword, int textInputTypeSearch, 644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int textInputTypeUrl, int textInputTypeEmail, int textInputTypeTel, 6454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int textInputTypeNumber, int textInputTypeContentEditable) { 646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sTextInputTypeNone = textInputTypeNone; 647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sTextInputTypeText = textInputTypeText; 648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sTextInputTypeTextArea = textInputTypeTextArea; 649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sTextInputTypePassword = textInputTypePassword; 650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sTextInputTypeSearch = textInputTypeSearch; 651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sTextInputTypeUrl = textInputTypeUrl; 652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sTextInputTypeEmail = textInputTypeEmail; 653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sTextInputTypeTel = textInputTypeTel; 654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sTextInputTypeNumber = textInputTypeNumber; 655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sTextInputTypeContentEditable = textInputTypeContentEditable; 656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) @CalledByNative 6596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private static void initializeTextInputFlags( 6606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int textInputFlagAutocompleteOn, int textInputFlagAutocompleteOff, 6616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int textInputFlagAutocorrectOn, int textInputFlagAutocorrectOff, 6626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int textInputFlagSpellcheckOn, int textInputFlagSpellcheckOff) { 6636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sTextInputFlagAutocompleteOn = textInputFlagAutocompleteOn; 6646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sTextInputFlagAutocompleteOff = textInputFlagAutocompleteOff; 6656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sTextInputFlagAutocorrectOn = textInputFlagAutocorrectOn; 6666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sTextInputFlagAutocorrectOff = textInputFlagAutocorrectOff; 6676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sTextInputFlagSpellcheckOn = textInputFlagSpellcheckOn; 6686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sTextInputFlagSpellcheckOff = textInputFlagSpellcheckOff; 6696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 6706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 6716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) @CalledByNative 6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private void focusedNodeChanged(boolean isEditable) { 6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (mInputConnection != null && isEditable) mInputConnection.restartInput(); 6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) @CalledByNative 6776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) private void populateUnderlinesFromSpans(CharSequence text, long underlines) { 6786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!(text instanceof SpannableString)) return; 6796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 6806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) SpannableString spannableString = ((SpannableString) text); 6816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) CharacterStyle spans[] = 6826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) spannableString.getSpans(0, text.length(), CharacterStyle.class); 6836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (CharacterStyle span : spans) { 6846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (span instanceof BackgroundColorSpan) { 6856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) nativeAppendBackgroundColorSpan(underlines, spannableString.getSpanStart(span), 6866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) spannableString.getSpanEnd(span), 6876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ((BackgroundColorSpan) span).getBackgroundColor()); 6886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } else if (span instanceof UnderlineSpan) { 6896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) nativeAppendUnderlineSpan(underlines, spannableString.getSpanStart(span), 6906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) spannableString.getSpanEnd(span)); 6916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 6926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 6936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 6946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 6956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) @CalledByNative 696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private void cancelComposition() { 6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (mInputConnection != null) mInputConnection.restartInput(); 6985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mLastComposeText = null; 699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) @CalledByNative 702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void detach() { 7031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mDismissInput != null) { 7041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mHandler.removeCallbacks(mDismissInput); 7051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mDismissInput.detach(); 7061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mNativeImeAdapterAndroid = 0; 708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mTextInputType = 0; 709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndroid, 7126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int eventType, long timestampMs, int keyCode, int modifiers, int unicodeChar); 713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 714f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyEvent event, 715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int action, int modifiers, long timestampMs, int keyCode, boolean isSystemKey, 716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int unicodeChar); 717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end); 7196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 7206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) private static native void nativeAppendBackgroundColorSpan(long underlinePtr, int start, 7216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int end, int backgroundColor); 7226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 7236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) private native void nativeSetComposingText(long nativeImeAdapterAndroid, CharSequence text, 7246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) String textStr, int newCursorPosition); 725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) private native void nativeCommitText(long nativeImeAdapterAndroid, String textStr); 727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 728f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeFinishComposingText(long nativeImeAdapterAndroid); 7297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 730f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid); 731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 732f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterAndroid, 733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int start, int end); 734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 735f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, int start, int end); 736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 737f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid, 738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int before, int after); 739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 740f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeUnselect(long nativeImeAdapterAndroid); 741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeSelectAll(long nativeImeAdapterAndroid); 742f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeCut(long nativeImeAdapterAndroid); 743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeCopy(long nativeImeAdapterAndroid); 744f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativePaste(long nativeImeAdapterAndroid); 745f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeResetImeAdapter(long nativeImeAdapterAndroid); 746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 747