ImeAdapter.java revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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 com.google.common.annotations.VisibleForTesting;
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)import java.lang.CharSequence;
236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import org.chromium.base.CalledByNative;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import org.chromium.base.JNINamespace;
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 {
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        private final long mNativeImeAdapter;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        DelayedDismissInput(long nativeImeAdapter) {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            mNativeImeAdapter = nativeImeAdapter;
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        @Override
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        public void run() {
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            attach(mNativeImeAdapter, sTextInputTypeNone, sTextInputFlagNone);
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            dismissInput(true);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static final int COMPOSITION_KEY_CODE = 229;
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Delay introduced to avoid hiding the keyboard if new show requests are received.
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The time required by the unfocus-focus events triggered by tab has been measured in soju:
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Mean: 18.633 ms, Standard deviation: 7.9837 ms.
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The value here should be higher enough to cover these cases, but not too high to avoid
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // letting the user perceiving important delays.
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static final int INPUT_DISMISS_DELAY = 150;
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // All the constants that are retrieved from the C++ code.
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // They get set through initializeWebInputEvents and initializeTextInputTypes calls.
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sEventTypeRawKeyDown;
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sEventTypeKeyUp;
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sEventTypeChar;
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeNone;
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeText;
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeTextArea;
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypePassword;
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeSearch;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeUrl;
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeEmail;
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeTel;
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeNumber;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeContentEditable;
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    static int sTextInputFlagNone = 0;
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    static int sTextInputFlagAutocompleteOn;
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    static int sTextInputFlagAutocompleteOff;
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    static int sTextInputFlagAutocorrectOn;
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    static int sTextInputFlagAutocorrectOff;
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    static int sTextInputFlagSpellcheckOn;
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    static int sTextInputFlagSpellcheckOff;
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sModifierShift;
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sModifierAlt;
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sModifierCtrl;
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sModifierCapsLockOn;
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sModifierNumLockOn;
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    static char[] sSingleCharArray = new char[1];
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    static KeyCharacterMap sKeyCharacterMap;
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private long mNativeImeAdapterAndroid;
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private InputMethodManagerWrapper mInputMethodManagerWrapper;
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private AdapterInputConnection mInputConnection;
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private final ImeAdapterDelegate mViewEmbedder;
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private final Handler mHandler;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private DelayedDismissInput mDismissInput = null;
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private int mTextInputType;
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    private int mTextInputFlags;
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    private String mLastComposeText;
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    @VisibleForTesting
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int mLastSyntheticKeyCode;
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @VisibleForTesting
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    boolean mIsShowWithoutHideOutstanding = false;
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @param wrapper InputMethodManagerWrapper that should receive all the call directed to
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     *                InputMethodManager.
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param embedder The view that is used for callbacks from ImeAdapter.
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embedder) {
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mInputMethodManagerWrapper = wrapper;
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mViewEmbedder = embedder;
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mHandler = new Handler();
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    /**
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     * Default factory for AdapterInputConnection classes.
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     */
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public static class AdapterInputConnectionFactory {
16023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        public AdapterInputConnection get(View view, ImeAdapter imeAdapter,
16123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                Editable editable, EditorInfo outAttrs) {
16223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            return new AdapterInputConnection(view, imeAdapter, editable, outAttrs);
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /**
1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * Overrides the InputMethodManagerWrapper that ImeAdapter uses to make calls to
1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * InputMethodManager.
1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param immw InputMethodManagerWrapper that should be used to call InputMethodManager.
1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     */
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @VisibleForTesting
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    public void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) {
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mInputMethodManagerWrapper = immw;
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Should be only used by AdapterInputConnection.
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return InputMethodManagerWrapper that should receive all the calls directed to
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     *         InputMethodManager.
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    InputMethodManagerWrapper getInputMethodManagerWrapper() {
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return mInputMethodManagerWrapper;
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Set the current active InputConnection when a new InputConnection is constructed.
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param inputConnection The input connection that is currently used with IME.
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    void setInputConnection(AdapterInputConnection inputConnection) {
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mInputConnection = inputConnection;
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        mLastComposeText = null;
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * Should be used only by AdapterInputConnection.
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return The input type of currently focused element.
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int getTextInputType() {
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return mTextInputType;
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /**
2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * Should be used only by AdapterInputConnection.
2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * @return The input flags of the currently focused element.
2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     */
2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int getTextInputFlags() {
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return mTextInputFlags;
2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    /**
2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @return Constant representing that a focused node is not an input field.
2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     */
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public static int getTextInputTypeNone() {
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return sTextInputTypeNone;
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static int getModifiers(int metaState) {
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int modifiers = 0;
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if ((metaState & KeyEvent.META_SHIFT_ON) != 0) {
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            modifiers |= sModifierShift;
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if ((metaState & KeyEvent.META_ALT_ON) != 0) {
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            modifiers |= sModifierAlt;
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if ((metaState & KeyEvent.META_CTRL_ON) != 0) {
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            modifiers |= sModifierCtrl;
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if ((metaState & KeyEvent.META_CAPS_LOCK_ON) != 0) {
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            modifiers |= sModifierCapsLockOn;
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if ((metaState & KeyEvent.META_NUM_LOCK_ON) != 0) {
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            modifiers |= sModifierNumLockOn;
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return modifiers;
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /**
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * Shows or hides the keyboard based on passed parameters.
2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param nativeImeAdapter Pointer to the ImeAdapterAndroid object that is sending the update.
2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param textInputType Text input type for the currently focused field in renderer.
2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param showIfNeeded Whether the keyboard should be shown if it is currently hidden.
2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     */
2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    public void updateKeyboardVisibility(long nativeImeAdapter, int textInputType,
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            int textInputFlags, boolean showIfNeeded) {
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mHandler.removeCallbacks(mDismissInput);
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // If current input type is none and showIfNeeded is false, IME should not be shown
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // and input type should remain as none.
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mTextInputType == sTextInputTypeNone && !showIfNeeded) {
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return;
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (mNativeImeAdapterAndroid != nativeImeAdapter || mTextInputType != textInputType) {
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // Set a delayed task to perform unfocus. This avoids hiding the keyboard when tabbing
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // through text inputs or when JS rapidly changes focus to another text element.
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (textInputType == sTextInputTypeNone) {
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                mDismissInput = new DelayedDismissInput(nativeImeAdapter);
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                mHandler.postDelayed(mDismissInput, INPUT_DISMISS_DELAY);
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                return;
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            attach(nativeImeAdapter, textInputType, textInputFlags);
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView());
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (showIfNeeded) {
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                showKeyboard();
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        } else if (hasInputType() && showIfNeeded) {
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            showKeyboard();
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    public void attach(long nativeImeAdapter, int textInputType, int textInputFlags) {
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid != 0) {
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            nativeResetImeAdapter(mNativeImeAdapterAndroid);
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mNativeImeAdapterAndroid = nativeImeAdapter;
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mTextInputType = textInputType;
2796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        mTextInputFlags = textInputFlags;
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        mLastComposeText = null;
281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        if (nativeImeAdapter != 0) {
282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            nativeAttachImeAdapter(mNativeImeAdapterAndroid);
283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        }
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (mTextInputType == sTextInputTypeNone) {
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            dismissInput(false);
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Attaches the imeAdapter to its native counterpart. This is needed to start forwarding
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * keyboard events to WebKit.
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param nativeImeAdapter The pointer to the native ImeAdapter object.
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    public void attach(long nativeImeAdapter) {
2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        attach(nativeImeAdapter, sTextInputTypeNone, sTextInputFlagNone);
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private void showKeyboard() {
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mIsShowWithoutHideOutstanding = true;
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mInputMethodManagerWrapper.showSoftInput(mViewEmbedder.getAttachedView(), 0,
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                mViewEmbedder.getNewShowKeyboardReceiver());
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private void dismissInput(boolean unzoomIfNeeded) {
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mIsShowWithoutHideOutstanding  = false;
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        View view = mViewEmbedder.getAttachedView();
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mInputMethodManagerWrapper.isActive(view)) {
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            mInputMethodManagerWrapper.hideSoftInputFromWindow(view.getWindowToken(), 0,
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    unzoomIfNeeded ? mViewEmbedder.getNewShowKeyboardReceiver() : null);
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
3110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        mViewEmbedder.onDismissInput();
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private boolean hasInputType() {
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return mTextInputType != sTextInputTypeNone;
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    private static boolean isTextInputType(int type) {
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return type != sTextInputTypeNone && !InputDialogContainer.isDialogInputType(type);
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean hasTextInputType() {
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return isTextInputType(mTextInputType);
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    /**
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)     * @return true if the selected text is of password.
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)     */
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    public boolean isSelectionPassword() {
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return mTextInputType == sTextInputTypePassword;
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean dispatchKeyEvent(KeyEvent event) {
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return translateAndSendNativeEvents(event);
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private int shouldSendKeyEventWithKeyCode(String text) {
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (text.length() != 1) return COMPOSITION_KEY_CODE;
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (text.equals("\n")) return KeyEvent.KEYCODE_ENTER;
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        else if (text.equals("\t")) return KeyEvent.KEYCODE_TAB;
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        else return COMPOSITION_KEY_CODE;
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    /**
3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * @return Android KeyEvent for a single unicode character.  Only one KeyEvent is returned
3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * even if the system determined that various modifier keys (like Shift) would also have
3486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * been pressed.
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     */
3506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    private static KeyEvent androidKeyEventForCharacter(char chr) {
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (sKeyCharacterMap == null) {
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            sKeyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        }
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        sSingleCharArray[0] = chr;
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // TODO: Evaluate cost of this system call.
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        KeyEvent[] events = sKeyCharacterMap.getEvents(sSingleCharArray);
3576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (events == null) {  // No known key sequence will create that character.
3586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            return null;
3596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        }
3606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        for (int i = 0; i < events.length; ++i) {
3626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (events[i].getAction() == KeyEvent.ACTION_DOWN &&
3636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    !KeyEvent.isModifierKey(events[i].getKeyCode())) {
3646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                return events[i];
3656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            }
3666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        }
3676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return null;  // No printing characters were found.
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    @VisibleForTesting
3726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    public static KeyEvent getTypedKeyEventGuess(String oldtext, String newtext) {
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // Starting typing a new composition should add only a single character.  Any composition
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // beginning with text longer than that must come from something other than typing so
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // return 0.
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (oldtext == null) {
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if (newtext.length() == 1) {
3786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                return androidKeyEventForCharacter(newtext.charAt(0));
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            } else {
3806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                return null;
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            }
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        }
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // The content has grown in length: assume the last character is the key that caused it.
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (newtext.length() > oldtext.length() && newtext.startsWith(oldtext))
3866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            return androidKeyEventForCharacter(newtext.charAt(newtext.length() - 1));
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // The content has shrunk in length: assume that backspace was pressed.
3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (oldtext.length() > newtext.length() && oldtext.startsWith(newtext))
3906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            return new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL);
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // The content is unchanged or has undergone a complex change (i.e. not a simple tail
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // modification) so return an unknown key-code.
3946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return null;
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    void sendKeyEventWithKeyCode(int keyCode, int flags) {
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        long eventTime = SystemClock.uptimeMillis();
3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        mLastSyntheticKeyCode = keyCode;
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        translateAndSendNativeEvents(new KeyEvent(eventTime, eventTime,
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                KeyEvent.ACTION_DOWN, keyCode, 0, 0,
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                flags));
404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        translateAndSendNativeEvents(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                KeyEvent.ACTION_UP, keyCode, 0, 0,
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                flags));
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Calls from Java to C++
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // TODO: Add performance tracing to more complicated functions.
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    boolean checkCompositionQueueAndCallNative(CharSequence text, int newCursorPosition,
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            boolean isCommit) {
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        mViewEmbedder.onImeEvent();
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        String textStr = text.toString();
4196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        int keyCode = shouldSendKeyEventWithKeyCode(textStr);
420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        long timeStampMs = SystemClock.uptimeMillis();
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (keyCode != COMPOSITION_KEY_CODE) {
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            sendKeyEventWithKeyCode(keyCode,
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE);
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        } else {
4266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            KeyEvent keyEvent = getTypedKeyEventGuess(mLastComposeText, textStr);
4276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            int modifiers = 0;
4286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (keyEvent != null) {
4296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                keyCode = keyEvent.getKeyCode();
4306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                modifiers = getModifiers(keyEvent.getMetaState());
4316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            } else if (!textStr.equals(mLastComposeText)) {
4326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                keyCode = KeyEvent.KEYCODE_UNKNOWN;
4336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            } else {
4346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                keyCode = -1;
4356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            }
4366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // If this is a commit with no previous composition, then treat it as a native
4386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // KeyDown/KeyUp pair with no composition rather than a synthetic pair with
4396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // composition below.
4406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (keyCode > 0 && isCommit && mLastComposeText == null) {
4416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                mLastSyntheticKeyCode = keyCode;
4426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                return translateAndSendNativeEvents(keyEvent) &&
4436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       translateAndSendNativeEvents(KeyEvent.changeAction(
4446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                               keyEvent, KeyEvent.ACTION_UP));
4456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            }
4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // When typing, there is no issue sending KeyDown and KeyUp events around the
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // composition event because those key events do nothing (other than call JS
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // handlers).  Typing does not cause changes outside of a KeyPress event which
4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // we don't call here.  However, if the key-code is a control key such as
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // KEYCODE_DEL then there never is an associated KeyPress event and the KeyDown
4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // event itself causes the action.  The net result below is that the Renderer calls
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // cancelComposition() and then Android starts anew with setComposingRegion().
4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // This stopping and restarting of composition could be a source of problems
4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // with 3rd party keyboards.
4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            //
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // An alternative is to *not* call nativeSetComposingText() in the non-commit case
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // below.  This avoids the restart of composition described above but fails to send
4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // an update to the composition while in composition which, strictly speaking,
4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // does not match the spec.
4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            //
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // For now, the solution is to endure the restarting of composition and only dive
4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // into the alternate solution should there be problems in the field.  --bcwhite
4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (keyCode >= 0) {
4666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawKeyDown,
4676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                        timeStampMs, keyCode, modifiers, 0);
4686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            }
4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (isCommit) {
4716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                nativeCommitText(mNativeImeAdapterAndroid, textStr);
4726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                textStr = null;
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            } else {
4746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                nativeSetComposingText(mNativeImeAdapterAndroid, text, textStr, newCursorPosition);
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (keyCode >= 0) {
4786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyUp,
4796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                        timeStampMs, keyCode, modifiers, 0);
4806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            }
4816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            mLastSyntheticKeyCode = keyCode;
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        mLastComposeText = textStr;
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    void finishComposingText() {
4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        mLastComposeText = null;
491c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        if (mNativeImeAdapterAndroid == 0) return;
4927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        nativeFinishComposingText(mNativeImeAdapterAndroid);
4937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
4947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    boolean translateAndSendNativeEvents(KeyEvent event) {
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int action = event.getAction();
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (action != KeyEvent.ACTION_DOWN &&
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            action != KeyEvent.ACTION_UP) {
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // action == KeyEvent.ACTION_MULTIPLE
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // TODO(bulach): confirm the actual behavior. Apparently:
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // composition key down (229) followed by a commit text with the
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // string from event.getUnicodeChars().
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // Otherwise, we'd need to send an event with a
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // WebInputEvent::IsAutoRepeat modifier. We also need to verify when
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // we receive ACTION_MULTIPLE: we may receive it after an ACTION_DOWN,
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // and if that's the case, we'll need to review when to send the Char
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // event.
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return false;
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        mViewEmbedder.onImeEvent();
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return nativeSendKeyEvent(mNativeImeAdapterAndroid, event, event.getAction(),
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                getModifiers(event.getMetaState()), event.getEventTime(), event.getKeyCode(),
51608c107de54178bb0990a09adec724924e8bc9486Primiano Tucci                             /*isSystemKey=*/false, event.getUnicodeChar());
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    boolean sendSyntheticKeyEvent(int eventType, long timestampMs, int keyCode, int modifiers,
5206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            int unicodeChar) {
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeSendSyntheticKeyEvent(
5246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                mNativeImeAdapterAndroid, eventType, timestampMs, keyCode, modifiers, unicodeChar);
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /**
5295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * Send a request to the native counterpart to delete a given range of characters.
5305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param beforeLength Number of characters to extend the selection by before the existing
5315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     *                     selection.
5325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param afterLength Number of characters to extend the selection by after the existing
5335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     *                    selection.
5345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @return Whether the native counterpart of ImeAdapter received the call.
5355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     */
5360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    boolean deleteSurroundingText(int beforeLength, int afterLength) {
5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        mViewEmbedder.onImeEvent();
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
5390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        nativeDeleteSurroundingText(mNativeImeAdapterAndroid, beforeLength, afterLength);
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /**
5445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * Send a request to the native counterpart to set the selection to given range.
5455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param start Selection start index.
5465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param end Selection end index.
5475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @return Whether the native counterpart of ImeAdapter received the call.
5485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     */
5490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    boolean setEditableSelectionOffsets(int start, int end) {
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end);
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
5565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     * Send a request to the native counterpart to set composing region to given indices.
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param start The start of the composition.
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param end The end of the composition.
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    boolean setComposingRegion(CharSequence text, int start, int end) {
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end);
5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        mLastComposeText = text != null ? text.toString() : null;
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart to unselect text.
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean unselect() {
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeUnselect(mNativeImeAdapterAndroid);
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart of ImeAdapter to select all the text.
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean selectAll() {
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeSelectAll(mNativeImeAdapterAndroid);
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart of ImeAdapter to cut the selected text.
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean cut() {
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeCut(mNativeImeAdapterAndroid);
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart of ImeAdapter to copy the selected text.
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean copy() {
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeCopy(mNativeImeAdapterAndroid);
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart of ImeAdapter to paste the text from the clipboard.
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean paste() {
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativePaste(mNativeImeAdapterAndroid);
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Calls from C++ to Java
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @CalledByNative
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static void initializeWebInputEvents(int eventTypeRawKeyDown, int eventTypeKeyUp,
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int eventTypeChar, int modifierShift, int modifierAlt, int modifierCtrl,
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int modifierCapsLockOn, int modifierNumLockOn) {
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sEventTypeRawKeyDown = eventTypeRawKeyDown;
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sEventTypeKeyUp = eventTypeKeyUp;
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sEventTypeChar = eventTypeChar;
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sModifierShift = modifierShift;
628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sModifierAlt = modifierAlt;
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sModifierCtrl = modifierCtrl;
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sModifierCapsLockOn = modifierCapsLockOn;
631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sModifierNumLockOn = modifierNumLockOn;
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @CalledByNative
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static void initializeTextInputTypes(int textInputTypeNone, int textInputTypeText,
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int textInputTypeTextArea, int textInputTypePassword, int textInputTypeSearch,
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int textInputTypeUrl, int textInputTypeEmail, int textInputTypeTel,
6384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            int textInputTypeNumber, int textInputTypeContentEditable) {
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeNone = textInputTypeNone;
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeText = textInputTypeText;
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeTextArea = textInputTypeTextArea;
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypePassword = textInputTypePassword;
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeSearch = textInputTypeSearch;
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeUrl = textInputTypeUrl;
645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeEmail = textInputTypeEmail;
646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeTel = textInputTypeTel;
647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeNumber = textInputTypeNumber;
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeContentEditable = textInputTypeContentEditable;
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @CalledByNative
6526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    private static void initializeTextInputFlags(
6536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            int textInputFlagAutocompleteOn, int textInputFlagAutocompleteOff,
6546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            int textInputFlagAutocorrectOn, int textInputFlagAutocorrectOff,
6556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            int textInputFlagSpellcheckOn, int textInputFlagSpellcheckOff) {
6566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        sTextInputFlagAutocompleteOn = textInputFlagAutocompleteOn;
6576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        sTextInputFlagAutocompleteOff = textInputFlagAutocompleteOff;
6586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        sTextInputFlagAutocorrectOn = textInputFlagAutocorrectOn;
6596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        sTextInputFlagAutocorrectOff = textInputFlagAutocorrectOff;
6606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        sTextInputFlagSpellcheckOn = textInputFlagSpellcheckOn;
6616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        sTextInputFlagSpellcheckOff = textInputFlagSpellcheckOff;
6626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
6636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
6646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    @CalledByNative
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    private void focusedNodeChanged(boolean isEditable) {
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (mInputConnection != null && isEditable) mInputConnection.restartInput();
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    @CalledByNative
6706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    private void populateUnderlinesFromSpans(CharSequence text, long underlines) {
6716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        if (!(text instanceof SpannableString)) return;
6726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        SpannableString spannableString = ((SpannableString) text);
6746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        CharacterStyle spans[] =
6756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                spannableString.getSpans(0, text.length(), CharacterStyle.class);
6766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        for (CharacterStyle span : spans) {
6776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            if (span instanceof BackgroundColorSpan) {
6786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                nativeAppendBackgroundColorSpan(underlines, spannableString.getSpanStart(span),
6796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                        spannableString.getSpanEnd(span),
6806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                        ((BackgroundColorSpan) span).getBackgroundColor());
6816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            } else if (span instanceof UnderlineSpan) {
6826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                nativeAppendUnderlineSpan(underlines, spannableString.getSpanStart(span),
6836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                        spannableString.getSpanEnd(span));
6846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            }
6856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        }
6866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
6876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    @CalledByNative
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private void cancelComposition() {
6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (mInputConnection != null) mInputConnection.restartInput();
6915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        mLastComposeText = null;
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @CalledByNative
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    void detach() {
6960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        if (mDismissInput != null) mHandler.removeCallbacks(mDismissInput);
697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mNativeImeAdapterAndroid = 0;
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mTextInputType = 0;
699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
701f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndroid,
7026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            int eventType, long timestampMs, int keyCode, int modifiers, int unicodeChar);
703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyEvent event,
705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int action, int modifiers, long timestampMs, int keyCode, boolean isSystemKey,
706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int unicodeChar);
707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end);
7096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
7106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    private static native void nativeAppendBackgroundColorSpan(long underlinePtr, int start,
7116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            int end, int backgroundColor);
7126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
7136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    private native void nativeSetComposingText(long nativeImeAdapterAndroid, CharSequence text,
7146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            String textStr, int newCursorPosition);
715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    private native void nativeCommitText(long nativeImeAdapterAndroid, String textStr);
717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
718f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeFinishComposingText(long nativeImeAdapterAndroid);
7197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
720f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid);
721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
722f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterAndroid,
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int start, int end);
724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
725f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, int start, int end);
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
727f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid,
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int before, int after);
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
730f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeUnselect(long nativeImeAdapterAndroid);
731f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeSelectAll(long nativeImeAdapterAndroid);
732f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeCut(long nativeImeAdapterAndroid);
733f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeCopy(long nativeImeAdapterAndroid);
734f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativePaste(long nativeImeAdapterAndroid);
735f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeResetImeAdapter(long nativeImeAdapterAndroid);
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
737