blob: 8437228257a09314b62f2905648325e9cb1d1122 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.util.Log;
Jeff Brownc28867a2013-03-26 15:42:39 -070029import android.util.SparseArray;
30import android.view.InputChannel;
31import android.view.InputDevice;
32import android.view.InputEvent;
33import android.view.InputEventReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.view.KeyEvent;
35import android.view.MotionEvent;
36import android.view.inputmethod.CompletionInfo;
37import android.view.inputmethod.ExtractedText;
38import android.view.inputmethod.InputMethodSession;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039
40class IInputMethodSessionWrapper extends IInputMethodSession.Stub
41 implements HandlerCaller.Callback {
42 private static final String TAG = "InputMethodWrapper";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043
44 private static final int DO_FINISH_INPUT = 60;
45 private static final int DO_DISPLAY_COMPLETIONS = 65;
46 private static final int DO_UPDATE_EXTRACTED_TEXT = 67;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047 private static final int DO_UPDATE_SELECTION = 90;
48 private static final int DO_UPDATE_CURSOR = 95;
49 private static final int DO_APP_PRIVATE_COMMAND = 100;
The Android Open Source Project4df24232009-03-05 14:34:35 -080050 private static final int DO_TOGGLE_SOFT_INPUT = 105;
Devin Taylor0c33ed22010-02-23 13:26:46 -060051 private static final int DO_FINISH_SESSION = 110;
satok863fcd62011-06-21 17:38:02 +090052 private static final int DO_VIEW_CLICKED = 115;
Devin Taylor0c33ed22010-02-23 13:26:46 -060053
54 HandlerCaller mCaller;
55 InputMethodSession mInputMethodSession;
Jeff Brownc28867a2013-03-26 15:42:39 -070056 InputChannel mChannel;
57 ImeInputEventReceiver mReceiver;
58
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059 public IInputMethodSessionWrapper(Context context,
Jeff Brownc28867a2013-03-26 15:42:39 -070060 InputMethodSession inputMethodSession, InputChannel channel) {
Mita Yuned218c72012-12-06 17:18:25 -080061 mCaller = new HandlerCaller(context, null,
62 this, true /*asyncHandler*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 mInputMethodSession = inputMethodSession;
Jeff Brownc28867a2013-03-26 15:42:39 -070064 mChannel = channel;
65 if (channel != null) {
66 mReceiver = new ImeInputEventReceiver(channel, context.getMainLooper());
67 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 }
69
70 public InputMethodSession getInternalInputMethodSession() {
71 return mInputMethodSession;
72 }
73
Jeff Brownc28867a2013-03-26 15:42:39 -070074 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 public void executeMessage(Message msg) {
Jeff Brownc28867a2013-03-26 15:42:39 -070076 if (mInputMethodSession == null) {
Henrik Baard857cdff2010-07-20 11:42:19 +020077 // The session has been finished. Args needs to be recycled
78 // for cases below.
79 switch (msg.what) {
80 case DO_UPDATE_SELECTION:
81 case DO_APP_PRIVATE_COMMAND: {
82 SomeArgs args = (SomeArgs)msg.obj;
83 args.recycle();
84 }
85 }
Jeff Brownc28867a2013-03-26 15:42:39 -070086 return;
87 }
Ken Wakasaa308c032011-01-25 14:02:07 +090088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 switch (msg.what) {
90 case DO_FINISH_INPUT:
91 mInputMethodSession.finishInput();
92 return;
93 case DO_DISPLAY_COMPLETIONS:
94 mInputMethodSession.displayCompletions((CompletionInfo[])msg.obj);
95 return;
96 case DO_UPDATE_EXTRACTED_TEXT:
97 mInputMethodSession.updateExtractedText(msg.arg1,
98 (ExtractedText)msg.obj);
99 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 case DO_UPDATE_SELECTION: {
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700101 SomeArgs args = (SomeArgs)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 mInputMethodSession.updateSelection(args.argi1, args.argi2,
103 args.argi3, args.argi4, args.argi5, args.argi6);
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700104 args.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 return;
106 }
107 case DO_UPDATE_CURSOR: {
108 mInputMethodSession.updateCursor((Rect)msg.obj);
109 return;
110 }
111 case DO_APP_PRIVATE_COMMAND: {
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700112 SomeArgs args = (SomeArgs)msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 mInputMethodSession.appPrivateCommand((String)args.arg1,
114 (Bundle)args.arg2);
Svetoslav Ganov758143e2012-08-06 16:40:27 -0700115 args.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 return;
117 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800118 case DO_TOGGLE_SOFT_INPUT: {
119 mInputMethodSession.toggleSoftInput(msg.arg1, msg.arg2);
120 return;
121 }
Devin Taylor0c33ed22010-02-23 13:26:46 -0600122 case DO_FINISH_SESSION: {
Jeff Brownc28867a2013-03-26 15:42:39 -0700123 doFinishSession();
Devin Taylor0c33ed22010-02-23 13:26:46 -0600124 return;
125 }
satok863fcd62011-06-21 17:38:02 +0900126 case DO_VIEW_CLICKED: {
127 mInputMethodSession.viewClicked(msg.arg1 == 1);
128 return;
129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 }
131 Log.w(TAG, "Unhandled message code: " + msg.what);
132 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700133
134 private void doFinishSession() {
135 mInputMethodSession = null;
136 if (mReceiver != null) {
137 mReceiver.dispose();
138 mReceiver = null;
139 }
140 if (mChannel != null) {
141 mChannel.dispose();
142 mChannel = null;
143 }
144 }
145
146 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 public void finishInput() {
148 mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_INPUT));
149 }
150
Jeff Brownc28867a2013-03-26 15:42:39 -0700151 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 public void displayCompletions(CompletionInfo[] completions) {
153 mCaller.executeOrSendMessage(mCaller.obtainMessageO(
154 DO_DISPLAY_COMPLETIONS, completions));
155 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700156
157 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 public void updateExtractedText(int token, ExtractedText text) {
159 mCaller.executeOrSendMessage(mCaller.obtainMessageIO(
160 DO_UPDATE_EXTRACTED_TEXT, token, text));
161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162
Jeff Brownc28867a2013-03-26 15:42:39 -0700163 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 public void updateSelection(int oldSelStart, int oldSelEnd,
165 int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
166 mCaller.executeOrSendMessage(mCaller.obtainMessageIIIIII(DO_UPDATE_SELECTION,
167 oldSelStart, oldSelEnd, newSelStart, newSelEnd,
168 candidatesStart, candidatesEnd));
169 }
satok863fcd62011-06-21 17:38:02 +0900170
Jeff Brownc28867a2013-03-26 15:42:39 -0700171 @Override
satok863fcd62011-06-21 17:38:02 +0900172 public void viewClicked(boolean focusChanged) {
Jeff Brownc28867a2013-03-26 15:42:39 -0700173 mCaller.executeOrSendMessage(
174 mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0));
satok863fcd62011-06-21 17:38:02 +0900175 }
176
Jeff Brownc28867a2013-03-26 15:42:39 -0700177 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 public void updateCursor(Rect newCursor) {
Jeff Brownc28867a2013-03-26 15:42:39 -0700179 mCaller.executeOrSendMessage(
180 mCaller.obtainMessageO(DO_UPDATE_CURSOR, newCursor));
The Android Open Source Project4df24232009-03-05 14:34:35 -0800181 }
Devin Taylor0c33ed22010-02-23 13:26:46 -0600182
Jeff Brownc28867a2013-03-26 15:42:39 -0700183 @Override
184 public void appPrivateCommand(String action, Bundle data) {
185 mCaller.executeOrSendMessage(
186 mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, data));
187 }
188
189 @Override
190 public void toggleSoftInput(int showFlags, int hideFlags) {
191 mCaller.executeOrSendMessage(
192 mCaller.obtainMessageII(DO_TOGGLE_SOFT_INPUT, showFlags, hideFlags));
193 }
194
195 @Override
Devin Taylor0c33ed22010-02-23 13:26:46 -0600196 public void finishSession() {
197 mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_SESSION));
198 }
Jeff Brownc28867a2013-03-26 15:42:39 -0700199
200 private final class ImeInputEventReceiver extends InputEventReceiver
201 implements InputMethodSession.EventCallback {
202 private final SparseArray<InputEvent> mPendingEvents = new SparseArray<InputEvent>();
203
204 public ImeInputEventReceiver(InputChannel inputChannel, Looper looper) {
205 super(inputChannel, looper);
206 }
207
208 @Override
209 public void onInputEvent(InputEvent event) {
210 if (mInputMethodSession == null) {
211 // The session has been finished.
212 finishInputEvent(event, false);
213 return;
214 }
215
216 final int seq = event.getSequenceNumber();
217 mPendingEvents.put(seq, event);
218 if (event instanceof KeyEvent) {
219 KeyEvent keyEvent = (KeyEvent)event;
220 mInputMethodSession.dispatchKeyEvent(seq, keyEvent, this);
221 } else {
222 MotionEvent motionEvent = (MotionEvent)event;
223 if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) {
224 mInputMethodSession.dispatchTrackballEvent(seq, motionEvent, this);
225 } else {
226 mInputMethodSession.dispatchGenericMotionEvent(seq, motionEvent, this);
227 }
228 }
229 }
230
231 @Override
232 public void finishedEvent(int seq, boolean handled) {
233 int index = mPendingEvents.indexOfKey(seq);
234 if (index >= 0) {
235 InputEvent event = mPendingEvents.valueAt(index);
236 mPendingEvents.removeAt(index);
237 finishInputEvent(event, handled);
238 }
239 }
240 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241}