Home | History | Annotate | Download | only in inputmethodservice
      1 /*
      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 
     17 package android.inputmethodservice;
     18 
     19 import com.android.internal.os.HandlerCaller;
     20 import com.android.internal.os.SomeArgs;
     21 import com.android.internal.view.IInputMethodSession;
     22 
     23 import android.content.Context;
     24 import android.graphics.Rect;
     25 import android.os.Bundle;
     26 import android.os.Looper;
     27 import android.os.Message;
     28 import android.os.RemoteException;
     29 import android.util.Log;
     30 import android.util.SparseArray;
     31 import android.view.InputChannel;
     32 import android.view.InputDevice;
     33 import android.view.InputEvent;
     34 import android.view.InputEventReceiver;
     35 import android.view.KeyEvent;
     36 import android.view.MotionEvent;
     37 import android.view.inputmethod.CompletionInfo;
     38 import android.view.inputmethod.ExtractedText;
     39 import android.view.inputmethod.InputMethodSession;
     40 
     41 class IInputMethodSessionWrapper extends IInputMethodSession.Stub
     42         implements HandlerCaller.Callback {
     43     private static final String TAG = "InputMethodWrapper";
     44 
     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;
     48     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;
     51     private static final int DO_TOGGLE_SOFT_INPUT = 105;
     52     private static final int DO_FINISH_SESSION = 110;
     53     private static final int DO_VIEW_CLICKED = 115;
     54 
     55     HandlerCaller mCaller;
     56     InputMethodSession mInputMethodSession;
     57     InputChannel mChannel;
     58     ImeInputEventReceiver mReceiver;
     59 
     60     public IInputMethodSessionWrapper(Context context,
     61             InputMethodSession inputMethodSession, InputChannel channel) {
     62         mCaller = new HandlerCaller(context, null,
     63                 this, true /*asyncHandler*/);
     64         mInputMethodSession = inputMethodSession;
     65         mChannel = channel;
     66         if (channel != null) {
     67             mReceiver = new ImeInputEventReceiver(channel, context.getMainLooper());
     68         }
     69     }
     70 
     71     public InputMethodSession getInternalInputMethodSession() {
     72         return mInputMethodSession;
     73     }
     74 
     75     @Override
     76     public void executeMessage(Message msg) {
     77         if (mInputMethodSession == null) {
     78             // The session has been finished.
     79             return;
     80         }
     81 
     82         switch (msg.what) {
     83             case DO_FINISH_INPUT:
     84                 mInputMethodSession.finishInput();
     85                 return;
     86             case DO_DISPLAY_COMPLETIONS:
     87                 mInputMethodSession.displayCompletions((CompletionInfo[])msg.obj);
     88                 return;
     89             case DO_UPDATE_EXTRACTED_TEXT:
     90                 mInputMethodSession.updateExtractedText(msg.arg1,
     91                         (ExtractedText)msg.obj);
     92                 return;
     93             case DO_UPDATE_SELECTION: {
     94                 SomeArgs args = (SomeArgs)msg.obj;
     95                 mInputMethodSession.updateSelection(args.argi1, args.argi2,
     96                         args.argi3, args.argi4, args.argi5, args.argi6);
     97                 args.recycle();
     98                 return;
     99             }
    100             case DO_UPDATE_CURSOR: {
    101                 mInputMethodSession.updateCursor((Rect)msg.obj);
    102                 return;
    103             }
    104             case DO_APP_PRIVATE_COMMAND: {
    105                 SomeArgs args = (SomeArgs)msg.obj;
    106                 mInputMethodSession.appPrivateCommand((String)args.arg1,
    107                         (Bundle)args.arg2);
    108                 args.recycle();
    109                 return;
    110             }
    111             case DO_TOGGLE_SOFT_INPUT: {
    112                 mInputMethodSession.toggleSoftInput(msg.arg1, msg.arg2);
    113                 return;
    114             }
    115             case DO_FINISH_SESSION: {
    116                 doFinishSession();
    117                 return;
    118             }
    119             case DO_VIEW_CLICKED: {
    120                 mInputMethodSession.viewClicked(msg.arg1 == 1);
    121                 return;
    122             }
    123         }
    124         Log.w(TAG, "Unhandled message code: " + msg.what);
    125     }
    126 
    127     private void doFinishSession() {
    128         mInputMethodSession = null;
    129         if (mReceiver != null) {
    130             mReceiver.dispose();
    131             mReceiver = null;
    132         }
    133         if (mChannel != null) {
    134             mChannel.dispose();
    135             mChannel = null;
    136         }
    137     }
    138 
    139     @Override
    140     public void finishInput() {
    141         mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_INPUT));
    142     }
    143 
    144     @Override
    145     public void displayCompletions(CompletionInfo[] completions) {
    146         mCaller.executeOrSendMessage(mCaller.obtainMessageO(
    147                 DO_DISPLAY_COMPLETIONS, completions));
    148     }
    149 
    150     @Override
    151     public void updateExtractedText(int token, ExtractedText text) {
    152         mCaller.executeOrSendMessage(mCaller.obtainMessageIO(
    153                 DO_UPDATE_EXTRACTED_TEXT, token, text));
    154     }
    155 
    156     @Override
    157     public void updateSelection(int oldSelStart, int oldSelEnd,
    158             int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
    159         mCaller.executeOrSendMessage(mCaller.obtainMessageIIIIII(DO_UPDATE_SELECTION,
    160                 oldSelStart, oldSelEnd, newSelStart, newSelEnd,
    161                 candidatesStart, candidatesEnd));
    162     }
    163 
    164     @Override
    165     public void viewClicked(boolean focusChanged) {
    166         mCaller.executeOrSendMessage(
    167                 mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0));
    168     }
    169 
    170     @Override
    171     public void updateCursor(Rect newCursor) {
    172         mCaller.executeOrSendMessage(
    173                 mCaller.obtainMessageO(DO_UPDATE_CURSOR, newCursor));
    174     }
    175 
    176     @Override
    177     public void appPrivateCommand(String action, Bundle data) {
    178         mCaller.executeOrSendMessage(
    179                 mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, data));
    180     }
    181 
    182     @Override
    183     public void toggleSoftInput(int showFlags, int hideFlags) {
    184         mCaller.executeOrSendMessage(
    185                 mCaller.obtainMessageII(DO_TOGGLE_SOFT_INPUT, showFlags, hideFlags));
    186     }
    187 
    188     @Override
    189     public void finishSession() {
    190         mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_SESSION));
    191     }
    192 
    193     private final class ImeInputEventReceiver extends InputEventReceiver
    194             implements InputMethodSession.EventCallback {
    195         private final SparseArray<InputEvent> mPendingEvents = new SparseArray<InputEvent>();
    196 
    197         public ImeInputEventReceiver(InputChannel inputChannel, Looper looper) {
    198             super(inputChannel, looper);
    199         }
    200 
    201         @Override
    202         public void onInputEvent(InputEvent event) {
    203             if (mInputMethodSession == null) {
    204                 // The session has been finished.
    205                 finishInputEvent(event, false);
    206                 return;
    207             }
    208 
    209             final int seq = event.getSequenceNumber();
    210             mPendingEvents.put(seq, event);
    211             if (event instanceof KeyEvent) {
    212                 KeyEvent keyEvent = (KeyEvent)event;
    213                 mInputMethodSession.dispatchKeyEvent(seq, keyEvent, this);
    214             } else {
    215                 MotionEvent motionEvent = (MotionEvent)event;
    216                 if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) {
    217                     mInputMethodSession.dispatchTrackballEvent(seq, motionEvent, this);
    218                 } else {
    219                     mInputMethodSession.dispatchGenericMotionEvent(seq, motionEvent, this);
    220                 }
    221             }
    222         }
    223 
    224         @Override
    225         public void finishedEvent(int seq, boolean handled) {
    226             int index = mPendingEvents.indexOfKey(seq);
    227             if (index >= 0) {
    228                 InputEvent event = mPendingEvents.valueAt(index);
    229                 mPendingEvents.removeAt(index);
    230                 finishInputEvent(event, handled);
    231             }
    232         }
    233     }
    234 }
    235