PageRenderTime 27ms CodeModel.GetById 9ms app.highlight 14ms RepoModel.GetById 2ms app.codeStats 0ms

/ime/latinime/src/com/googlecode/eyesfree/inputmethod/PersistentInputMethodService.java

http://eyes-free.googlecode.com/
Java | 230 lines | 162 code | 32 blank | 36 comment | 29 complexity | fe8e9c81bcbe0df8d5ad94fc2bff2831 MD5 | raw file
  1/*
  2 * Copyright (C) 2011 Google Inc.
  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
 17package com.googlecode.eyesfree.inputmethod;
 18
 19import android.content.res.Configuration;
 20import android.os.Handler;
 21import android.os.Message;
 22import android.util.Log;
 23import android.view.KeyEvent;
 24import android.view.ViewConfiguration;
 25import android.view.WindowManager;
 26import android.view.inputmethod.EditorInfo;
 27import android.view.inputmethod.InputConnection;
 28
 29import com.google.android.marvin.aime.AccessibleInputMethodService;
 30
 31/**
 32 * This class extends {@link AccessibleInputMethodService} by overriding methods
 33 * related to hiding the input window. It allows the input method to be forced
 34 * open by long-pressing the MENU key.
 35 * 
 36 * @author alanv@google.com (Alan Viverette)
 37 */
 38public class PersistentInputMethodService extends LinearNavigationInputMethodService {
 39    private static final String TAG = "PersistentInputMethodService";
 40    private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout();
 41    private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout();
 42
 43    /** Constant used for LongPressHandler. */
 44    private static final int LONG_PRESS = 1;
 45
 46    private LongPressHandler mLongPressHandler;
 47
 48    /**
 49     * Avoids handling repeated key presses. This is set after the first down
 50     * event in a series of down events, then cleared on an up event.
 51     */
 52    private KeyEvent mDownEvent;
 53
 54    private boolean mInLongPress;
 55
 56    private class LongPressHandler extends Handler {
 57        LongPressHandler() {
 58            super();
 59        }
 60
 61        @Override
 62        public void handleMessage(Message msg) {
 63            switch (msg.what) {
 64                case LONG_PRESS:
 65                    mInLongPress = true;
 66                    onKeyLongPress(msg.arg1, (KeyEvent) msg.obj);
 67                    break;
 68            }
 69        }
 70    }
 71
 72    @Override
 73    public void onCreate() {
 74        super.onCreate();
 75
 76        mLongPressHandler = new LongPressHandler();
 77    }
 78
 79    @Override
 80    public void onConfigurationChanged(Configuration newConfig) {
 81        super.onConfigurationChanged(newConfig);
 82
 83        if (!isAccessibilityEnabled()) {
 84            return;
 85        }
 86
 87        // Ensure that we force the view open when accessibility is enabled, but
 88        // only if we've already been attached to a window.
 89        if (getWindow().getWindow().getAttributes().token != null) {
 90            try {
 91                showWindow(true);
 92            } catch (RuntimeException e) {
 93                e.printStackTrace();
 94            }
 95        }
 96    }
 97
 98    @Override
 99    protected void onAccessibilityChanged(boolean accessibilityEnabled) {
100        if (!accessibilityEnabled) {
101            // This is the only correct way to hide the window. Don't use
102            // hideWindow() or requestHideSelf() because they'll mess up the
103            // internal state.
104            onCreateInputMethodInterface().hideSoftInput(0, null);
105        }
106    }
107
108    @Override
109    public boolean onKeyDown(int keyCode, KeyEvent event) {
110        if (!isAccessibilityEnabled()) {
111            return super.onKeyDown(keyCode, event);
112        }
113
114        switch (keyCode) {
115            case KeyEvent.KEYCODE_BACK:
116                return false;
117            case KeyEvent.KEYCODE_VOLUME_UP:
118            case KeyEvent.KEYCODE_VOLUME_DOWN: {
119                event.startTracking();
120                if (mDownEvent == null) {
121                    mDownEvent = event;
122                    mInLongPress = false;
123                    mLongPressHandler.removeMessages(LONG_PRESS);
124                    mLongPressHandler.sendMessageDelayed(
125                            mLongPressHandler.obtainMessage(LONG_PRESS, keyCode, 0, event),
126                            TAP_TIMEOUT + LONGPRESS_TIMEOUT);
127                }
128                return true;
129            }
130        }
131
132        return super.onKeyDown(keyCode, event);
133    }
134
135    @Override
136    public boolean onKeyUp(int keyCode, KeyEvent event) {
137        if (!isAccessibilityEnabled()) {
138            return super.onKeyUp(keyCode, event);
139        }
140
141        final KeyEvent downEvent = mDownEvent;
142        mDownEvent = null;
143
144        // Give the parent class a chance to consume the cached down
145        // event, then send it through the input connection.
146        if (downEvent != null && !mInLongPress) {
147            final InputConnection input = getCurrentInputConnection();
148            if (!super.onKeyDown(downEvent.getKeyCode(), downEvent) && input != null) {
149                input.sendKeyEvent(downEvent);
150            }
151        }
152
153        switch (keyCode) {
154            case KeyEvent.KEYCODE_BACK:
155                return false;
156            case KeyEvent.KEYCODE_VOLUME_UP:
157            case KeyEvent.KEYCODE_VOLUME_DOWN: {
158                mLongPressHandler.removeMessages(LONG_PRESS);
159                if (mInLongPress) {
160                    mInLongPress = false;
161                    return true;
162                } else {
163                    return super.onKeyUp(keyCode, event);
164                }
165            }
166        }
167
168        return super.onKeyUp(keyCode, event);
169    }
170
171    @Override
172    public void onStartInput(EditorInfo attribute, boolean restarting) {
173        super.onStartInput(attribute, restarting);
174
175        if (!isAccessibilityEnabled()) {
176            return;
177        }
178
179        // Restart input view when changing input.
180        onStartInputView(attribute, restarting);
181    }
182
183    @Override
184    public void hideWindow() {
185        if (!isAccessibilityEnabled()) {
186            super.hideWindow();
187        }
188    }
189
190    @Override
191    public void showWindow(boolean showInput) {
192        if (!isAccessibilityEnabled()) {
193            super.showWindow(showInput);
194        } else {
195            try {
196                super.showWindow(true);
197            } catch (WindowManager.BadTokenException e) {
198                Log.e(TAG, "Failed to show window", e);
199            }
200        }
201    }
202
203    @Override
204    public boolean onShowInputRequested(int flags, boolean configChange) {
205        if (!isAccessibilityEnabled()) {
206            return super.onShowInputRequested(flags, configChange);
207        } else {
208            return true;
209        }
210    }
211
212    @Override
213    public boolean onEvaluateInputViewShown() {
214        if (!isAccessibilityEnabled()) {
215            return super.onEvaluateInputViewShown();
216        } else {
217            return true;
218        }
219    }
220
221    @Override
222    public boolean onEvaluateFullscreenMode() {
223        if (!isAccessibilityEnabled()) {
224            return super.onEvaluateFullscreenMode();
225        } else {
226            // This input method should never show an extract view.
227            return false;
228        }
229    }
230}