2013-12-13 08:09:16 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013 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.keyboard.internal;
|
|
|
|
|
|
|
|
import android.os.Message;
|
|
|
|
import android.os.SystemClock;
|
|
|
|
import android.view.ViewConfiguration;
|
|
|
|
|
|
|
|
import com.android.inputmethod.keyboard.Key;
|
|
|
|
import com.android.inputmethod.keyboard.PointerTracker;
|
|
|
|
import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
|
|
|
|
import com.android.inputmethod.keyboard.internal.TimerHandler.Callbacks;
|
2014-10-23 09:37:32 +00:00
|
|
|
import com.android.inputmethod.latin.common.Constants;
|
2013-12-13 08:09:16 +00:00
|
|
|
import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
|
|
|
|
|
2014-10-14 08:42:10 +00:00
|
|
|
import javax.annotation.Nonnull;
|
|
|
|
|
2013-12-13 08:09:16 +00:00
|
|
|
// TODO: Separate this class into KeyTimerHandler and BatchInputTimerHandler or so.
|
|
|
|
public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> implements TimerProxy {
|
|
|
|
public interface Callbacks {
|
2014-10-29 06:47:40 +00:00
|
|
|
public static final int FADE_IN = 0;
|
|
|
|
public static final int FADE_OUT = 1;
|
|
|
|
public void startWhileTypingAnimation(final int fadeInOrOut);
|
|
|
|
public void onLongPress(@Nonnull PointerTracker tracker);
|
2014-10-29 03:56:42 +00:00
|
|
|
public void dismissKeyPreviewWithoutDelay(@Nonnull Key key);
|
|
|
|
public void dismissGestureFloatingPreviewTextWithoutDelay();
|
2013-12-13 08:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private static final int MSG_TYPING_STATE_EXPIRED = 0;
|
|
|
|
private static final int MSG_REPEAT_KEY = 1;
|
|
|
|
private static final int MSG_LONGPRESS_KEY = 2;
|
2013-12-16 05:55:05 +00:00
|
|
|
private static final int MSG_LONGPRESS_SHIFT_KEY = 3;
|
|
|
|
private static final int MSG_DOUBLE_TAP_SHIFT_KEY = 4;
|
|
|
|
private static final int MSG_UPDATE_BATCH_INPUT = 5;
|
2014-10-29 03:56:42 +00:00
|
|
|
private static final int MSG_DISMISS_KEY_PREVIEW = 6;
|
|
|
|
private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 7;
|
2013-12-13 08:09:16 +00:00
|
|
|
|
|
|
|
private final int mIgnoreAltCodeKeyTimeout;
|
|
|
|
private final int mGestureRecognitionUpdateTime;
|
|
|
|
|
2014-10-14 08:42:10 +00:00
|
|
|
public TimerHandler(@Nonnull final Callbacks ownerInstance, final int ignoreAltCodeKeyTimeout,
|
2013-12-13 08:09:16 +00:00
|
|
|
final int gestureRecognitionUpdateTime) {
|
|
|
|
super(ownerInstance);
|
|
|
|
mIgnoreAltCodeKeyTimeout = ignoreAltCodeKeyTimeout;
|
|
|
|
mGestureRecognitionUpdateTime = gestureRecognitionUpdateTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void handleMessage(final Message msg) {
|
|
|
|
final Callbacks callbacks = getOwnerInstance();
|
|
|
|
if (callbacks == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (msg.what) {
|
|
|
|
case MSG_TYPING_STATE_EXPIRED:
|
2014-10-29 06:47:40 +00:00
|
|
|
callbacks.startWhileTypingAnimation(Callbacks.FADE_IN);
|
2013-12-13 08:09:16 +00:00
|
|
|
break;
|
|
|
|
case MSG_REPEAT_KEY:
|
2014-10-29 03:56:42 +00:00
|
|
|
final PointerTracker tracker1 = (PointerTracker) msg.obj;
|
|
|
|
tracker1.onKeyRepeat(msg.arg1 /* code */, msg.arg2 /* repeatCount */);
|
2013-12-13 08:09:16 +00:00
|
|
|
break;
|
|
|
|
case MSG_LONGPRESS_KEY:
|
2013-12-16 05:55:05 +00:00
|
|
|
case MSG_LONGPRESS_SHIFT_KEY:
|
2013-12-13 08:09:16 +00:00
|
|
|
cancelLongPressTimers();
|
2014-10-29 03:56:42 +00:00
|
|
|
final PointerTracker tracker2 = (PointerTracker) msg.obj;
|
|
|
|
callbacks.onLongPress(tracker2);
|
2013-12-13 08:09:16 +00:00
|
|
|
break;
|
|
|
|
case MSG_UPDATE_BATCH_INPUT:
|
2014-10-29 03:56:42 +00:00
|
|
|
final PointerTracker tracker3 = (PointerTracker) msg.obj;
|
|
|
|
tracker3.updateBatchInputByTimer(SystemClock.uptimeMillis());
|
|
|
|
startUpdateBatchInputTimer(tracker3);
|
|
|
|
break;
|
|
|
|
case MSG_DISMISS_KEY_PREVIEW:
|
|
|
|
final Key key = (Key) msg.obj;
|
|
|
|
callbacks.dismissKeyPreviewWithoutDelay(key);
|
|
|
|
break;
|
|
|
|
case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT:
|
|
|
|
callbacks.dismissGestureFloatingPreviewTextWithoutDelay();
|
2013-12-13 08:09:16 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void startKeyRepeatTimerOf(final PointerTracker tracker, final int repeatCount,
|
|
|
|
final int delay) {
|
|
|
|
final Key key = tracker.getKey();
|
|
|
|
if (key == null || delay == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
sendMessageDelayed(
|
|
|
|
obtainMessage(MSG_REPEAT_KEY, key.getCode(), repeatCount, tracker), delay);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void cancelKeyRepeatTimerOf(final PointerTracker tracker) {
|
|
|
|
removeMessages(MSG_REPEAT_KEY, tracker);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void cancelKeyRepeatTimers() {
|
|
|
|
removeMessages(MSG_REPEAT_KEY);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Suppress layout changes in key repeat mode
|
|
|
|
public boolean isInKeyRepeat() {
|
|
|
|
return hasMessages(MSG_REPEAT_KEY);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void startLongPressTimerOf(final PointerTracker tracker, final int delay) {
|
2013-12-16 05:55:05 +00:00
|
|
|
final Key key = tracker.getKey();
|
|
|
|
if (key == null) {
|
2013-12-13 08:09:16 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-12-16 05:55:05 +00:00
|
|
|
// Use a separate message id for long pressing shift key, because long press shift key
|
|
|
|
// timers should be canceled when other key is pressed.
|
|
|
|
final int messageId = (key.getCode() == Constants.CODE_SHIFT)
|
|
|
|
? MSG_LONGPRESS_SHIFT_KEY : MSG_LONGPRESS_KEY;
|
|
|
|
sendMessageDelayed(obtainMessage(messageId, tracker), delay);
|
2013-12-13 08:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void cancelLongPressTimerOf(final PointerTracker tracker) {
|
|
|
|
removeMessages(MSG_LONGPRESS_KEY, tracker);
|
2013-12-16 05:55:05 +00:00
|
|
|
removeMessages(MSG_LONGPRESS_SHIFT_KEY, tracker);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void cancelLongPressShiftKeyTimers() {
|
|
|
|
removeMessages(MSG_LONGPRESS_SHIFT_KEY);
|
2013-12-13 08:09:16 +00:00
|
|
|
}
|
|
|
|
|
2014-01-09 03:53:35 +00:00
|
|
|
public void cancelLongPressTimers() {
|
2013-12-13 08:09:16 +00:00
|
|
|
removeMessages(MSG_LONGPRESS_KEY);
|
2013-12-16 05:55:05 +00:00
|
|
|
removeMessages(MSG_LONGPRESS_SHIFT_KEY);
|
2013-12-13 08:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void startTypingStateTimer(final Key typedKey) {
|
|
|
|
if (typedKey.isModifier() || typedKey.altCodeWhileTyping()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
final boolean isTyping = isTypingState();
|
|
|
|
removeMessages(MSG_TYPING_STATE_EXPIRED);
|
|
|
|
final Callbacks callbacks = getOwnerInstance();
|
|
|
|
if (callbacks == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// When user hits the space or the enter key, just cancel the while-typing timer.
|
|
|
|
final int typedCode = typedKey.getCode();
|
|
|
|
if (typedCode == Constants.CODE_SPACE || typedCode == Constants.CODE_ENTER) {
|
|
|
|
if (isTyping) {
|
2014-10-29 06:47:40 +00:00
|
|
|
callbacks.startWhileTypingAnimation(Callbacks.FADE_IN);
|
2013-12-13 08:09:16 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sendMessageDelayed(
|
|
|
|
obtainMessage(MSG_TYPING_STATE_EXPIRED), mIgnoreAltCodeKeyTimeout);
|
|
|
|
if (isTyping) {
|
|
|
|
return;
|
|
|
|
}
|
2014-10-29 06:47:40 +00:00
|
|
|
callbacks.startWhileTypingAnimation(Callbacks.FADE_OUT);
|
2013-12-13 08:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isTypingState() {
|
|
|
|
return hasMessages(MSG_TYPING_STATE_EXPIRED);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void startDoubleTapShiftKeyTimer() {
|
|
|
|
sendMessageDelayed(obtainMessage(MSG_DOUBLE_TAP_SHIFT_KEY),
|
|
|
|
ViewConfiguration.getDoubleTapTimeout());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void cancelDoubleTapShiftKeyTimer() {
|
|
|
|
removeMessages(MSG_DOUBLE_TAP_SHIFT_KEY);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isInDoubleTapShiftKeyTimeout() {
|
|
|
|
return hasMessages(MSG_DOUBLE_TAP_SHIFT_KEY);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void cancelKeyTimersOf(final PointerTracker tracker) {
|
|
|
|
cancelKeyRepeatTimerOf(tracker);
|
|
|
|
cancelLongPressTimerOf(tracker);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void cancelAllKeyTimers() {
|
|
|
|
cancelKeyRepeatTimers();
|
|
|
|
cancelLongPressTimers();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void startUpdateBatchInputTimer(final PointerTracker tracker) {
|
|
|
|
if (mGestureRecognitionUpdateTime <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
removeMessages(MSG_UPDATE_BATCH_INPUT, tracker);
|
|
|
|
sendMessageDelayed(obtainMessage(MSG_UPDATE_BATCH_INPUT, tracker),
|
|
|
|
mGestureRecognitionUpdateTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void cancelUpdateBatchInputTimer(final PointerTracker tracker) {
|
|
|
|
removeMessages(MSG_UPDATE_BATCH_INPUT, tracker);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void cancelAllUpdateBatchInputTimers() {
|
|
|
|
removeMessages(MSG_UPDATE_BATCH_INPUT);
|
|
|
|
}
|
|
|
|
|
2014-10-29 03:56:42 +00:00
|
|
|
public void postDismissKeyPreview(@Nonnull final Key key, final long delay) {
|
|
|
|
sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, key), delay);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void postDismissGestureFloatingPreviewText(final long delay) {
|
|
|
|
sendMessageDelayed(obtainMessage(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT), delay);
|
|
|
|
}
|
|
|
|
|
2013-12-13 08:09:16 +00:00
|
|
|
public void cancelAllMessages() {
|
|
|
|
cancelAllKeyTimers();
|
|
|
|
cancelAllUpdateBatchInputTimers();
|
2014-10-29 03:56:42 +00:00
|
|
|
removeMessages(MSG_DISMISS_KEY_PREVIEW);
|
|
|
|
removeMessages(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT);
|
2013-12-13 08:09:16 +00:00
|
|
|
}
|
|
|
|
}
|