PointerTracker.java revision eea34598bf63f670f47d7b3f37b6436921e5fe02
16a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka/* 28632bff2d5a8e1160989008dea6eff4b94b065ddTadashi G. Takaoka * Copyright (C) 2010 The Android Open Source Project 36a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * 46a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); you may not 56a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * use this file except in compliance with the License. You may obtain a copy of 66a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * the License at 76a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * 86a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 96a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * 106a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 116a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 126a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 136a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * License for the specific language governing permissions and limitations under 146a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka * the License. 156a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka */ 166a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 175a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokapackage com.android.inputmethod.keyboard; 186a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 19e51d164482c7896892d6eccb80f1e1e6fe6d50dbTadashi G. Takaokaimport android.os.SystemClock; 20c2a21786e526cc32e48a577a55b1b7e72ae1a6ddTadashi G. Takaokaimport android.util.Log; 218ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaokaimport android.view.MotionEvent; 22fe824948bb5c07dcd0a47221cb5b7b4f2f4365caTadashi G. Takaokaimport android.view.View; 234692af50daefea9498faebeaa8d7e7a444afda4cTadashi G. Takaokaimport android.widget.TextView; 24c2a21786e526cc32e48a577a55b1b7e72ae1a6ddTadashi G. Takaoka 25eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyangimport com.android.inputmethod.keyboard.internal.GestureTracker; 2672934bd5967d0127f71fd4d66158b18b4e6ceefeTadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.PointerTrackerQueue; 27faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinImeLogger; 289bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridgeimport com.android.inputmethod.latin.ResearchLogger; 299bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridgeimport com.android.inputmethod.latin.define.ProductionFlag; 306a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 315c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaokaimport java.util.ArrayList; 32dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka 336a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaokapublic class PointerTracker { 34dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka private static final String TAG = PointerTracker.class.getSimpleName(); 35dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka private static final boolean DEBUG_EVENT = false; 36dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka private static final boolean DEBUG_MOVE_EVENT = false; 37dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka private static final boolean DEBUG_LISTENER = false; 38faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka private static boolean DEBUG_MODE = LatinImeLogger.sDBG; 3940a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka 40f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka public interface KeyEventHandler { 41f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka /** 42f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka * Get KeyDetector object that is used for this PointerTracker. 43f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka * @return the KeyDetector object that is used for this PointerTracker 44f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka */ 45f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka public KeyDetector getKeyDetector(); 46f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka 47f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka /** 48f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka * Get KeyboardActionListener object that is used to register key code and so on. 49f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka * @return the KeyboardActionListner for this PointerTracker 50f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka */ 51f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka public KeyboardActionListener getKeyboardActionListener(); 52f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka 53f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka /** 54f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka * Get DrawingProxy object that is used for this PointerTracker. 55f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka * @return the DrawingProxy object that is used for this PointerTracker 56f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka */ 57f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka public DrawingProxy getDrawingProxy(); 58f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka 59f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka /** 60f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka * Get TimerProxy object that handles key repeat and long press timer event for this 61f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka * PointerTracker. 62f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka * @return the TimerProxy object that handles key repeat and long press timer event. 63f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka */ 64f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka public TimerProxy getTimerProxy(); 65f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka } 66f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka 679d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka public interface DrawingProxy extends MoreKeysPanel.Controller { 686a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka public void invalidateKey(Key key); 694692af50daefea9498faebeaa8d7e7a444afda4cTadashi G. Takaoka public TextView inflateKeyPreviewText(); 70e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka public void showKeyPreview(PointerTracker tracker); 71d9786ce2e389c8c02af7773b53b5c44fe4fa0b0cTadashi G. Takaoka public void dismissKeyPreview(PointerTracker tracker); 726a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 736a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 742321caa1f9eb6c2d616bc36f11f5b48eebf144feTadashi G. Takaoka public interface TimerProxy { 7573a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka public void startTypingStateTimer(); 7673a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka public boolean isTypingState(); 77a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka public void startKeyRepeatTimer(PointerTracker tracker); 78a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka public void startLongPressTimer(PointerTracker tracker); 79a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka public void startLongPressTimer(int code); 8098b5c982b93cbfc74b221af30079ecb69dd4e0a1Tadashi G. Takaoka public void cancelLongPressTimer(); 810ed2d3a4491cb0f6142975a15b653be6079b6a4eTadashi G. Takaoka public void startDoubleTapTimer(); 82beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka public void cancelDoubleTapTimer(); 830ed2d3a4491cb0f6142975a15b653be6079b6a4eTadashi G. Takaoka public boolean isInDoubleTapTimeout(); 842321caa1f9eb6c2d616bc36f11f5b48eebf144feTadashi G. Takaoka public void cancelKeyTimers(); 8529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka 8629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka public static class Adapter implements TimerProxy { 8729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka @Override 8873a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka public void startTypingStateTimer() {} 8993246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka @Override 9073a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka public boolean isTypingState() { return false; } 9193246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka @Override 92a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka public void startKeyRepeatTimer(PointerTracker tracker) {} 9329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka @Override 94a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka public void startLongPressTimer(PointerTracker tracker) {} 95a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka @Override 96a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka public void startLongPressTimer(int code) {} 9729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka @Override 9829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka public void cancelLongPressTimer() {} 9929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka @Override 1000ed2d3a4491cb0f6142975a15b653be6079b6a4eTadashi G. Takaoka public void startDoubleTapTimer() {} 1010ed2d3a4491cb0f6142975a15b653be6079b6a4eTadashi G. Takaoka @Override 102beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka public void cancelDoubleTapTimer() {} 103beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka @Override 1040ed2d3a4491cb0f6142975a15b653be6079b6a4eTadashi G. Takaoka public boolean isInDoubleTapTimeout() { return false; } 1050ed2d3a4491cb0f6142975a15b653be6079b6a4eTadashi G. Takaoka @Override 10629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka public void cancelKeyTimers() {} 10729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka } 1082321caa1f9eb6c2d616bc36f11f5b48eebf144feTadashi G. Takaoka } 1092321caa1f9eb6c2d616bc36f11f5b48eebf144feTadashi G. Takaoka 110160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka // Parameters for pointer handling. 111160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka private static LatinKeyboardView.PointerTrackerParams sParams; 1125c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka private static int sTouchNoiseThresholdDistanceSquared; 113d438fcaca2a35ace4fee5b7a469596bfe2d1b025Tadashi G. Takaoka private static boolean sNeedsPhantomSuddenMoveEventHack; 1145c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka 115b4fbbe57f574ce6e6a5827156f875fe7d3eb5089Tadashi G. Takaoka private static final ArrayList<PointerTracker> sTrackers = new ArrayList<PointerTracker>(); 1165c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka private static PointerTrackerQueue sPointerTrackerQueue; 1175c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka 1185c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka public final int mPointerId; 1196a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 1200efe174ea43fe576683102effbaef5be27575706Tadashi G. Takaoka private DrawingProxy mDrawingProxy; 1210efe174ea43fe576683102effbaef5be27575706Tadashi G. Takaoka private TimerProxy mTimerProxy; 122a19b84dcf65bd70caa0fc72089cfe043b023a898Tadashi G. Takaoka private KeyDetector mKeyDetector; 123dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka private KeyboardActionListener mListener = EMPTY_LISTENER; 124baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka 1255a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka private Keyboard mKeyboard; 126faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka private int mKeyQuarterWidthSquared; 1274692af50daefea9498faebeaa8d7e7a444afda4cTadashi G. Takaoka private final TextView mKeyPreviewText; 1286a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 1298a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka // The position and time at which first down event occurred. 1308a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka private long mDownTime; 1318a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka private long mUpTime; 1328a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka 133e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka // The current key where this pointer is. 134e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private Key mCurrentKey = null; 135e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka // The position where the current key was recognized for the first time. 1368a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka private int mKeyX; 1378a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka private int mKeyY; 1388a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka 1398a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka // Last pointer position. 1408a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka private int mLastX; 1418a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka private int mLastY; 1426a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 1431a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka // true if keyboard layout has been changed. 1441a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka private boolean mKeyboardLayoutHasBeenChanged; 1451a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka 1469ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka // true if event is already translated to a key action. 147c5d33b16521de56ad01b0b6308217efb009078b7Tadashi G. Takaoka private boolean mKeyAlreadyProcessed; 148c5d33b16521de56ad01b0b6308217efb009078b7Tadashi G. Takaoka 1499d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka // true if this pointer has been long-pressed and is showing a more keys panel. 1509d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka private boolean mIsShowingMoreKeysPanel; 1519ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka 152cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka // true if this pointer is in sliding key input 1535c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka boolean mIsInSlidingKeyInput; 154cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka 15567a4ecacc7525c9343cded13fc93e9a2381ea2d8Tadashi G. Takaoka // true if sliding key is allowed. 15667a4ecacc7525c9343cded13fc93e9a2381ea2d8Tadashi G. Takaoka private boolean mIsAllowedSlidingKeyInput; 15767a4ecacc7525c9343cded13fc93e9a2381ea2d8Tadashi G. Takaoka 158996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka // ignore modifier key if true 159996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka private boolean mIgnoreModifierKey; 160996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka 161dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka // Empty {@link KeyboardActionListener} 162e3be3bcebc11892b536fdf650f74bba21af13383Tadashi G. Takaoka private static final KeyboardActionListener EMPTY_LISTENER = 163e3be3bcebc11892b536fdf650f74bba21af13383Tadashi G. Takaoka new KeyboardActionListener.Adapter(); 1646e5a3986854549a45c95770b5a88ae5577e93299Tadashi G. Takaoka 165eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang // Gesture tracker singleton instance 166eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang private static final GestureTracker sGestureTracker = GestureTracker.getInstance(); 167eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang 168d438fcaca2a35ace4fee5b7a469596bfe2d1b025Tadashi G. Takaoka public static void init(boolean hasDistinctMultitouch, 169d438fcaca2a35ace4fee5b7a469596bfe2d1b025Tadashi G. Takaoka boolean needsPhantomSuddenMoveEventHack) { 1705c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka if (hasDistinctMultitouch) { 1715c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka sPointerTrackerQueue = new PointerTrackerQueue(); 1725c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } else { 1735c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka sPointerTrackerQueue = null; 1745c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } 175d438fcaca2a35ace4fee5b7a469596bfe2d1b025Tadashi G. Takaoka sNeedsPhantomSuddenMoveEventHack = needsPhantomSuddenMoveEventHack; 1765c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka 177160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka setParameters(LatinKeyboardView.PointerTrackerParams.DEFAULT); 178160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka } 17993246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka 180160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka public static void setParameters(LatinKeyboardView.PointerTrackerParams params) { 181160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka sParams = params; 1825c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka sTouchNoiseThresholdDistanceSquared = (int)( 183160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka params.mTouchNoiseThresholdDistance * params.mTouchNoiseThresholdDistance); 1846a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 1856a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 1865c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka public static PointerTracker getPointerTracker(final int id, KeyEventHandler handler) { 187b4fbbe57f574ce6e6a5827156f875fe7d3eb5089Tadashi G. Takaoka final ArrayList<PointerTracker> trackers = sTrackers; 1885c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka 1895c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka // Create pointer trackers until we can get 'id+1'-th tracker, if needed. 1905c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka for (int i = trackers.size(); i <= id; i++) { 1915c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka final PointerTracker tracker = new PointerTracker(i, handler); 1925c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka trackers.add(tracker); 1935c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } 1945c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka 1955c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka return trackers.get(id); 1965c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } 1975c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka 1985c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka public static boolean isAnyInSlidingKeyInput() { 1995c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka return sPointerTrackerQueue != null ? sPointerTrackerQueue.isAnyInSlidingKeyInput() : false; 2005c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } 2015c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka 2025c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka public static void setKeyboardActionListener(KeyboardActionListener listener) { 2035c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka for (final PointerTracker tracker : sTrackers) { 2045c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka tracker.mListener = listener; 2055c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } 206eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang GestureTracker.init(listener); 2075c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } 2085c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka 2095c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka public static void setKeyDetector(KeyDetector keyDetector) { 2105c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka for (final PointerTracker tracker : sTrackers) { 2115c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka tracker.setKeyDetectorInner(keyDetector); 2125c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka // Mark that keyboard layout has been changed. 2135c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka tracker.mKeyboardLayoutHasBeenChanged = true; 2145c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } 215eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang sGestureTracker.setKeyboard(keyDetector.getKeyboard()); 2165c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } 2175c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka 2185c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka public static void dismissAllKeyPreviews() { 2195c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka for (final PointerTracker tracker : sTrackers) { 220fe824948bb5c07dcd0a47221cb5b7b4f2f4365caTadashi G. Takaoka tracker.getKeyPreviewText().setVisibility(View.INVISIBLE); 221e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka tracker.setReleasedKeyGraphics(tracker.mCurrentKey); 2225c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } 2235c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka } 2245c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka 2255c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka public PointerTracker(int id, KeyEventHandler handler) { 2265c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka if (handler == null) 2275c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka throw new NullPointerException(); 2285c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka mPointerId = id; 2295c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka setKeyDetectorInner(handler.getKeyDetector()); 2305c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka mListener = handler.getKeyboardActionListener(); 2315c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka mDrawingProxy = handler.getDrawingProxy(); 2325c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka mTimerProxy = handler.getTimerProxy(); 2334692af50daefea9498faebeaa8d7e7a444afda4cTadashi G. Takaoka mKeyPreviewText = mDrawingProxy.inflateKeyPreviewText(); 2344692af50daefea9498faebeaa8d7e7a444afda4cTadashi G. Takaoka } 2354692af50daefea9498faebeaa8d7e7a444afda4cTadashi G. Takaoka 2364692af50daefea9498faebeaa8d7e7a444afda4cTadashi G. Takaoka public TextView getKeyPreviewText() { 2374692af50daefea9498faebeaa8d7e7a444afda4cTadashi G. Takaoka return mKeyPreviewText; 2386a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 2396a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 2401a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka // Returns true if keyboard has been changed by this callback. 2412a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key) { 242eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (sGestureTracker.isInGesture()) { 243eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang return false; 244eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } 245e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); 246e742436a29f46764441e83aaebf3ec25283bff1bTadashi G. Takaoka if (DEBUG_LISTENER) { 2477dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka Log.d(TAG, "onPress : " + KeyDetector.printableCode(key) 2482a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka + " ignoreModifier=" + ignoreModifierKey 249e742436a29f46764441e83aaebf3ec25283bff1bTadashi G. Takaoka + " enabled=" + key.isEnabled()); 250e742436a29f46764441e83aaebf3ec25283bff1bTadashi G. Takaoka } 25193246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka if (ignoreModifierKey) { 252996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka return false; 25393246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka } 254e7759091ddb5ec18268945d70d9212195bf6497bTadashi G. Takaoka if (key.isEnabled()) { 2552a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka mListener.onPressKey(key.mCode); 256690b1360bfda3cbaae896de65dcc3cd347dc8329Tadashi G. Takaoka final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged; 257690b1360bfda3cbaae896de65dcc3cd347dc8329Tadashi G. Takaoka mKeyboardLayoutHasBeenChanged = false; 2580f87ca72f7c569f7db075701767e504c75952182Tadashi G. Takaoka if (!key.altCodeWhileTyping() && !key.isModifier()) { 2590f87ca72f7c569f7db075701767e504c75952182Tadashi G. Takaoka mTimerProxy.startTypingStateTimer(); 2600f87ca72f7c569f7db075701767e504c75952182Tadashi G. Takaoka } 261690b1360bfda3cbaae896de65dcc3cd347dc8329Tadashi G. Takaoka return keyboardLayoutHasBeenChanged; 262690b1360bfda3cbaae896de65dcc3cd347dc8329Tadashi G. Takaoka } 263690b1360bfda3cbaae896de65dcc3cd347dc8329Tadashi G. Takaoka return false; 264dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka } 265dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka 266690b1360bfda3cbaae896de65dcc3cd347dc8329Tadashi G. Takaoka // Note that we need primaryCode argument because the keyboard may in shifted state and the 267690b1360bfda3cbaae896de65dcc3cd347dc8329Tadashi G. Takaoka // primaryCode is different from {@link Key#mCode}. 268ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok private void callListenerOnCodeInput(Key key, int primaryCode, int x, int y) { 269e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); 2706bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); 2716bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka final int code = altersCode ? key.mAltCode : primaryCode; 2722013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka if (DEBUG_LISTENER) { 2738cab0b56eb8db311f158b18a361d9ceb85cff482Tadashi G. Takaoka Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code) + " text=" + key.mOutputText 274ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok + " x=" + x + " y=" + y 2756bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode 276e742436a29f46764441e83aaebf3ec25283bff1bTadashi G. Takaoka + " enabled=" + key.isEnabled()); 2772013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 2789bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 2799bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge ResearchLogger.pointerTracker_callListenerOnCodeInput(key, x, y, ignoreModifierKey, 2809bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge altersCode, code); 2819bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge } 282e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka if (ignoreModifierKey) { 283996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka return; 284e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka } 2856bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state. 2866bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka if (key.isEnabled() || altersCode) { 2878cab0b56eb8db311f158b18a361d9ceb85cff482Tadashi G. Takaoka if (code == Keyboard.CODE_OUTPUT_TEXT) { 2888cab0b56eb8db311f158b18a361d9ceb85cff482Tadashi G. Takaoka mListener.onTextInput(key.mOutputText); 2898cab0b56eb8db311f158b18a361d9ceb85cff482Tadashi G. Takaoka } else if (code != Keyboard.CODE_UNSPECIFIED) { 290ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok mListener.onCodeInput(code, x, y); 2912013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 29293246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka } 293dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka } 294dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka 295690b1360bfda3cbaae896de65dcc3cd347dc8329Tadashi G. Takaoka // Note that we need primaryCode argument because the keyboard may in shifted state and the 296690b1360bfda3cbaae896de65dcc3cd347dc8329Tadashi G. Takaoka // primaryCode is different from {@link Key#mCode}. 297e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka private void callListenerOnRelease(Key key, int primaryCode, boolean withSliding) { 298eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (sGestureTracker.isInGesture()) { 299eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang return; 300eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } 301e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); 302e742436a29f46764441e83aaebf3ec25283bff1bTadashi G. Takaoka if (DEBUG_LISTENER) { 3037dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka Log.d(TAG, "onRelease : " + Keyboard.printableCode(primaryCode) 304e742436a29f46764441e83aaebf3ec25283bff1bTadashi G. Takaoka + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey 305e742436a29f46764441e83aaebf3ec25283bff1bTadashi G. Takaoka + " enabled="+ key.isEnabled()); 306e742436a29f46764441e83aaebf3ec25283bff1bTadashi G. Takaoka } 3079bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 3089bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge ResearchLogger.pointerTracker_callListenerOnRelease(key, primaryCode, withSliding, 3099bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge ignoreModifierKey); 3109bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge } 311e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka if (ignoreModifierKey) { 312996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka return; 313e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka } 31493246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka if (key.isEnabled()) { 3152a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka mListener.onReleaseKey(primaryCode, withSliding); 31693246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka } 317dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka } 318dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka 3198aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka private void callListenerOnCancelInput() { 320dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka if (DEBUG_LISTENER) 3218aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka Log.d(TAG, "onCancelInput"); 3229bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 3239bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge ResearchLogger.pointerTracker_callListenerOnCancelInput(); 3249bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge } 3258aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka mListener.onCancelInput(); 326dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka } 327dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka 32846286874f30c4a6ef44646c4e4adf36fe55c74b9Tadashi G. Takaoka private void setKeyDetectorInner(KeyDetector keyDetector) { 329a19b84dcf65bd70caa0fc72089cfe043b023a898Tadashi G. Takaoka mKeyDetector = keyDetector; 3305a7a696aff6718d4e0250c394a9d01cbf2a16916Tadashi G. Takaoka mKeyboard = keyDetector.getKeyboard(); 3318a092b4ede02b79422deae51f0a416b034777fb3Tadashi G. Takaoka final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY); 3328a092b4ede02b79422deae51f0a416b034777fb3Tadashi G. Takaoka if (newKey != mCurrentKey) { 3338a092b4ede02b79422deae51f0a416b034777fb3Tadashi G. Takaoka if (mDrawingProxy != null) { 3348a092b4ede02b79422deae51f0a416b034777fb3Tadashi G. Takaoka setReleasedKeyGraphics(mCurrentKey); 3358a092b4ede02b79422deae51f0a416b034777fb3Tadashi G. Takaoka } 3368a092b4ede02b79422deae51f0a416b034777fb3Tadashi G. Takaoka mCurrentKey = newKey; 3378a092b4ede02b79422deae51f0a416b034777fb3Tadashi G. Takaoka } 3388da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka final int keyQuarterWidth = mKeyboard.mMostCommonKeyWidth / 4; 339faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth; 3405a7a696aff6718d4e0250c394a9d01cbf2a16916Tadashi G. Takaoka } 3415a7a696aff6718d4e0250c394a9d01cbf2a16916Tadashi G. Takaoka 342cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka public boolean isInSlidingKeyInput() { 343cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka return mIsInSlidingKeyInput; 344cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 345cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka 346e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka public Key getKey() { 347e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka return mCurrentKey; 348dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka } 349dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka 3502aa8078df86029dab394d8dd616f4f6decb39035Tadashi G. Takaoka public boolean isModifier() { 351e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka return mCurrentKey != null && mCurrentKey.isModifier(); 3522aa8078df86029dab394d8dd616f4f6decb39035Tadashi G. Takaoka } 3532aa8078df86029dab394d8dd616f4f6decb39035Tadashi G. Takaoka 354e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka public Key getKeyOn(int x, int y) { 355723aaa2eebcfea0d285f11fc265941057332664dTadashi G. Takaoka return mKeyDetector.detectHitKey(x, y); 3562aa8078df86029dab394d8dd616f4f6decb39035Tadashi G. Takaoka } 3572aa8078df86029dab394d8dd616f4f6decb39035Tadashi G. Takaoka 358e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private void setReleasedKeyGraphics(Key key) { 359d3002aa8cd5339d59123e0c96174f6701e2c72ccTadashi G. Takaoka mDrawingProxy.dismissKeyPreview(this); 3606bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka if (key == null) { 361faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka return; 362faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka } 363faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka 3646bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka // Even if the key is disabled, update the key release graphics just in case. 365faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka updateReleaseKeyGraphics(key); 366faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka 367faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka if (key.isShift()) { 368faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka for (final Key shiftKey : mKeyboard.mShiftKeys) { 369faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka if (shiftKey != key) { 370faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka updateReleaseKeyGraphics(shiftKey); 3712013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 3722013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 373faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka } 3742013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka 375faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka if (key.altCodeWhileTyping()) { 376faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka final int altCode = key.mAltCode; 377faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka final Key altKey = mKeyboard.getKey(altCode); 378faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka if (altKey != null) { 379faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka updateReleaseKeyGraphics(altKey); 380faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka } 381faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) { 382faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka if (k != key && k.mAltCode == altCode) { 383faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka updateReleaseKeyGraphics(k); 3842013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 3852013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 3866a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 3876a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 3886a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 389e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private void setPressedKeyGraphics(Key key) { 3906bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka if (key == null) { 3916bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka return; 3926bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka } 3936bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka 3946bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state. 3956bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); 3966bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka final boolean needsToUpdateGraphics = key.isEnabled() || altersCode; 3976bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka if (!needsToUpdateGraphics) { 398faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka return; 399faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka } 400faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka 401eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (!key.noKeyPreview() && !sGestureTracker.isInGesture()) { 402faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka mDrawingProxy.showKeyPreview(this); 403faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka } 404faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka updatePressKeyGraphics(key); 405faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka 406faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka if (key.isShift()) { 407faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka for (final Key shiftKey : mKeyboard.mShiftKeys) { 408faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka if (shiftKey != key) { 409faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka updatePressKeyGraphics(shiftKey); 4102013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 4112013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 412faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka } 4132013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka 41473a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka if (key.altCodeWhileTyping() && mTimerProxy.isTypingState()) { 415faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka final int altCode = key.mAltCode; 416faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka final Key altKey = mKeyboard.getKey(altCode); 417faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka if (altKey != null) { 418faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka updatePressKeyGraphics(altKey); 419faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka } 420faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) { 421faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka if (k != key && k.mAltCode == altCode) { 422faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka updatePressKeyGraphics(k); 4232013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 4242013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 425d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6Tadashi G. Takaoka } 426c5d33b16521de56ad01b0b6308217efb009078b7Tadashi G. Takaoka } 427c5d33b16521de56ad01b0b6308217efb009078b7Tadashi G. Takaoka 428faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka private void updateReleaseKeyGraphics(Key key) { 429faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka key.onReleased(); 430faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka mDrawingProxy.invalidateKey(key); 431faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka } 432faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka 433faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka private void updatePressKeyGraphics(Key key) { 434faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka key.onPressed(); 435faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka mDrawingProxy.invalidateKey(key); 436faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka } 437faad353feabef17e3bea6d5d9b4cb8bacf94788cTadashi G. Takaoka 4388a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka public int getLastX() { 4398a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka return mLastX; 4408a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka } 4418a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka 4428a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka public int getLastY() { 4438a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka return mLastY; 4448a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka } 4458a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka 4468a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka public long getDownTime() { 4478a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka return mDownTime; 4488a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka } 4498a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka 450e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private Key onDownKey(int x, int y, long eventTime) { 4518a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka mDownTime = eventTime; 4528a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka return onMoveToNewKey(onMoveKeyInternal(x, y), x, y); 4538a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka } 4548a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka 455e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private Key onMoveKeyInternal(int x, int y) { 4568a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka mLastX = x; 4578a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka mLastY = y; 458723aaa2eebcfea0d285f11fc265941057332664dTadashi G. Takaoka return mKeyDetector.detectHitKey(x, y); 4598a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka } 4608a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka 461e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private Key onMoveKey(int x, int y) { 4628a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka return onMoveKeyInternal(x, y); 4638a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka } 4648a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka 465e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private Key onMoveToNewKey(Key newKey, int x, int y) { 466e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka mCurrentKey = newKey; 4678a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka mKeyX = x; 4688a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka mKeyY = y; 469e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka return newKey; 4708a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka } 4718a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka 4728ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka public void processMotionEvent(int action, int x, int y, long eventTime, 4738ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka KeyEventHandler handler) { 4748ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka switch (action) { 4758ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka case MotionEvent.ACTION_DOWN: 4768ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka case MotionEvent.ACTION_POINTER_DOWN: 4778ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka onDownEvent(x, y, eventTime, handler); 4788ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka break; 4798ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka case MotionEvent.ACTION_UP: 4808ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka case MotionEvent.ACTION_POINTER_UP: 4818ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka onUpEvent(x, y, eventTime); 4828ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka break; 4838ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka case MotionEvent.ACTION_MOVE: 4843314d38dafc0b9670e695a194c74950c4ebf2b3dTadashi G. Takaoka onMoveEvent(x, y, eventTime, null); 4858ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka break; 4868ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka case MotionEvent.ACTION_CANCEL: 4878ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka onCancelEvent(x, y, eventTime); 4888ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka break; 4898ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka } 4908ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka } 4918ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka 492f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka public void onDownEvent(int x, int y, long eventTime, KeyEventHandler handler) { 493dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka if (DEBUG_EVENT) 494dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka printTouchEvent("onDownEvent:", x, y, eventTime); 4951d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka 496f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka mDrawingProxy = handler.getDrawingProxy(); 49763c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka mTimerProxy = handler.getTimerProxy(); 498f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka setKeyboardActionListener(handler.getKeyboardActionListener()); 499f426cdd5c62452224ac4bb833c3ccf7b26d1a2a8Tadashi G. Takaoka setKeyDetectorInner(handler.getKeyDetector()); 500baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka // Naive up-to-down noise filter. 5018a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka final long deltaT = eventTime - mUpTime; 502160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka if (deltaT < sParams.mTouchNoiseThresholdTime) { 5038a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka final int dx = x - mLastX; 5048a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka final int dy = y - mLastY; 505baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka final int distanceSquared = (dx * dx + dy * dy); 5065c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka if (distanceSquared < sTouchNoiseThresholdDistanceSquared) { 507faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka if (DEBUG_MODE) 508faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka Log.w(TAG, "onDownEvent: ignore potential noise: time=" + deltaT 509faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka + " distance=" + distanceSquared); 5109bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 5119bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge ResearchLogger.pointerTracker_onDownEvent(deltaT, distanceSquared); 5129bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge } 513d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6Tadashi G. Takaoka mKeyAlreadyProcessed = true; 514baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka return; 515baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka } 516baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka } 517baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka 5185c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka final PointerTrackerQueue queue = sPointerTrackerQueue; 519eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang final Key key = getKeyOn(x, y); 5201d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka if (queue != null) { 521e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka if (key != null && key.isModifier()) { 5221d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka // Before processing a down event of modifier key, all pointers already being 5231d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka // tracked should be released. 5241d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka queue.releaseAllPointers(eventTime); 5251d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka } 5261d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka queue.add(this); 5271d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka } 5281d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka onDownEventInternal(x, y, eventTime); 529eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (queue != null && queue.size() == 1) { 530eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang sGestureTracker.onDownEvent(this, x, y, eventTime, key); 531eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } 5321d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka } 5331d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka 534baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka private void onDownEventInternal(int x, int y, long eventTime) { 535e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka Key key = onDownKey(x, y, eventTime); 53667a4ecacc7525c9343cded13fc93e9a2381ea2d8Tadashi G. Takaoka // Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding 53732572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka // from modifier key, or 3) this pointer's KeyDetector always allows sliding input. 538160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka mIsAllowedSlidingKeyInput = sParams.mSlidingKeyInputEnabled 539c9f203805ca23276fcdcdc79b9298bc1d413ad98Tadashi G. Takaoka || (key != null && key.isModifier()) 54032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka || mKeyDetector.alwaysAllowsSlidingInput(); 5411a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka mKeyboardLayoutHasBeenChanged = false; 542c5d33b16521de56ad01b0b6308217efb009078b7Tadashi G. Takaoka mKeyAlreadyProcessed = false; 543cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka mIsInSlidingKeyInput = false; 544996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka mIgnoreModifierKey = false; 545e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka if (key != null) { 5461a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka // This onPress call may have changed keyboard layout. Those cases are detected at 547e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka // {@link #setKeyboard}. In those cases, we should update key according to the new 5481a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka // keyboard layout. 5492a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { 550e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka key = onDownKey(x, y, eventTime); 551e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka } 552996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka 553e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka startRepeatKey(key); 554e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka startLongPressTimer(key); 555e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka setPressedKeyGraphics(key); 5566a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 5576a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 5586a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 559996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka private void startSlidingKeyInput(Key key) { 560e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka if (!mIsInSlidingKeyInput) { 561e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka mIgnoreModifierKey = key.isModifier(); 562e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka } 563996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka mIsInSlidingKeyInput = true; 564996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka } 565996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka 5663314d38dafc0b9670e695a194c74950c4ebf2b3dTadashi G. Takaoka public void onMoveEvent(int x, int y, long eventTime, MotionEvent me) { 567dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka if (DEBUG_MOVE_EVENT) 568dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka printTouchEvent("onMoveEvent:", x, y, eventTime); 569e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka if (mKeyAlreadyProcessed) 570e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka return; 571baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka 572eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (me != null) { 573eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang // Add historical points to gesture path. 574eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang final int pointerIndex = me.findPointerIndex(mPointerId); 575eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang final int historicalSize = me.getHistorySize(); 576eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang for (int h = 0; h < historicalSize; h++) { 577eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang final int historicalX = (int)me.getHistoricalX(pointerIndex, h); 578eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang final int historicalY = (int)me.getHistoricalY(pointerIndex, h); 579eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang final long historicalTime = me.getHistoricalEventTime(h); 580eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang sGestureTracker.onMoveEvent(this, historicalX, historicalY, historicalTime, 581eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang true /* isHistorical */, null); 582eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } 583eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } 584eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang 5858a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka final int lastX = mLastX; 5868a995157f37365cf79b893e9106d1830d70c39dcTadashi G. Takaoka final int lastY = mLastY; 587e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka final Key oldKey = mCurrentKey; 588e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka Key key = onMoveKey(x, y); 589eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang 590eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang // Register move event on gesture tracker. 591eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang sGestureTracker.onMoveEvent(this, x, y, eventTime, false, key); 592eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (sGestureTracker.isInGesture()) { 593eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang mIgnoreModifierKey = true; 594eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang mTimerProxy.cancelLongPressTimer(); 595eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang mIsInSlidingKeyInput = true; 596eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang mCurrentKey = null; 597eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang setReleasedKeyGraphics(oldKey); 598eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } 599eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang 600e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka if (key != null) { 601c0b5c9c43e5eb7a6ed768d56f462ca9ed5c5f913Tadashi G. Takaoka if (oldKey == null) { 6029e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // The pointer has been slid in to the new key, but the finger was not on any keys. 6039e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // In this case, we must call onPress() to notify that the new key is being pressed. 6041a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka // This onPress call may have changed keyboard layout. Those cases are detected at 605e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka // {@link #setKeyboard}. In those cases, we should update key according to the 6061a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka // new keyboard layout. 6072a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { 608e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka key = onMoveKey(x, y); 609e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka } 610e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka onMoveToNewKey(key, x, y); 611e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka startLongPressTimer(key); 612e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka setPressedKeyGraphics(key); 613e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka } else if (isMajorEnoughMoveToBeOnNewKey(x, y, key)) { 6149e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // The pointer has been slid in to the new key from the previous key, we must call 6159e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // onRelease() first to notify that the previous key has been released, then call 6169e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // onPress() to notify that the new key is being pressed. 617e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka setReleasedKeyGraphics(oldKey); 618e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka callListenerOnRelease(oldKey, oldKey.mCode, true); 619996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka startSlidingKeyInput(oldKey); 6202321caa1f9eb6c2d616bc36f11f5b48eebf144feTadashi G. Takaoka mTimerProxy.cancelKeyTimers(); 621e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka startRepeatKey(key); 62267a4ecacc7525c9343cded13fc93e9a2381ea2d8Tadashi G. Takaoka if (mIsAllowedSlidingKeyInput) { 6231a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka // This onPress call may have changed keyboard layout. Those cases are detected 624e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka // at {@link #setKeyboard}. In those cases, we should update key according 6251a6fba570260ca9f837e5a6874274f39a3c0a734Tadashi G. Takaoka // to the new keyboard layout. 6262a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { 627e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka key = onMoveKey(x, y); 628e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka } 629e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka onMoveToNewKey(key, x, y); 630e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka startLongPressTimer(key); 631e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka setPressedKeyGraphics(key); 63267a4ecacc7525c9343cded13fc93e9a2381ea2d8Tadashi G. Takaoka } else { 633faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka // HACK: On some devices, quick successive touches may be translated to sudden 634faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka // move by touch panel firmware. This hack detects the case and translates the 635faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka // move event to successive up and down events. 636faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka final int dx = x - lastX; 637faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka final int dy = y - lastY; 638faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka final int lastMoveSquared = dx * dx + dy * dy; 639d438fcaca2a35ace4fee5b7a469596bfe2d1b025Tadashi G. Takaoka if (sNeedsPhantomSuddenMoveEventHack 640d438fcaca2a35ace4fee5b7a469596bfe2d1b025Tadashi G. Takaoka && lastMoveSquared >= mKeyQuarterWidthSquared) { 641d438fcaca2a35ace4fee5b7a469596bfe2d1b025Tadashi G. Takaoka if (DEBUG_MODE) { 642d438fcaca2a35ace4fee5b7a469596bfe2d1b025Tadashi G. Takaoka Log.w(TAG, String.format("onMoveEvent:" 643d438fcaca2a35ace4fee5b7a469596bfe2d1b025Tadashi G. Takaoka + " phantom sudden move event is translated to " 644faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y)); 645d438fcaca2a35ace4fee5b7a469596bfe2d1b025Tadashi G. Takaoka } 6469bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 6479bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY); 6489bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge } 649eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang onUpEventInternal(x, y, eventTime); 650faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka onDownEventInternal(x, y, eventTime); 651faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka } else { 6525e06b8534ffdf5099d2ef4551b113a103cdf7061Tadashi G. Takaoka // HACK: If there are currently multiple touches, register the key even if 6535e06b8534ffdf5099d2ef4551b113a103cdf7061Tadashi G. Takaoka // the finger slides off the key. This defends against noise from some 6545e06b8534ffdf5099d2ef4551b113a103cdf7061Tadashi G. Takaoka // touch panels when there are close multiple touches. 6555e06b8534ffdf5099d2ef4551b113a103cdf7061Tadashi G. Takaoka // Caveat: When in chording input mode with a modifier key, we don't use 6565e06b8534ffdf5099d2ef4551b113a103cdf7061Tadashi G. Takaoka // this hack. 6575e06b8534ffdf5099d2ef4551b113a103cdf7061Tadashi G. Takaoka if (me != null && me.getPointerCount() > 1 6585e06b8534ffdf5099d2ef4551b113a103cdf7061Tadashi G. Takaoka && !sPointerTrackerQueue.hasModifierKeyOlderThan(this)) { 659eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang onUpEventInternal(x, y, eventTime); 6605e06b8534ffdf5099d2ef4551b113a103cdf7061Tadashi G. Takaoka } 661d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6Tadashi G. Takaoka mKeyAlreadyProcessed = true; 662e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka setReleasedKeyGraphics(oldKey); 663faf437b5078e882b630706cd315c335f204ab861Tadashi G. Takaoka } 66467a4ecacc7525c9343cded13fc93e9a2381ea2d8Tadashi G. Takaoka } 665c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka } 6666a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } else { 667e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, key)) { 6689e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // The pointer has been slid out from the previous key, we must call onRelease() to 6699e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // notify that the previous key has been released. 670e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka setReleasedKeyGraphics(oldKey); 671e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka callListenerOnRelease(oldKey, oldKey.mCode, true); 672996db15d3c018ed2a7b4eee96ea94b9f80d8e379Tadashi G. Takaoka startSlidingKeyInput(oldKey); 67398b5c982b93cbfc74b221af30079ecb69dd4e0a1Tadashi G. Takaoka mTimerProxy.cancelLongPressTimer(); 67467a4ecacc7525c9343cded13fc93e9a2381ea2d8Tadashi G. Takaoka if (mIsAllowedSlidingKeyInput) { 675e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka onMoveToNewKey(key, x, y); 67667a4ecacc7525c9343cded13fc93e9a2381ea2d8Tadashi G. Takaoka } else { 677d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6Tadashi G. Takaoka mKeyAlreadyProcessed = true; 67867a4ecacc7525c9343cded13fc93e9a2381ea2d8Tadashi G. Takaoka } 67907221a4ad11fa5ae6275c107f1f86260691bd505Tadashi G. Takaoka } 6806a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 6816a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 6826a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 683906f03121b6c6a795f35dbc24d2eceac0665f35fTadashi G. Takaoka public void onUpEvent(int x, int y, long eventTime) { 684dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka if (DEBUG_EVENT) 685dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka printTouchEvent("onUpEvent :", x, y, eventTime); 6861d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka 6875c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka final PointerTrackerQueue queue = sPointerTrackerQueue; 6881d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka if (queue != null) { 689eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (!sGestureTracker.isInGesture()) { 690eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (mCurrentKey != null && mCurrentKey.isModifier()) { 691eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang // Before processing an up event of modifier key, all pointers already being 692eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang // tracked should be released. 693eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang queue.releaseAllPointersExcept(this, eventTime); 694eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } else { 695eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang queue.releaseAllPointersOlderThan(this, eventTime); 696eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } 6971d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka } 6981d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka queue.remove(this); 6991d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka } 700eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang onUpEventInternal(x, y, eventTime); 7011d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka } 7021d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka 703d9786ce2e389c8c02af7773b53b5c44fe4fa0b0cTadashi G. Takaoka // Let this pointer tracker know that one of newer-than-this pointer trackers got an up event. 704d9786ce2e389c8c02af7773b53b5c44fe4fa0b0cTadashi G. Takaoka // This pointer tracker needs to keep the key top graphics "pressed", but needs to get a 705d9786ce2e389c8c02af7773b53b5c44fe4fa0b0cTadashi G. Takaoka // "virtual" up event. 706d3002aa8cd5339d59123e0c96174f6701e2c72ccTadashi G. Takaoka public void onPhantomUpEvent(int x, int y, long eventTime) { 707c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka if (DEBUG_EVENT) 708c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka printTouchEvent("onPhntEvent:", x, y, eventTime); 709eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang onUpEventInternal(x, y, eventTime); 710d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6Tadashi G. Takaoka mKeyAlreadyProcessed = true; 7111d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka } 7121d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka 713eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang private void onUpEventInternal(int x, int y, long eventTime) { 7142321caa1f9eb6c2d616bc36f11f5b48eebf144feTadashi G. Takaoka mTimerProxy.cancelKeyTimers(); 715cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka mIsInSlidingKeyInput = false; 7165a40dcaf8b6250eeea241471e54e8fe856cdf19bTadashi G. Takaoka // Release the last pressed key. 7175a40dcaf8b6250eeea241471e54e8fe856cdf19bTadashi G. Takaoka setReleasedKeyGraphics(mCurrentKey); 7189d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka if (mIsShowingMoreKeysPanel) { 7199d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka mDrawingProxy.dismissMoreKeysPanel(); 7209d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka mIsShowingMoreKeysPanel = false; 7219ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka } 722eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang 723eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (sGestureTracker.isInGesture()) { 724eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang // Register up event on gesture tracker. 725eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang sGestureTracker.onUpEvent(this, x, y, eventTime); 726eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (!sPointerTrackerQueue.isAnyInSlidingKeyInput()) { 727eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang // TODO: Calls to beginBatchInput() is missing in this class. Reorganize the code. 728eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang sGestureTracker.endBatchInput(); 729eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } 730eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (mCurrentKey != null) { 731eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang callListenerOnRelease(mCurrentKey, mCurrentKey.mCode, true); 732eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } 733eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang mCurrentKey = null; 734eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang return; 735eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } else { 736eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang // TODO: Calls to beginBatchInput() is missing in this class. Reorganize the code. 737eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang sGestureTracker.endBatchInput(); 738eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang } 739eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang 740d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6Tadashi G. Takaoka if (mKeyAlreadyProcessed) 741d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6Tadashi G. Takaoka return; 7420d9d37cec2b3c4b4c3747baeb529bd2a70cbafb8Tadashi G. Takaoka if (mCurrentKey != null && !mCurrentKey.isRepeatable()) { 7435a40dcaf8b6250eeea241471e54e8fe856cdf19bTadashi G. Takaoka detectAndSendKey(mCurrentKey, mKeyX, mKeyY); 7446a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 7456a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 7466a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 747e51d164482c7896892d6eccb80f1e1e6fe6d50dbTadashi G. Takaoka public void onShowMoreKeysPanel(int x, int y, KeyEventHandler handler) { 7489ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka onLongPressed(); 749e51d164482c7896892d6eccb80f1e1e6fe6d50dbTadashi G. Takaoka onDownEvent(x, y, SystemClock.uptimeMillis(), handler); 7509d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka mIsShowingMoreKeysPanel = true; 751eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang // TODO: Calls to beginBatchInput() is missing in this class. Reorganize the code. 752eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang sGestureTracker.abortBatchInput(); 7539ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka } 7549ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka 755906f03121b6c6a795f35dbc24d2eceac0665f35fTadashi G. Takaoka public void onLongPressed() { 756d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6Tadashi G. Takaoka mKeyAlreadyProcessed = true; 757e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka setReleasedKeyGraphics(mCurrentKey); 7585c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka final PointerTrackerQueue queue = sPointerTrackerQueue; 7591ddb4897fee79ec00c68e4a255e653568477a995Tadashi G. Takaoka if (queue != null) { 760d00d963b9d47c1bba6f65534033a33fe7c30dde5Tadashi G. Takaoka queue.remove(this); 7611ddb4897fee79ec00c68e4a255e653568477a995Tadashi G. Takaoka } 762d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6Tadashi G. Takaoka } 763d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6Tadashi G. Takaoka 764906f03121b6c6a795f35dbc24d2eceac0665f35fTadashi G. Takaoka public void onCancelEvent(int x, int y, long eventTime) { 765dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka if (DEBUG_EVENT) 766dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka printTouchEvent("onCancelEvt:", x, y, eventTime); 7671d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka 7685c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka final PointerTrackerQueue queue = sPointerTrackerQueue; 769c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka if (queue != null) { 770d3002aa8cd5339d59123e0c96174f6701e2c72ccTadashi G. Takaoka queue.releaseAllPointersExcept(this, eventTime); 7711d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka queue.remove(this); 772c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka } 773baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka onCancelEventInternal(); 7741d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka } 7751d7d9664a9850a7c8043651e4b7a055ec034f571Tadashi G. Takaoka 776baf83886be975d804eda3e1519b7255026e5163eTadashi G. Takaoka private void onCancelEventInternal() { 7772321caa1f9eb6c2d616bc36f11f5b48eebf144feTadashi G. Takaoka mTimerProxy.cancelKeyTimers(); 778e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka setReleasedKeyGraphics(mCurrentKey); 779cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka mIsInSlidingKeyInput = false; 7809d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka if (mIsShowingMoreKeysPanel) { 7819d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka mDrawingProxy.dismissMoreKeysPanel(); 7829d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka mIsShowingMoreKeysPanel = false; 7839ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka } 7846a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 7856a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 786e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private void startRepeatKey(Key key) { 787eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (key != null && key.isRepeatable() && !sGestureTracker.isInGesture()) { 7886662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv onRegisterKey(key); 789a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka mTimerProxy.startKeyRepeatTimer(this); 790a0537fb4c73dff8beecc328720830af9719d0277Tadashi G. Takaoka } 791a0537fb4c73dff8beecc328720830af9719d0277Tadashi G. Takaoka } 792a0537fb4c73dff8beecc328720830af9719d0277Tadashi G. Takaoka 7936662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv public void onRegisterKey(Key key) { 794c6df09182cac288c9a4de2cc05628dac6b6db41eTadashi G. Takaoka if (key != null) { 795e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka detectAndSendKey(key, key.mX, key.mY); 7960f87ca72f7c569f7db075701767e504c75952182Tadashi G. Takaoka if (!key.altCodeWhileTyping() && !key.isModifier()) { 7970f87ca72f7c569f7db075701767e504c75952182Tadashi G. Takaoka mTimerProxy.startTypingStateTimer(); 7980f87ca72f7c569f7db075701767e504c75952182Tadashi G. Takaoka } 799c6df09182cac288c9a4de2cc05628dac6b6db41eTadashi G. Takaoka } 8006a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 8016a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 802e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, Key newKey) { 803b4fbbe57f574ce6e6a5827156f875fe7d3eb5089Tadashi G. Takaoka if (mKeyDetector == null) 804a19b84dcf65bd70caa0fc72089cfe043b023a898Tadashi G. Takaoka throw new NullPointerException("keyboard and/or key detector not set"); 805e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka Key curKey = mCurrentKey; 8066a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka if (newKey == curKey) { 807e6cb8fc234940700ae97af787e62962a98d332e5Tadashi G. Takaoka return false; 808e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka } else if (curKey != null) { 809e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka return curKey.squaredDistanceToEdge(x, y) 810a19b84dcf65bd70caa0fc72089cfe043b023a898Tadashi G. Takaoka >= mKeyDetector.getKeyHysteresisDistanceSquared(); 8116a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } else { 812e6cb8fc234940700ae97af787e62962a98d332e5Tadashi G. Takaoka return true; 8136a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 8146a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 8156a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 816e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private void startLongPressTimer(Key key) { 817eea34598bf63f670f47d7b3f37b6436921e5fe02Tom Ouyang if (key != null && key.isLongPressEnabled() && !sGestureTracker.isInGesture()) { 818a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka mTimerProxy.startLongPressTimer(this); 8194189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 82066e306d01c6820d4f4d8b2209438ec086b48ac51Tadashi G. Takaoka } 82166e306d01c6820d4f4d8b2209438ec086b48ac51Tadashi G. Takaoka 822e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private void detectAndSendKey(Key key, int x, int y) { 82383e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka if (key == null) { 8248aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka callListenerOnCancelInput(); 825dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka return; 826dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka } 82766e306d01c6820d4f4d8b2209438ec086b48ac51Tadashi G. Takaoka 8282013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka int code = key.mCode; 829ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok callListenerOnCodeInput(key, code, x, y); 8302013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka callListenerOnRelease(key, code, false); 8316a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka } 8326a1514a0deac7f3d8ec33430403b2caea05bc8b9Tadashi G. Takaoka 833dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka private void printTouchEvent(String title, int x, int y, long eventTime) { 834723aaa2eebcfea0d285f11fc265941057332664dTadashi G. Takaoka final Key key = mKeyDetector.detectHitKey(x, y); 835e742436a29f46764441e83aaebf3ec25283bff1bTadashi G. Takaoka final String code = KeyDetector.printableCode(key); 836e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka Log.d(TAG, String.format("%s%s[%d] %4d %4d %5d %s", title, 837d7edd1cbb5dfacacdd39766e379fb60d2b7c6b73Tadashi G. Takaoka (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, eventTime, code)); 838dbc44989a5be68679c889ae45cde17002b748fdaTadashi G. Takaoka } 8396e5a3986854549a45c95770b5a88ae5577e93299Tadashi G. Takaoka} 840