TimerHandler.java revision 9342484e8d573a40f470b6a593df31c602fa4076
1/* 2 * Copyright (C) 2013 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 17package com.android.inputmethod.keyboard.internal; 18 19import android.os.Message; 20import android.os.SystemClock; 21import android.view.ViewConfiguration; 22 23import com.android.inputmethod.keyboard.Key; 24import com.android.inputmethod.keyboard.PointerTracker; 25import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; 26import com.android.inputmethod.keyboard.internal.TimerHandler.Callbacks; 27import com.android.inputmethod.latin.common.Constants; 28import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; 29 30import javax.annotation.Nonnull; 31 32// TODO: Separate this class into KeyTimerHandler and BatchInputTimerHandler or so. 33public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> implements TimerProxy { 34 public interface Callbacks { 35 public void startWhileTypingFadeinAnimation(); 36 public void startWhileTypingFadeoutAnimation(); 37 public void onLongPress(PointerTracker tracker); 38 } 39 40 private static final int MSG_TYPING_STATE_EXPIRED = 0; 41 private static final int MSG_REPEAT_KEY = 1; 42 private static final int MSG_LONGPRESS_KEY = 2; 43 private static final int MSG_LONGPRESS_SHIFT_KEY = 3; 44 private static final int MSG_DOUBLE_TAP_SHIFT_KEY = 4; 45 private static final int MSG_UPDATE_BATCH_INPUT = 5; 46 47 private final int mIgnoreAltCodeKeyTimeout; 48 private final int mGestureRecognitionUpdateTime; 49 50 public TimerHandler(@Nonnull final Callbacks ownerInstance, final int ignoreAltCodeKeyTimeout, 51 final int gestureRecognitionUpdateTime) { 52 super(ownerInstance); 53 mIgnoreAltCodeKeyTimeout = ignoreAltCodeKeyTimeout; 54 mGestureRecognitionUpdateTime = gestureRecognitionUpdateTime; 55 } 56 57 @Override 58 public void handleMessage(final Message msg) { 59 final Callbacks callbacks = getOwnerInstance(); 60 if (callbacks == null) { 61 return; 62 } 63 final PointerTracker tracker = (PointerTracker) msg.obj; 64 switch (msg.what) { 65 case MSG_TYPING_STATE_EXPIRED: 66 callbacks.startWhileTypingFadeinAnimation(); 67 break; 68 case MSG_REPEAT_KEY: 69 tracker.onKeyRepeat(msg.arg1 /* code */, msg.arg2 /* repeatCount */); 70 break; 71 case MSG_LONGPRESS_KEY: 72 case MSG_LONGPRESS_SHIFT_KEY: 73 cancelLongPressTimers(); 74 callbacks.onLongPress(tracker); 75 break; 76 case MSG_UPDATE_BATCH_INPUT: 77 tracker.updateBatchInputByTimer(SystemClock.uptimeMillis()); 78 startUpdateBatchInputTimer(tracker); 79 break; 80 } 81 } 82 83 @Override 84 public void startKeyRepeatTimerOf(final PointerTracker tracker, final int repeatCount, 85 final int delay) { 86 final Key key = tracker.getKey(); 87 if (key == null || delay == 0) { 88 return; 89 } 90 sendMessageDelayed( 91 obtainMessage(MSG_REPEAT_KEY, key.getCode(), repeatCount, tracker), delay); 92 } 93 94 private void cancelKeyRepeatTimerOf(final PointerTracker tracker) { 95 removeMessages(MSG_REPEAT_KEY, tracker); 96 } 97 98 public void cancelKeyRepeatTimers() { 99 removeMessages(MSG_REPEAT_KEY); 100 } 101 102 // TODO: Suppress layout changes in key repeat mode 103 public boolean isInKeyRepeat() { 104 return hasMessages(MSG_REPEAT_KEY); 105 } 106 107 @Override 108 public void startLongPressTimerOf(final PointerTracker tracker, final int delay) { 109 final Key key = tracker.getKey(); 110 if (key == null) { 111 return; 112 } 113 // Use a separate message id for long pressing shift key, because long press shift key 114 // timers should be canceled when other key is pressed. 115 final int messageId = (key.getCode() == Constants.CODE_SHIFT) 116 ? MSG_LONGPRESS_SHIFT_KEY : MSG_LONGPRESS_KEY; 117 sendMessageDelayed(obtainMessage(messageId, tracker), delay); 118 } 119 120 @Override 121 public void cancelLongPressTimerOf(final PointerTracker tracker) { 122 removeMessages(MSG_LONGPRESS_KEY, tracker); 123 removeMessages(MSG_LONGPRESS_SHIFT_KEY, tracker); 124 } 125 126 @Override 127 public void cancelLongPressShiftKeyTimers() { 128 removeMessages(MSG_LONGPRESS_SHIFT_KEY); 129 } 130 131 public void cancelLongPressTimers() { 132 removeMessages(MSG_LONGPRESS_KEY); 133 removeMessages(MSG_LONGPRESS_SHIFT_KEY); 134 } 135 136 @Override 137 public void startTypingStateTimer(final Key typedKey) { 138 if (typedKey.isModifier() || typedKey.altCodeWhileTyping()) { 139 return; 140 } 141 142 final boolean isTyping = isTypingState(); 143 removeMessages(MSG_TYPING_STATE_EXPIRED); 144 final Callbacks callbacks = getOwnerInstance(); 145 if (callbacks == null) { 146 return; 147 } 148 149 // When user hits the space or the enter key, just cancel the while-typing timer. 150 final int typedCode = typedKey.getCode(); 151 if (typedCode == Constants.CODE_SPACE || typedCode == Constants.CODE_ENTER) { 152 if (isTyping) { 153 callbacks.startWhileTypingFadeinAnimation(); 154 } 155 return; 156 } 157 158 sendMessageDelayed( 159 obtainMessage(MSG_TYPING_STATE_EXPIRED), mIgnoreAltCodeKeyTimeout); 160 if (isTyping) { 161 return; 162 } 163 callbacks.startWhileTypingFadeoutAnimation(); 164 } 165 166 @Override 167 public boolean isTypingState() { 168 return hasMessages(MSG_TYPING_STATE_EXPIRED); 169 } 170 171 @Override 172 public void startDoubleTapShiftKeyTimer() { 173 sendMessageDelayed(obtainMessage(MSG_DOUBLE_TAP_SHIFT_KEY), 174 ViewConfiguration.getDoubleTapTimeout()); 175 } 176 177 @Override 178 public void cancelDoubleTapShiftKeyTimer() { 179 removeMessages(MSG_DOUBLE_TAP_SHIFT_KEY); 180 } 181 182 @Override 183 public boolean isInDoubleTapShiftKeyTimeout() { 184 return hasMessages(MSG_DOUBLE_TAP_SHIFT_KEY); 185 } 186 187 @Override 188 public void cancelKeyTimersOf(final PointerTracker tracker) { 189 cancelKeyRepeatTimerOf(tracker); 190 cancelLongPressTimerOf(tracker); 191 } 192 193 public void cancelAllKeyTimers() { 194 cancelKeyRepeatTimers(); 195 cancelLongPressTimers(); 196 } 197 198 @Override 199 public void startUpdateBatchInputTimer(final PointerTracker tracker) { 200 if (mGestureRecognitionUpdateTime <= 0) { 201 return; 202 } 203 removeMessages(MSG_UPDATE_BATCH_INPUT, tracker); 204 sendMessageDelayed(obtainMessage(MSG_UPDATE_BATCH_INPUT, tracker), 205 mGestureRecognitionUpdateTime); 206 } 207 208 @Override 209 public void cancelUpdateBatchInputTimer(final PointerTracker tracker) { 210 removeMessages(MSG_UPDATE_BATCH_INPUT, tracker); 211 } 212 213 @Override 214 public void cancelAllUpdateBatchInputTimers() { 215 removeMessages(MSG_UPDATE_BATCH_INPUT); 216 } 217 218 public void cancelAllMessages() { 219 cancelAllKeyTimers(); 220 cancelAllUpdateBatchInputTimers(); 221 } 222} 223