blob: bbea8ffa4334dad3cbe085cc0c03de0fb5fa360c [file] [log] [blame]
Kenny Root15a4d2f2010-03-11 18:20:12 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017package android.inputmethodservice;
18
19import com.android.internal.os.HandlerCaller;
Svetoslav Ganov758143e2012-08-06 16:40:27 -070020import com.android.internal.os.SomeArgs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.internal.view.IInputMethodSession;
22
23import android.content.Context;
24import android.graphics.Rect;
25import android.os.Bundle;
Jeff Brownc28867a2013-03-26 15:42:39 -070026import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.os.Message;
28import android.os.RemoteException;
29import android.util.Log;
Jeff Brownc28867a2013-03-26 15:42:39 -070030import android.util.SparseArray;
31import android.view.InputChannel;
32import android.view.InputDevice;
33import android.view.InputEvent;
34import android.view.InputEventReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.view.KeyEvent;
36import android.view.MotionEvent;
37import android.view.inputmethod.CompletionInfo;
38import android.view.inputmethod.ExtractedText;
39import android.view.inputmethod.InputMethodSession;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040
41class IInputMethodSessionWrapper extends IInputMethodSession.Stub
42 implements HandlerCaller.Callback {
43 private static final String TAG = "InputMethodWrapper";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044
45 private static final int DO_FINISH_INPUT = 60;
46 private static final int DO_DISPLAY_COMPLETIONS = 65;
47 private static final int DO_UPDATE_EXTRACTED_TEXT = 67;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 private static final int DO_UPDATE_SELECTION = 90;
49 private static final int DO_UPDATE_CURSOR = 95;
50 private static final int DO_APP_PRIVATE_COMMAND = 100;
The Android Open Source Project4df24232009-03-05 14:34:35 -080051 private static final int DO_TOGGLE_SOFT_INPUT = 105;
Devin Taylor0c33ed22010-02-23 13:26:46 -060052 private static final int DO_FINISH_SESSION = 110;
satok863fcd62011-06-21 17:38:02 +090053 private static final int DO_VIEW_CLICKED = 115;
Devin Taylor0c33ed22010-02-23 13:26:46 -060054
55 HandlerCaller mCaller;
56 InputMethodSession mInputMethodSession;
Jeff Brownc28867a2013-03-26 15:42:39 -070057 InputChannel mChannel;
58 ImeInputEventReceiver mReceiver;
59
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060 public IInputMethodSessionWrapper(Context context,
Jeff Brownc28867a2013-03-26 15:42:39 -070061 InputMethodSession inputMethodSession, InputChannel channel) {
Mita Yuned218c72012-12-06 17:18:25 -080062 mCaller = new HandlerCaller(context, null,
63 this, true /*asyncHandler*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 mInputMethodSession = inputMethodSession;
Jeff Brownc28867a2013-03-26 15:42:39 -070065 mChannel = channel;
66 if (channel != null) {
67 mReceiver = new ImeInputEventReceiver(channel, context.getMainLooper());
68 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 }
70
71 public InputMethodSession getInternalInputMethodSession() {
72 return mInputMethodSession;
73 }
74
Jeff Brownc28867a2013-03-26 15:42:39 -070075 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 public void executeMessage(Message msg) {
Jeff Brownc28867a2013-03-26 15:42:39 -070077 if (mInputMethodSession == null) {
Henrik Baard857cdff2010-07-20 11:42:19 +020078 // The session has been finished. Args needs to be recycled
79 // for cases below.
80 switch (msg.what) {
81 case DO_UPDATE_SELECTION:
82 case DO_APP_PRIVATE_COMMAND: {
83 SomeArgs args = (SomeArgs)msg.obj;
84 args.recycle();
85 }
86 }
Jeff Brownc28867a2013-03-26 15:42:39 -070087 return;
88 }
Ken Wakasaa308c032011-01-25 14:02:07 +090089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 switch (msg.what) {
91 case DO_FINISH_INPUT:
92 mInputMethodSession.finishInput();
93 return;
94 case DO_DISPLAY_COMPLETIONS:
95 mInputMethodSession.displayCompletions((CompletionInfo[])msg.obj);
96 return;
97 case DO_UPDATE_EXTRACTED_TEXT:
98 mInputMethodSession.updateExtractedText(msg.arg1,
99 (ExtractedText)msg.obj);
100 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 case DO_UPDATE_SELECTION: {
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700102 SomeArgs args = (SomeArgs)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 mInputMethodSession.updateSelection(args.argi1, args.argi2,
104 args.argi3, args.argi4, args.argi5, args.argi6);
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700105 args.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 return;
107 }
108 case DO_UPDATE_CURSOR: {
109 mInputMethodSession.updateCursor((Rect)msg.obj);
110 return;
111 }
112 case DO_APP_PRIVATE_COMMAND: {
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700113 SomeArgs args = (SomeArgs)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 mInputMethodSession.appPrivateCommand((String)args.arg1,
115 (Bundle)args.arg2);
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700116 args.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 return;
118 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800119 case DO_TOGGLE_SOFT_INPUT: {
120 mInputMethodSession.toggleSoftInput(msg.arg1, msg.arg2);
121 return;
122 }
Devin Taylor0c33ed22010-02-23 13:26:46 -0600123 case DO_FINISH_SESSION: {
Jeff Brownc28867a2013-03-26 15:42:39 -0700124 doFinishSession();
Devin Taylor0c33ed22010-02-23 13:26:46 -0600125 return;
126 }
satok863fcd62011-06-21 17:38:02 +0900127 case DO_VIEW_CLICKED: {
128 mInputMethodSession.viewClicked(msg.arg1 == 1);
129 return;
130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 }
132 Log.w(TAG, "Unhandled message code: " + msg.what);
133 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700134
135 private void doFinishSession() {
136 mInputMethodSession = null;
137 if (mReceiver != null) {
138 mReceiver.dispose();
139 mReceiver = null;
140 }
141 if (mChannel != null) {
142 mChannel.dispose();
143 mChannel = null;
144 }
145 }
146
147 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 public void finishInput() {
149 mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_INPUT));
150 }
151
Jeff Brownc28867a2013-03-26 15:42:39 -0700152 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 public void displayCompletions(CompletionInfo[] completions) {
154 mCaller.executeOrSendMessage(mCaller.obtainMessageO(
155 DO_DISPLAY_COMPLETIONS, completions));
156 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700157
158 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 public void updateExtractedText(int token, ExtractedText text) {
160 mCaller.executeOrSendMessage(mCaller.obtainMessageIO(
161 DO_UPDATE_EXTRACTED_TEXT, token, text));
162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163
Jeff Brownc28867a2013-03-26 15:42:39 -0700164 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 public void updateSelection(int oldSelStart, int oldSelEnd,
166 int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
167 mCaller.executeOrSendMessage(mCaller.obtainMessageIIIIII(DO_UPDATE_SELECTION,
168 oldSelStart, oldSelEnd, newSelStart, newSelEnd,
169 candidatesStart, candidatesEnd));
170 }
satok863fcd62011-06-21 17:38:02 +0900171
Jeff Brownc28867a2013-03-26 15:42:39 -0700172 @Override
satok863fcd62011-06-21 17:38:02 +0900173 public void viewClicked(boolean focusChanged) {
Jeff Brownc28867a2013-03-26 15:42:39 -0700174 mCaller.executeOrSendMessage(
175 mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0));
satok863fcd62011-06-21 17:38:02 +0900176 }
177
Jeff Brownc28867a2013-03-26 15:42:39 -0700178 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 public void updateCursor(Rect newCursor) {
Jeff Brownc28867a2013-03-26 15:42:39 -0700180 mCaller.executeOrSendMessage(
181 mCaller.obtainMessageO(DO_UPDATE_CURSOR, newCursor));
The Android Open Source Project4df24232009-03-05 14:34:35 -0800182 }
Devin Taylor0c33ed22010-02-23 13:26:46 -0600183
Jeff Brownc28867a2013-03-26 15:42:39 -0700184 @Override
185 public void appPrivateCommand(String action, Bundle data) {
186 mCaller.executeOrSendMessage(
187 mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, data));
188 }
189
190 @Override
191 public void toggleSoftInput(int showFlags, int hideFlags) {
192 mCaller.executeOrSendMessage(
193 mCaller.obtainMessageII(DO_TOGGLE_SOFT_INPUT, showFlags, hideFlags));
194 }
195
196 @Override
Devin Taylor0c33ed22010-02-23 13:26:46 -0600197 public void finishSession() {
198 mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_SESSION));
199 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700200
201 private final class ImeInputEventReceiver extends InputEventReceiver
202 implements InputMethodSession.EventCallback {
203 private final SparseArray<InputEvent> mPendingEvents = new SparseArray<InputEvent>();
204
205 public ImeInputEventReceiver(InputChannel inputChannel, Looper looper) {
206 super(inputChannel, looper);
207 }
208
209 @Override
210 public void onInputEvent(InputEvent event) {
211 if (mInputMethodSession == null) {
212 // The session has been finished.
213 finishInputEvent(event, false);
214 return;
215 }
216
217 final int seq = event.getSequenceNumber();
218 mPendingEvents.put(seq, event);
219 if (event instanceof KeyEvent) {
220 KeyEvent keyEvent = (KeyEvent)event;
221 mInputMethodSession.dispatchKeyEvent(seq, keyEvent, this);
222 } else {
223 MotionEvent motionEvent = (MotionEvent)event;
224 if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) {
225 mInputMethodSession.dispatchTrackballEvent(seq, motionEvent, this);
226 } else {
227 mInputMethodSession.dispatchGenericMotionEvent(seq, motionEvent, this);
228 }
229 }
230 }
231
232 @Override
233 public void finishedEvent(int seq, boolean handled) {
234 int index = mPendingEvents.indexOfKey(seq);
235 if (index >= 0) {
236 InputEvent event = mPendingEvents.valueAt(index);
237 mPendingEvents.removeAt(index);
238 finishInputEvent(event, handled);
239 }
240 }
241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242}