LatinIME/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java

173 lines
5.8 KiB
Java
Raw Normal View History

/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.accessibility;
import android.content.Context;
import android.content.SharedPreferences;
import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
import android.os.Looper;
import android.os.Message;
import android.os.Vibrator;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActionListener {
private static final AccessibleInputMethodServiceProxy sInstance =
new AccessibleInputMethodServiceProxy();
/*
* Delay for the handler event that's fired when Accessibility is on and the
* user hovers outside of any valid keys. This is used to let the user know
* that if they lift their finger, nothing will be typed.
*/
private static final long DELAY_NO_HOVER_SELECTION = 250;
/**
* Duration of the key click vibration in milliseconds.
*/
private static final long VIBRATE_KEY_CLICK = 50;
private InputMethodService mInputMethod;
private Vibrator mVibrator;
private AudioManager mAudioManager;
private AccessibilityHandler mAccessibilityHandler;
private static class AccessibilityHandler
extends StaticInnerHandlerWrapper<AccessibleInputMethodServiceProxy> {
private static final int MSG_NO_HOVER_SELECTION = 0;
public AccessibilityHandler(AccessibleInputMethodServiceProxy outerInstance,
Looper looper) {
super(outerInstance, looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_NO_HOVER_SELECTION:
getOuterInstance().notifyNoHoverSelection();
break;
}
}
public void postNoHoverSelection() {
removeMessages(MSG_NO_HOVER_SELECTION);
sendEmptyMessageDelayed(MSG_NO_HOVER_SELECTION, DELAY_NO_HOVER_SELECTION);
}
public void cancelNoHoverSelection() {
removeMessages(MSG_NO_HOVER_SELECTION);
}
}
public static void init(InputMethodService inputMethod, SharedPreferences prefs) {
sInstance.initInternal(inputMethod, prefs);
}
public static AccessibleInputMethodServiceProxy getInstance() {
return sInstance;
}
private AccessibleInputMethodServiceProxy() {
// Not publicly instantiable.
}
private void initInternal(InputMethodService inputMethod, SharedPreferences prefs) {
mInputMethod = inputMethod;
mVibrator = (Vibrator) inputMethod.getSystemService(Context.VIBRATOR_SERVICE);
mAudioManager = (AudioManager) inputMethod.getSystemService(Context.AUDIO_SERVICE);
mAccessibilityHandler = new AccessibilityHandler(this, inputMethod.getMainLooper());
}
/**
* If touch exploration is enabled, cancels the event sent by
* {@link AccessibleInputMethodServiceProxy#onHoverExit(int)} because the
* user is currently hovering above a key.
*/
@Override
public void onHoverEnter(int primaryCode) {
mAccessibilityHandler.cancelNoHoverSelection();
}
/**
* If touch exploration is enabled, sends a delayed event to notify the user
* that they are not currently hovering above a key.
*/
@Override
public void onHoverExit(int primaryCode) {
mAccessibilityHandler.postNoHoverSelection();
}
/**
* Handle flick gestures by mapping them to directional pad keys.
*/
@Override
public void onFlickGesture(int direction) {
final int keyEventCode;
switch (direction) {
case FlickGestureDetector.FLICK_LEFT:
sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_LEFT);
break;
case FlickGestureDetector.FLICK_RIGHT:
sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_RIGHT);
break;
}
}
/**
* Provide haptic feedback and send the specified keyCode to the input
* connection as a pair of down/up events.
*
* @param keyCode
*/
private void sendDownUpKeyEvents(int keyCode) {
mVibrator.vibrate(VIBRATE_KEY_CLICK);
mAudioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
mInputMethod.sendDownUpKeyEvents(keyCode);
}
/**
* When Accessibility is turned on, notifies the user that they are not
* currently hovering above a key. By default this will speak the currently
* entered text.
*/
private void notifyNoHoverSelection() {
final ExtractedText extracted = mInputMethod.getCurrentInputConnection().getExtractedText(
new ExtractedTextRequest(), 0);
if (extracted == null)
return;
final CharSequence text;
if (TextUtils.isEmpty(extracted.text)) {
text = mInputMethod.getString(R.string.spoken_no_text_entered);
} else {
text = mInputMethod.getString(R.string.spoken_current_text_is, extracted.text);
}
AccessibilityUtils.getInstance().speak(text);
}
}