SuddenJumpingTouchEventHandler.java revision 5a309f57155fb95667c2ccdda730eaf175de8876
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/* 2443c360d0afdbab091994244f045f4756feaf2b4Jean-Baptiste Queru * Copyright (C) 2008 The Android Open Source Project 35a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * 4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of 6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at 75a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * 8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 95a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * 10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under 14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License. 15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 175a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokapackage com.android.inputmethod.keyboard; 18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 195a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinIMEUtil; 201fb28137f43ae083c773c32440981ac61e83fa5dsatokimport com.android.inputmethod.voice.VoiceIMEConnector; 214fc510a7890976d9968d73ceacf3983e77f489d2satok 22923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context; 23923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.graphics.Canvas; 241b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasaniimport android.graphics.Paint; 25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Handler; 26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message; 27923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock; 2875c23ced94979a6b3f7c59e95dd46385e9702e2dKen Wakasaimport android.text.TextUtils; 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.AttributeSet; 30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.MotionEvent; 31d2a431efa726771dee5c7b90004a0ed670d9a129Tadashi G. Takaoka 32d2a431efa726771dee5c7b90004a0ed670d9a129Tadashi G. Takaokaimport java.util.List; 33923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 345a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokapublic class LatinKeyboardView extends KeyboardView { 358eb2e34d5b2def57c9548f88e37e5c9e5a0bea59Amith Yamasani 360fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani /** Whether we've started dropping move events because we found a big jump */ 370fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani private boolean mDroppingEvents; 38e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka /** 39d2a431efa726771dee5c7b90004a0ed670d9a129Tadashi G. Takaoka * Whether multi-touch disambiguation needs to be disabled if a real multi-touch event has 40d2a431efa726771dee5c7b90004a0ed670d9a129Tadashi G. Takaoka * occured 410fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani */ 420fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani private boolean mDisableDisambiguation; 430fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani /** The distance threshold at which we start treating the touch session as a multi-touch */ 440fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani private int mJumpThresholdSquare = Integer.MAX_VALUE; 453e0c82ec80a69c4adbd60546c3c56c83c43ec7ebAmith Yamasani /** The y coordinate of the last row */ 463e0c82ec80a69c4adbd60546c3c56c83c43ec7ebAmith Yamasani private int mLastRowY; 473f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani 48923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public LatinKeyboardView(Context context, AttributeSet attrs) { 49a1cc4f0a8d9a70ff1515d1ddb1476f6ce630afe2Tadashi G. Takaoka this(context, attrs, 0); 50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 51923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 52923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) { 53923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super(context, attrs, defStyle); 54923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 55230cd6f7f27300e2688b5e5a22a5361f446b80e7Amith Yamasani 56923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 573a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka public void setPreviewEnabled(boolean previewEnabled) { 582c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 592c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka if (latinKeyboard != null 602c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka && (latinKeyboard.isPhoneKeyboard() || latinKeyboard.isNumberKeyboard())) { 612c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka // Phone and number keyboard never shows popup preview (except language switch). 623a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka super.setPreviewEnabled(false); 633a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka } else { 643a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka super.setPreviewEnabled(previewEnabled); 653a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka } 663a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka } 673a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka 680ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa public void setLatinKeyboard(LatinKeyboard k) { 690fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani super.setKeyboard(k); 700fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // One-seventh of the keyboard width seems like a reasonable threshold 710fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani mJumpThresholdSquare = k.getMinWidth() / 7; 720fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani mJumpThresholdSquare *= mJumpThresholdSquare; 733e0c82ec80a69c4adbd60546c3c56c83c43ec7ebAmith Yamasani // Assuming there are 4 rows, this is the coordinate of the last row 743e0c82ec80a69c4adbd60546c3c56c83c43ec7ebAmith Yamasani mLastRowY = (k.getHeight() * 3) / 4; 750fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani setKeyboardLocal(k); 760fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani } 770fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani 780ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa public LatinKeyboard getLatinKeyboard() { 795a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka Keyboard keyboard = getKeyboard(); 800ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa if (keyboard instanceof LatinKeyboard) { 810ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa return (LatinKeyboard)keyboard; 820ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa } else { 830ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa return null; 840ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa } 850ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa } 860ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa 870fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani @Override 88923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project protected boolean onLongPress(Key key) { 89e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka int primaryCode = key.codes[0]; 905a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka if (primaryCode == LatinKeyboard.KEYCODE_OPTIONS) { 915a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka return invokeOnKey(LatinKeyboard.KEYCODE_OPTIONS_LONGPRESS); 922c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } else if (primaryCode == '0' && getLatinKeyboard().isPhoneKeyboard()) { 93923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Long pressing on 0 in phone number keypad gives you a '+'. 94a1cc4f0a8d9a70ff1515d1ddb1476f6ce630afe2Tadashi G. Takaoka return invokeOnKey('+'); 95923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 96923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onLongPress(key); 97923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 98923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 99923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 100a1cc4f0a8d9a70ff1515d1ddb1476f6ce630afe2Tadashi G. Takaoka private boolean invokeOnKey(int primaryCode) { 101a1cc4f0a8d9a70ff1515d1ddb1476f6ce630afe2Tadashi G. Takaoka getOnKeyboardActionListener().onKey(primaryCode, null, 1025a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka KeyboardView.NOT_A_TOUCH_COORDINATE, 1035a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka KeyboardView.NOT_A_TOUCH_COORDINATE); 104a1cc4f0a8d9a70ff1515d1ddb1476f6ce630afe2Tadashi G. Takaoka return true; 105a1cc4f0a8d9a70ff1515d1ddb1476f6ce630afe2Tadashi G. Takaoka } 106a1cc4f0a8d9a70ff1515d1ddb1476f6ce630afe2Tadashi G. Takaoka 107979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 108979f8690967ff5409fe18f5085858ccdb8e0ccf1satok protected CharSequence adjustCase(CharSequence label) { 1090ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa LatinKeyboard keyboard = getLatinKeyboard(); 1100ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa if (keyboard.isAlphaKeyboard() 111f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka && keyboard.isShiftedOrShiftLocked() 11275c23ced94979a6b3f7c59e95dd46385e9702e2dKen Wakasa && !TextUtils.isEmpty(label) && label.length() < 3 113979f8690967ff5409fe18f5085858ccdb8e0ccf1satok && Character.isLowerCase(label.charAt(0))) { 114979f8690967ff5409fe18f5085858ccdb8e0ccf1satok label = label.toString().toUpperCase(); 115979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 116979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return label; 117979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 118979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1190fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani /** 1200fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani * This function checks to see if we need to handle any sudden jumps in the pointer location 1210fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani * that could be due to a multi-touch being treated as a move by the firmware or hardware. 1220fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani * Once a sudden jump is detected, all subsequent move events are discarded 1230fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani * until an UP is received.<P> 124e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka * When a sudden jump is detected, an UP event is simulated at the last position and when 1250fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani * the sudden moves subside, a DOWN event is simulated for the second key. 1260fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani * @param me the motion event 127e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka * @return true if the event was consumed, so that it doesn't continue to be handled by 1280fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani * KeyboardView. 1290fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani */ 1300fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani private boolean handleSuddenJump(MotionEvent me) { 1310fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani final int action = me.getAction(); 1320fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani final int x = (int) me.getX(); 1330fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani final int y = (int) me.getY(); 1340fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani boolean result = false; 1350fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani 1360fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // Real multi-touch event? Stop looking for sudden jumps 1370fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani if (me.getPointerCount() > 1) { 1380fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani mDisableDisambiguation = true; 1390fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani } 1400fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani if (mDisableDisambiguation) { 1410fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // If UP, reset the multi-touch flag 1420fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani if (action == MotionEvent.ACTION_UP) mDisableDisambiguation = false; 1430fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani return false; 1440fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani } 1450fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani 1460fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani switch (action) { 1470fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani case MotionEvent.ACTION_DOWN: 1480fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // Reset the "session" 1490fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani mDroppingEvents = false; 1500fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani mDisableDisambiguation = false; 1510fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani break; 1520fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani case MotionEvent.ACTION_MOVE: 1530fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // Is this a big jump? 1540fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani final int distanceSquare = (mLastX - x) * (mLastX - x) + (mLastY - y) * (mLastY - y); 1553e0c82ec80a69c4adbd60546c3c56c83c43ec7ebAmith Yamasani // Check the distance and also if the move is not entirely within the bottom row 1563e0c82ec80a69c4adbd60546c3c56c83c43ec7ebAmith Yamasani // If it's only in the bottom row, it might be an intentional slide gesture 1573e0c82ec80a69c4adbd60546c3c56c83c43ec7ebAmith Yamasani // for language switching 1583e0c82ec80a69c4adbd60546c3c56c83c43ec7ebAmith Yamasani if (distanceSquare > mJumpThresholdSquare 1593e0c82ec80a69c4adbd60546c3c56c83c43ec7ebAmith Yamasani && (mLastY < mLastRowY || y < mLastRowY)) { 1600fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // If we're not yet dropping events, start dropping and send an UP event 1610fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani if (!mDroppingEvents) { 1620fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani mDroppingEvents = true; 1630fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // Send an up event 1640fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(), 1650fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani MotionEvent.ACTION_UP, 1660fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani mLastX, mLastY, me.getMetaState()); 1670fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani super.onTouchEvent(translated); 1680fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani translated.recycle(); 1690fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani } 1700fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani result = true; 1710fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani } else if (mDroppingEvents) { 1720fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // If moves are small and we're already dropping events, continue dropping 1730fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani result = true; 1740fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani } 1750fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani break; 1760fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani case MotionEvent.ACTION_UP: 1770fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani if (mDroppingEvents) { 1780fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // Send a down event first, as we dropped a bunch of sudden jumps and assume that 1790fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // the user is releasing the touch on the second key. 1800fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(), 1810fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani MotionEvent.ACTION_DOWN, 1820fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani x, y, me.getMetaState()); 1830fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani super.onTouchEvent(translated); 1840fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani translated.recycle(); 1850fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani mDroppingEvents = false; 1860fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // Let the up event get processed as well, result = false 1870fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani } 1880fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani break; 1890fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani } 1900fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani // Track the previous coordinate 1910fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani mLastX = x; 1920fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani mLastY = y; 1930fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani return result; 1940fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani } 1950fef498a07515bdd5ac1ccfa564776d72fd85a51Amith Yamasani 196358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani @Override 197358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani public boolean onTouchEvent(MotionEvent me) { 1980ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa LatinKeyboard keyboard = getLatinKeyboard(); 1991b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani if (DEBUG_LINE) { 2001b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani mLastX = (int) me.getX(); 2011b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani mLastY = (int) me.getY(); 2021b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani invalidate(); 2031b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani } 204938c178215d38c6f085b32b0994598f9e8bc5ab5Amith Yamasani 205d2a431efa726771dee5c7b90004a0ed670d9a129Tadashi G. Takaoka // If there was a sudden jump, return without processing the actual motion event. 206d2a431efa726771dee5c7b90004a0ed670d9a129Tadashi G. Takaoka if (handleSuddenJump(me)) 207d2a431efa726771dee5c7b90004a0ed670d9a129Tadashi G. Takaoka return true; 208d2a431efa726771dee5c7b90004a0ed670d9a129Tadashi G. Takaoka 2093f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani // Reset any bounding box controls in the keyboard 2103f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani if (me.getAction() == MotionEvent.ACTION_DOWN) { 2113f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani keyboard.keyReleased(); 2123f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani } 2133f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani 2143f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani if (me.getAction() == MotionEvent.ACTION_UP) { 2153f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani int languageDirection = keyboard.getLanguageChangeDirection(); 2163f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani if (languageDirection != 0) { 2173f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani getOnKeyboardActionListener().onKey( 2185a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka languageDirection == 1 2195a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka ? LatinKeyboard.KEYCODE_NEXT_LANGUAGE : LatinKeyboard.KEYCODE_PREV_LANGUAGE, 220542f057ef64ae16cf2bc528880cf32bfd073edadsatok null, mLastX, mLastY); 2213f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani me.setAction(MotionEvent.ACTION_CANCEL); 2223f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani keyboard.keyReleased(); 2233f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani return super.onTouchEvent(me); 2243f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani } 2253f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani } 2263f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani 227d2a431efa726771dee5c7b90004a0ed670d9a129Tadashi G. Takaoka return super.onTouchEvent(me); 228bad436e93b49116f9005433845bf53126452a839Amith Yamasani } 229bad436e93b49116f9005433845bf53126452a839Amith Yamasani 230923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /**************************** INSTRUMENTATION *******************************/ 231923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2325a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka public static final boolean DEBUG_AUTO_PLAY = false; 2335a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka public static final boolean DEBUG_LINE = false; 234923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int MSG_TOUCH_DOWN = 1; 235923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int MSG_TOUCH_UP = 2; 236e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka 237923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Handler mHandler2; 238e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka 239923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private String mStringToPlay; 240923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mStringIndex; 241923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mDownDelivered; 242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private Key[] mAsciiKeys = new Key[256]; 243923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mPlaying; 2441b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani private int mLastX; 2451b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani private int mLastY; 2461b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani private Paint mPaint; 247923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2480ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa private void setKeyboardLocal(LatinKeyboard k) { 249923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (DEBUG_AUTO_PLAY) { 250923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project findKeys(); 251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mHandler2 == null) { 252923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mHandler2 = new Handler() { 253923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 254923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 255923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project removeMessages(MSG_TOUCH_DOWN); 256923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project removeMessages(MSG_TOUCH_UP); 257923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mPlaying == false) return; 258e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka 259923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 260923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case MSG_TOUCH_DOWN: 261923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mStringIndex >= mStringToPlay.length()) { 262923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPlaying = false; 263923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 264923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 265923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project char c = mStringToPlay.charAt(mStringIndex); 266e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka while (c > 255 || mAsciiKeys[c] == null) { 267923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mStringIndex++; 268923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mStringIndex >= mStringToPlay.length()) { 269923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPlaying = false; 270923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 271923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 272923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project c = mStringToPlay.charAt(mStringIndex); 273923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 274923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int x = mAsciiKeys[c].x + 10; 275923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int y = mAsciiKeys[c].y + 26; 276e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(), 277e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka SystemClock.uptimeMillis(), 278923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project MotionEvent.ACTION_DOWN, x, y, 0); 279923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project LatinKeyboardView.this.dispatchTouchEvent(me); 280923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project me.recycle(); 281923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendEmptyMessageDelayed(MSG_TOUCH_UP, 500); // Deliver up in 500ms if nothing else 282923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // happens 283923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDownDelivered = true; 284923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 285923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case MSG_TOUCH_UP: 286923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project char cUp = mStringToPlay.charAt(mStringIndex); 287923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int x2 = mAsciiKeys[cUp].x + 10; 288923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int y2 = mAsciiKeys[cUp].y + 26; 289923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mStringIndex++; 290e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka 291e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka MotionEvent me2 = MotionEvent.obtain(SystemClock.uptimeMillis(), 292e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka SystemClock.uptimeMillis(), 293923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project MotionEvent.ACTION_UP, x2, y2, 0); 294923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project LatinKeyboardView.this.dispatchTouchEvent(me2); 295923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project me2.recycle(); 296923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 500); // Deliver up in 500ms if nothing else 297923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // happens 298923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDownDelivered = false; 299923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 300923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 301923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 302923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 303923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 304923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 305923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 306923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 307923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 308923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void findKeys() { 3090ce98cbf98c6409ac18fa341f467703d78352a4cKen Wakasa List<Key> keys = getLatinKeyboard().getKeys(); 310923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Get the keys on this keyboard 311923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i = 0; i < keys.size(); i++) { 312923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int code = keys.get(i).codes[0]; 313e8f45ab56f3e6f358953dede794a63fc5901961dTadashi G. Takaoka if (code >= 0 && code <= 255) { 314923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAsciiKeys[code] = keys.get(i); 315923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 316923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 317923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 318979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 319979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public void startPlaying(String s) { 320979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG_AUTO_PLAY) { 321979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (s == null) return; 322979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mStringToPlay = s.toLowerCase(); 323979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mPlaying = true; 324979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mDownDelivered = false; 325979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mStringIndex = 0; 326979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 10); 327979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 328923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 329923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 330923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 331923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void draw(Canvas c) { 332979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinIMEUtil.GCUtils.getInstance().reset(); 333979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 334979f8690967ff5409fe18f5085858ccdb8e0ccf1satok for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 335979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 336979f8690967ff5409fe18f5085858ccdb8e0ccf1satok super.draw(c); 337979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 338979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 339979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait("LatinKeyboardView", e); 340979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 341979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 342979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG_AUTO_PLAY) { 343979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mPlaying) { 344979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mHandler2.removeMessages(MSG_TOUCH_DOWN); 345979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mHandler2.removeMessages(MSG_TOUCH_UP); 346979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mDownDelivered) { 347979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_UP, 20); 348979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 349979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 20); 350979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 351923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 352923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 3531b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani if (DEBUG_LINE) { 3541b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani if (mPaint == null) { 3551b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani mPaint = new Paint(); 3561b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani mPaint.setColor(0x80FFFFFF); 3571b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani mPaint.setAntiAlias(false); 3581b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani } 3591b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani c.drawLine(mLastX, 0, mLastX, getHeight(), mPaint); 3601b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani c.drawLine(0, mLastY, getWidth(), mLastY, mPaint); 3611b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani } 362923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 3631fb28137f43ae083c773c32440981ac61e83fa5dsatok 3641fb28137f43ae083c773c32440981ac61e83fa5dsatok @Override 3651fb28137f43ae083c773c32440981ac61e83fa5dsatok protected void onAttachedToWindow() { 3661fb28137f43ae083c773c32440981ac61e83fa5dsatok // Token is available from here. 3671fb28137f43ae083c773c32440981ac61e83fa5dsatok VoiceIMEConnector.getInstance().onAttachedToWindow(); 3681fb28137f43ae083c773c32440981ac61e83fa5dsatok } 369923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 370