ImeAdapter.java revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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;
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.view.KeyCharacterMap;
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.view.KeyEvent;
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.view.View;
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.view.inputmethod.EditorInfo;
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import com.google.common.annotations.VisibleForTesting;
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import org.chromium.base.CalledByNative;
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import org.chromium.base.JNINamespace;
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Adapts and plumbs android IME service onto the chrome text input API.
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * ImeAdapter provides an interface in both ways native <-> java:
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 1. InputConnectionAdapter notifies native code of text composition state and
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *    dispatch key events from java -> WebKit.
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 2. Native ImeAdapter notifies java side to clear composition text.
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * The basic flow is:
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 1. When InputConnectionAdapter gets called with composition or result text:
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *    If we receive a composition text or a result text, then we just need to
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *    dispatch a synthetic key event with special keycode 229, and then dispatch
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *    the composition or result text.
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 2. Intercept dispatchKeyEvent() method for key events not handled by IME, we
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   need to dispatch them to webkit and check webkit's reply. Then inject a
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   new key event for further processing if webkit didn't handle it.
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Note that the native peer object does not take any strong reference onto the
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * instance of this java object, hence it is up to the client of this class (e.g.
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the ViewEmbedder implementor) to hold a strong reference to it for the required
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * lifetime of the object.
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)@JNINamespace("content")
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public class ImeAdapter {
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    /**
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     * Interface for the delegate that needs to be notified of IME changes.
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     */
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public interface ImeAdapterDelegate {
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        /**
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         * @param isFinish whether the event is occurring because input is finished.
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         */
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        void onImeEvent(boolean isFinish);
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        /**
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         * Called when a request to hide the keyboard is sent to InputMethodManager.
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         */
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        void onDismissInput();
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        /**
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         * @return View that the keyboard should be attached to.
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         */
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        View getAttachedView();
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        /**
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         * @return Object that should be called for all keyboard show and hide requests.
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         */
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ResultReceiver getNewShowKeyboardReceiver();
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private class DelayedDismissInput implements Runnable {
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        private final long mNativeImeAdapter;
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        DelayedDismissInput(long nativeImeAdapter) {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            mNativeImeAdapter = nativeImeAdapter;
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        @Override
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        public void run() {
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            attach(mNativeImeAdapter, sTextInputTypeNone);
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            dismissInput(true);
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static final int COMPOSITION_KEY_CODE = 229;
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Delay introduced to avoid hiding the keyboard if new show requests are received.
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The time required by the unfocus-focus events triggered by tab has been measured in soju:
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Mean: 18.633 ms, Standard deviation: 7.9837 ms.
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The value here should be higher enough to cover these cases, but not too high to avoid
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // letting the user perceiving important delays.
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static final int INPUT_DISMISS_DELAY = 150;
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // All the constants that are retrieved from the C++ code.
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // They get set through initializeWebInputEvents and initializeTextInputTypes calls.
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sEventTypeRawKeyDown;
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sEventTypeKeyUp;
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sEventTypeChar;
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeNone;
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeText;
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeTextArea;
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypePassword;
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeSearch;
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeUrl;
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeEmail;
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeTel;
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeNumber;
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sTextInputTypeContentEditable;
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sModifierShift;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sModifierAlt;
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sModifierCtrl;
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sModifierCapsLockOn;
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    static int sModifierNumLockOn;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private long mNativeImeAdapterAndroid;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private InputMethodManagerWrapper mInputMethodManagerWrapper;
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private AdapterInputConnection mInputConnection;
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private final ImeAdapterDelegate mViewEmbedder;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private final Handler mHandler;
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private DelayedDismissInput mDismissInput = null;
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private int mTextInputType;
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @VisibleForTesting
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    boolean mIsShowWithoutHideOutstanding = false;
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @param wrapper InputMethodManagerWrapper that should receive all the call directed to
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     *                InputMethodManager.
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param embedder The view that is used for callbacks from ImeAdapter.
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embedder) {
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mInputMethodManagerWrapper = wrapper;
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mViewEmbedder = embedder;
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mHandler = new Handler();
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    /**
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     * Default factory for AdapterInputConnection classes.
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     */
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public static class AdapterInputConnectionFactory {
14023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        public AdapterInputConnection get(View view, ImeAdapter imeAdapter,
14123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                Editable editable, EditorInfo outAttrs) {
14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            return new AdapterInputConnection(view, imeAdapter, editable, outAttrs);
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /**
1475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * Overrides the InputMethodManagerWrapper that ImeAdapter uses to make calls to
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * InputMethodManager.
1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param immw InputMethodManagerWrapper that should be used to call InputMethodManager.
1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     */
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @VisibleForTesting
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    public void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) {
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mInputMethodManagerWrapper = immw;
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Should be only used by AdapterInputConnection.
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return InputMethodManagerWrapper that should receive all the calls directed to
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     *         InputMethodManager.
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    InputMethodManagerWrapper getInputMethodManagerWrapper() {
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return mInputMethodManagerWrapper;
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Set the current active InputConnection when a new InputConnection is constructed.
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param inputConnection The input connection that is currently used with IME.
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    void setInputConnection(AdapterInputConnection inputConnection) {
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mInputConnection = inputConnection;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Should be only used by AdapterInputConnection.
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return The input type of currently focused element.
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int getTextInputType() {
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return mTextInputType;
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /**
1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @return Constant representing that a focused node is not an input field.
1835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     */
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public static int getTextInputTypeNone() {
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return sTextInputTypeNone;
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static int getModifiers(int metaState) {
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int modifiers = 0;
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if ((metaState & KeyEvent.META_SHIFT_ON) != 0) {
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            modifiers |= sModifierShift;
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if ((metaState & KeyEvent.META_ALT_ON) != 0) {
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            modifiers |= sModifierAlt;
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if ((metaState & KeyEvent.META_CTRL_ON) != 0) {
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            modifiers |= sModifierCtrl;
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if ((metaState & KeyEvent.META_CAPS_LOCK_ON) != 0) {
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            modifiers |= sModifierCapsLockOn;
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if ((metaState & KeyEvent.META_NUM_LOCK_ON) != 0) {
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            modifiers |= sModifierNumLockOn;
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return modifiers;
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /**
2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * Shows or hides the keyboard based on passed parameters.
2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param nativeImeAdapter Pointer to the ImeAdapterAndroid object that is sending the update.
2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param textInputType Text input type for the currently focused field in renderer.
2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param showIfNeeded Whether the keyboard should be shown if it is currently hidden.
2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     */
2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    public void updateKeyboardVisibility(long nativeImeAdapter, int textInputType,
21523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            boolean showIfNeeded) {
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mHandler.removeCallbacks(mDismissInput);
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // If current input type is none and showIfNeeded is false, IME should not be shown
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // and input type should remain as none.
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mTextInputType == sTextInputTypeNone && !showIfNeeded) {
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return;
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (mNativeImeAdapterAndroid != nativeImeAdapter || mTextInputType != textInputType) {
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // Set a delayed task to perform unfocus. This avoids hiding the keyboard when tabbing
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // through text inputs or when JS rapidly changes focus to another text element.
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (textInputType == sTextInputTypeNone) {
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                mDismissInput = new DelayedDismissInput(nativeImeAdapter);
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                mHandler.postDelayed(mDismissInput, INPUT_DISMISS_DELAY);
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                return;
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            attach(nativeImeAdapter, textInputType);
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView());
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (showIfNeeded) {
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                showKeyboard();
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        } else if (hasInputType() && showIfNeeded) {
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            showKeyboard();
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    public void attach(long nativeImeAdapter, int textInputType) {
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid != 0) {
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            nativeResetImeAdapter(mNativeImeAdapterAndroid);
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mNativeImeAdapterAndroid = nativeImeAdapter;
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mTextInputType = textInputType;
250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        if (nativeImeAdapter != 0) {
251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            nativeAttachImeAdapter(mNativeImeAdapterAndroid);
252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        }
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Attaches the imeAdapter to its native counterpart. This is needed to start forwarding
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * keyboard events to WebKit.
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param nativeImeAdapter The pointer to the native ImeAdapter object.
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    public void attach(long nativeImeAdapter) {
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid != 0) {
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            nativeResetImeAdapter(mNativeImeAdapterAndroid);
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mNativeImeAdapterAndroid = nativeImeAdapter;
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (nativeImeAdapter != 0) {
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            nativeAttachImeAdapter(mNativeImeAdapterAndroid);
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private void showKeyboard() {
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mIsShowWithoutHideOutstanding = true;
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mInputMethodManagerWrapper.showSoftInput(mViewEmbedder.getAttachedView(), 0,
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                mViewEmbedder.getNewShowKeyboardReceiver());
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private void dismissInput(boolean unzoomIfNeeded) {
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mIsShowWithoutHideOutstanding  = false;
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        View view = mViewEmbedder.getAttachedView();
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mInputMethodManagerWrapper.isActive(view)) {
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            mInputMethodManagerWrapper.hideSoftInputFromWindow(view.getWindowToken(), 0,
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    unzoomIfNeeded ? mViewEmbedder.getNewShowKeyboardReceiver() : null);
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
2830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        mViewEmbedder.onDismissInput();
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private boolean hasInputType() {
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return mTextInputType != sTextInputTypeNone;
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    private static boolean isTextInputType(int type) {
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return type != sTextInputTypeNone && !InputDialogContainer.isDialogInputType(type);
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean hasTextInputType() {
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return isTextInputType(mTextInputType);
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean dispatchKeyEvent(KeyEvent event) {
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return translateAndSendNativeEvents(event);
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private int shouldSendKeyEventWithKeyCode(String text) {
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (text.length() != 1) return COMPOSITION_KEY_CODE;
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (text.equals("\n")) return KeyEvent.KEYCODE_ENTER;
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        else if (text.equals("\t")) return KeyEvent.KEYCODE_TAB;
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        else return COMPOSITION_KEY_CODE;
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    void sendKeyEventWithKeyCode(int keyCode, int flags) {
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        long eventTime = SystemClock.uptimeMillis();
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        translateAndSendNativeEvents(new KeyEvent(eventTime, eventTime,
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                KeyEvent.ACTION_DOWN, keyCode, 0, 0,
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                flags));
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        translateAndSendNativeEvents(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                KeyEvent.ACTION_UP, keyCode, 0, 0,
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                flags));
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Calls from Java to C++
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    boolean checkCompositionQueueAndCallNative(String text, int newCursorPosition,
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            boolean isCommit) {
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Committing an empty string finishes the current composition.
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        boolean isFinish = text.isEmpty();
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mViewEmbedder.onImeEvent(isFinish);
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int keyCode = shouldSendKeyEventWithKeyCode(text);
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        long timeStampMs = SystemClock.uptimeMillis();
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (keyCode != COMPOSITION_KEY_CODE) {
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            sendKeyEventWithKeyCode(keyCode,
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE);
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        } else {
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawKeyDown,
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    timeStampMs, keyCode, 0);
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (isCommit) {
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                nativeCommitText(mNativeImeAdapterAndroid, text);
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            } else {
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                nativeSetComposingText(mNativeImeAdapterAndroid, text, newCursorPosition);
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyUp,
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    timeStampMs, keyCode, 0);
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    void finishComposingText() {
353c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        if (mNativeImeAdapterAndroid == 0) return;
3547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        nativeFinishComposingText(mNativeImeAdapterAndroid);
3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
3567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    boolean translateAndSendNativeEvents(KeyEvent event) {
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int action = event.getAction();
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (action != KeyEvent.ACTION_DOWN &&
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            action != KeyEvent.ACTION_UP) {
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // action == KeyEvent.ACTION_MULTIPLE
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // TODO(bulach): confirm the actual behavior. Apparently:
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // composition key down (229) followed by a commit text with the
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // string from event.getUnicodeChars().
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // Otherwise, we'd need to send an event with a
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // WebInputEvent::IsAutoRepeat modifier. We also need to verify when
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // we receive ACTION_MULTIPLE: we may receive it after an ACTION_DOWN,
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // and if that's the case, we'll need to review when to send the Char
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // event.
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            return false;
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mViewEmbedder.onImeEvent(false);
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return nativeSendKeyEvent(mNativeImeAdapterAndroid, event, event.getAction(),
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                getModifiers(event.getMetaState()), event.getEventTime(), event.getKeyCode(),
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                event.isSystem(), event.getUnicodeChar());
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    boolean sendSyntheticKeyEvent(int eventType, long timestampMs, int keyCode, int unicodeChar) {
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeSendSyntheticKeyEvent(
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                mNativeImeAdapterAndroid, eventType, timestampMs, keyCode, unicodeChar);
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /**
3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * Send a request to the native counterpart to delete a given range of characters.
3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param beforeLength Number of characters to extend the selection by before the existing
3925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     *                     selection.
3935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param afterLength Number of characters to extend the selection by after the existing
3945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     *                    selection.
3955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @return Whether the native counterpart of ImeAdapter received the call.
3965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     */
3970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    boolean deleteSurroundingText(int beforeLength, int afterLength) {
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
3990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        nativeDeleteSurroundingText(mNativeImeAdapterAndroid, beforeLength, afterLength);
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /**
4045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * Send a request to the native counterpart to set the selection to given range.
4055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param start Selection start index.
4065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @param end Selection end index.
4075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     * @return Whether the native counterpart of ImeAdapter received the call.
4085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu     */
4090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    boolean setEditableSelectionOffsets(int start, int end) {
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end);
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart to set compositing region to given indices.
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param start The start of the composition.
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param end The end of the composition.
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    boolean setComposingRegion(int start, int end) {
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end);
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart to unselect text.
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean unselect() {
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeUnselect(mNativeImeAdapterAndroid);
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart of ImeAdapter to select all the text.
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean selectAll() {
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeSelectAll(mNativeImeAdapterAndroid);
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart of ImeAdapter to cut the selected text.
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean cut() {
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeCut(mNativeImeAdapterAndroid);
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart of ImeAdapter to copy the selected text.
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean copy() {
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativeCopy(mNativeImeAdapterAndroid);
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Send a request to the native counterpart of ImeAdapter to paste the text from the clipboard.
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return Whether the native counterpart of ImeAdapter received the call.
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public boolean paste() {
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (mNativeImeAdapterAndroid == 0) return false;
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        nativePaste(mNativeImeAdapterAndroid);
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Calls from C++ to Java
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @CalledByNative
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static void initializeWebInputEvents(int eventTypeRawKeyDown, int eventTypeKeyUp,
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int eventTypeChar, int modifierShift, int modifierAlt, int modifierCtrl,
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int modifierCapsLockOn, int modifierNumLockOn) {
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sEventTypeRawKeyDown = eventTypeRawKeyDown;
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sEventTypeKeyUp = eventTypeKeyUp;
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sEventTypeChar = eventTypeChar;
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sModifierShift = modifierShift;
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sModifierAlt = modifierAlt;
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sModifierCtrl = modifierCtrl;
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sModifierCapsLockOn = modifierCapsLockOn;
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sModifierNumLockOn = modifierNumLockOn;
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @CalledByNative
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static void initializeTextInputTypes(int textInputTypeNone, int textInputTypeText,
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int textInputTypeTextArea, int textInputTypePassword, int textInputTypeSearch,
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int textInputTypeUrl, int textInputTypeEmail, int textInputTypeTel,
4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            int textInputTypeNumber, int textInputTypeContentEditable) {
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeNone = textInputTypeNone;
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeText = textInputTypeText;
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeTextArea = textInputTypeTextArea;
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypePassword = textInputTypePassword;
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeSearch = textInputTypeSearch;
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeUrl = textInputTypeUrl;
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeEmail = textInputTypeEmail;
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeTel = textInputTypeTel;
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeNumber = textInputTypeNumber;
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sTextInputTypeContentEditable = textInputTypeContentEditable;
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @CalledByNative
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    private void focusedNodeChanged(boolean isEditable) {
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (mInputConnection != null && isEditable) mInputConnection.restartInput();
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    @CalledByNative
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private void cancelComposition() {
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (mInputConnection != null) mInputConnection.restartInput();
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @CalledByNative
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    void detach() {
5220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        if (mDismissInput != null) mHandler.removeCallbacks(mDismissInput);
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mNativeImeAdapterAndroid = 0;
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mTextInputType = 0;
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
527f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndroid,
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int eventType, long timestampMs, int keyCode, int unicodeChar);
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyEvent event,
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int action, int modifiers, long timestampMs, int keyCode, boolean isSystemKey,
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int unicodeChar);
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
534f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeSetComposingText(long nativeImeAdapterAndroid, String text,
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int newCursorPosition);
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
537f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeCommitText(long nativeImeAdapterAndroid, String text);
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
539f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeFinishComposingText(long nativeImeAdapterAndroid);
5407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
541f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid);
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
543f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterAndroid,
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int start, int end);
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
546f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, int start, int end);
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
548f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid,
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int before, int after);
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
551f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeUnselect(long nativeImeAdapterAndroid);
552f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeSelectAll(long nativeImeAdapterAndroid);
553f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeCut(long nativeImeAdapterAndroid);
554f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeCopy(long nativeImeAdapterAndroid);
555f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativePaste(long nativeImeAdapterAndroid);
556f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeResetImeAdapter(long nativeImeAdapterAndroid);
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
558