MetaKeyKeyListener.java revision 497a92cc5ba2176b8a8484b0a7da040eac0e887b
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.text.method; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brownimport android.text.Editable; 20497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brownimport android.text.NoCopySpan; 21497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brownimport android.text.Spannable; 22497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brownimport android.text.Spanned; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This base class encapsulates the behavior for handling the meta keys 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (shift and alt) and the pseudo-meta state of selecting text. 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Key listeners that care about meta state should 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * inherit from it; you should not instantiate this class directly in a client. 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class MetaKeyKeyListener { 34497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown /** 35497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * Flag that indicates that the SHIFT key is on. 36497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * Value equals {@link KeyEvent#META_SHIFT_ON}. 37497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown */ 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int META_SHIFT_ON = KeyEvent.META_SHIFT_ON; 39497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown /** 40497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * Flag that indicates that the ALT key is on. 41497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * Value equals {@link KeyEvent#META_ALT_ON}. 42497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown */ 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int META_ALT_ON = KeyEvent.META_ALT_ON; 44497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown /** 45497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * Flag that indicates that the SYM key is on. 46497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * Value equals {@link KeyEvent#META_SYM_ON}. 47497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown */ 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int META_SYM_ON = KeyEvent.META_SYM_ON; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 50497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown /** 51497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * Flag that indicates that the SHIFT key is locked in CAPS mode. 52497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown */ 53497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown public static final int META_CAP_LOCKED = KeyEvent.META_CAP_LOCKED; 54497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown /** 55497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * Flag that indicates that the ALT key is locked. 56497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown */ 57497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown public static final int META_ALT_LOCKED = KeyEvent.META_ALT_LOCKED; 58497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown /** 59497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * Flag that indicates that the SYM key is locked. 60497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown */ 61497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown public static final int META_SYM_LOCKED = KeyEvent.META_SYM_LOCKED; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide pending API review 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 66497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown public static final int META_SELECTING = KeyEvent.META_SELECTING; 67497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown 68497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final int META_SHIFT_ON_AND_LOCKED = META_SHIFT_ON | META_CAP_LOCKED; 69497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final int META_ALT_ON_AND_LOCKED = META_ALT_ON | META_ALT_LOCKED; 70497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final int META_SYM_ON_AND_LOCKED = META_SYM_ON | META_SYM_LOCKED; 71497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown 72497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown // These bits are privately used by the meta key key listener. 73497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown // They are deliberately assigned values outside of the representable range of an 'int' 74497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown // so as not to conflict with any meta key states publicly defined by KeyEvent. 75497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final long META_CAP_USED = 1L << 32; 76497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final long META_ALT_USED = 1L << 33; 77497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final long META_SYM_USED = 1L << 34; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final long META_CAP_PRESSED = 1L << 40; 80497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final long META_ALT_PRESSED = 1L << 41; 81497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final long META_SYM_PRESSED = 1L << 42; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 83497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final long META_CAP_RELEASED = 1L << 48; 84497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final long META_ALT_RELEASED = 1L << 49; 85497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static final long META_SYM_RELEASED = 1L << 50; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long META_SHIFT_MASK = META_SHIFT_ON 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | META_CAP_LOCKED | META_CAP_USED 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | META_CAP_PRESSED | META_CAP_RELEASED; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long META_ALT_MASK = META_ALT_ON 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | META_ALT_LOCKED | META_ALT_USED 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | META_ALT_PRESSED | META_ALT_RELEASED; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long META_SYM_MASK = META_SYM_ON 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | META_SYM_LOCKED | META_SYM_USED 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | META_SYM_PRESSED | META_SYM_RELEASED; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final Object CAP = new NoCopySpan.Concrete(); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final Object ALT = new NoCopySpan.Concrete(); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final Object SYM = new NoCopySpan.Concrete(); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final Object SELECTING = new NoCopySpan.Concrete(); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Resets all meta state to inactive. 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void resetMetaState(Spannable text) { 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(CAP); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(ALT); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(SYM); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(SELECTING); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the state of the meta keys. 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text the buffer in which the meta key would have been pressed. 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return an integer in which each bit set to one represents a pressed 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or locked meta key. 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int getMetaState(CharSequence text) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getActive(text, CAP, META_SHIFT_ON, META_CAP_LOCKED) | 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getActive(text, ALT, META_ALT_ON, META_ALT_LOCKED) | 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getActive(text, SYM, META_SYM_ON, META_SYM_LOCKED) | 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getActive(text, SELECTING, META_SELECTING, META_SELECTING); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the state of a particular meta key. 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param meta META_SHIFT_ON, META_ALT_ON, META_SYM_ON, or META_SELECTING 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text the buffer in which the meta key would have been pressed. 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return 0 if inactive, 1 if active, 2 if locked. 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int getMetaState(CharSequence text, int meta) { 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (meta) { 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case META_SHIFT_ON: 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getActive(text, CAP, 1, 2); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case META_ALT_ON: 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getActive(text, ALT, 1, 2); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case META_SYM_ON: 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getActive(text, SYM, 1, 2); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case META_SELECTING: 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getActive(text, SELECTING, 1, 2); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static int getActive(CharSequence text, Object meta, 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int on, int lock) { 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!(text instanceof Spanned)) { 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) text; 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = sp.getSpanFlags(meta); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flag == LOCKED) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return lock; 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (flag != 0) { 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return on; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Call this method after you handle a keypress so that the meta 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * state will be reset to unshifted (if it is not still down) 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or primed to be reset to unshifted (once it is released). 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void adjustMetaAfterKeypress(Spannable content) { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjust(content, CAP); 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjust(content, ALT); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjust(content, SYM); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns true if this object is one that this class would use to 185b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * keep track of any meta state in the specified text. 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean isMetaTracker(CharSequence text, Object what) { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return what == CAP || what == ALT || what == SYM || 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project what == SELECTING; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 192b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project /** 193b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * Returns true if this object is one that this class would use to 194b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * keep track of the selecting meta state in the specified text. 195b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project */ 196b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project public static boolean isSelectingMetaTracker(CharSequence text, Object what) { 197b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project return what == SELECTING; 198b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 199b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void adjust(Spannable content, Object what) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int current = content.getSpanFlags(what); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (current == PRESSED) 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.setSpan(what, 0, 0, USED); 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (current == RELEASED) 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.removeSpan(what); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Call this if you are a method that ignores the locked meta state 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (arrow keys, for example) and you handle a key. 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected static void resetLockedMeta(Spannable content) { 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetLock(content, CAP); 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetLock(content, ALT); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetLock(content, SYM); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetLock(content, SELECTING); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void resetLock(Spannable content, Object what) { 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int current = content.getSpanFlags(what); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (current == LOCKED) 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.removeSpan(what); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handles presses of the meta keys. 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onKeyDown(View view, Editable content, 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int keyCode, KeyEvent event) { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project press(content, CAP); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || keyCode == KeyEvent.KEYCODE_NUM) { 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project press(content, ALT); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_SYM) { 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project press(content, SYM); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; // no super to call through to 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void press(Editable content, Object what) { 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int state = content.getSpanFlags(what); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == PRESSED) 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ; // repeat before use 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (state == RELEASED) 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.setSpan(what, 0, 0, LOCKED); 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (state == USED) 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ; // repeat after use 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (state == LOCKED) 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.removeSpan(what); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.setSpan(what, 0, 0, PRESSED); 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Start selecting text. 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide pending API review 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void startSelecting(View view, Spannable content) { 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.setSpan(SELECTING, 0, 0, PRESSED); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Stop selecting text. This does not actually collapse the selection; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * call {@link android.text.Selection#setSelection} too. 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide pending API review 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void stopSelecting(View view, Spannable content) { 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.removeSpan(SELECTING); 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handles release of the meta keys. 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onKeyUp(View view, Editable content, int keyCode, 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KeyEvent event) { 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project release(content, CAP); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || keyCode == KeyEvent.KEYCODE_NUM) { 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project release(content, ALT); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_SYM) { 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project release(content, SYM); 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; // no super to call through to 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void release(Editable content, Object what) { 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int current = content.getSpanFlags(what); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (current == USED) 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.removeSpan(what); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (current == PRESSED) 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content.setSpan(what, 0, 0, RELEASED); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearMetaKeyState(View view, Editable content, int states) { 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clearMetaKeyState(content, states); 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void clearMetaKeyState(Editable content, int states) { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((states&META_SHIFT_ON) != 0) content.removeSpan(CAP); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((states&META_ALT_ON) != 0) content.removeSpan(ALT); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((states&META_SYM_ON) != 0) content.removeSpan(SYM); 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((states&META_SELECTING) != 0) content.removeSpan(SELECTING); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Call this if you are a method that ignores the locked meta state 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (arrow keys, for example) and you handle a key. 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long resetLockedMeta(long state) { 332497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_CAP_LOCKED) != 0) { 333497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~META_SHIFT_MASK; 334497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 335497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_ALT_LOCKED) != 0) { 336497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~META_ALT_MASK; 337497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 338497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_SYM_LOCKED) != 0) { 339497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~META_SYM_MASK; 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return state; 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // --------------------------------------------------------------------- 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Version of API that operates on a state bit mask 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // --------------------------------------------------------------------- 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the state of the meta keys. 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param state the current meta state bits. 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return an integer in which each bit set to one represents a pressed 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or locked meta key. 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int getMetaState(long state) { 357497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown int result = 0; 358497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown 359497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_CAP_LOCKED) != 0) { 360497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown result |= META_CAP_LOCKED; 361497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else if ((state & META_SHIFT_ON) != 0) { 362497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown result |= META_SHIFT_ON; 363497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 364497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown 365497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_ALT_LOCKED) != 0) { 366497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown result |= META_ALT_LOCKED; 367497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else if ((state & META_ALT_ON) != 0) { 368497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown result |= META_ALT_ON; 369497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 370497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown 371497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_SYM_LOCKED) != 0) { 372497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown result |= META_SYM_LOCKED; 373497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else if ((state & META_SYM_ON) != 0) { 374497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown result |= META_SYM_ON; 375497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 376497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown 377497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown return result; 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the state of a particular meta key. 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param state the current state bits. 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param meta META_SHIFT_ON, META_ALT_ON, or META_SYM_ON 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return 0 if inactive, 1 if active, 2 if locked. 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int getMetaState(long state, int meta) { 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (meta) { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case META_SHIFT_ON: 391497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_CAP_LOCKED) != 0) return 2; 392497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_SHIFT_ON) != 0) return 1; 393497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown return 0; 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case META_ALT_ON: 396497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_ALT_LOCKED) != 0) return 2; 397497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_ALT_ON) != 0) return 1; 398497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown return 0; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case META_SYM_ON: 401497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_SYM_LOCKED) != 0) return 2; 402497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_SYM_ON) != 0) return 1; 403497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown return 0; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Call this method after you handle a keypress so that the meta 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * state will be reset to unshifted (if it is not still down) 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or primed to be reset to unshifted (once it is released). Takes 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the current state, returns the new state. 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long adjustMetaAfterKeypress(long state) { 417497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_CAP_PRESSED) != 0) { 418497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state = (state & ~META_SHIFT_MASK) | META_SHIFT_ON | META_CAP_USED; 419497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else if ((state & META_CAP_RELEASED) != 0) { 420497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~META_SHIFT_MASK; 421497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 422497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown 423497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_ALT_PRESSED) != 0) { 424497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state = (state & ~META_ALT_MASK) | META_ALT_ON | META_ALT_USED; 425497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else if ((state & META_ALT_RELEASED) != 0) { 426497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~META_ALT_MASK; 427497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 429497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & META_SYM_PRESSED) != 0) { 430497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state = (state & ~META_SYM_MASK) | META_SYM_ON | META_SYM_USED; 431497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else if ((state & META_SYM_RELEASED) != 0) { 432497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~META_SYM_MASK; 433497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return state; 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handles presses of the meta keys. 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long handleKeyDown(long state, int keyCode, KeyEvent event) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) { 442497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown return press(state, META_SHIFT_ON, META_SHIFT_MASK, 443497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown META_CAP_LOCKED, META_CAP_PRESSED, META_CAP_RELEASED, META_CAP_USED); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || keyCode == KeyEvent.KEYCODE_NUM) { 448497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown return press(state, META_ALT_ON, META_ALT_MASK, 449497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown META_ALT_LOCKED, META_ALT_PRESSED, META_ALT_RELEASED, META_ALT_USED); 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_SYM) { 453497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown return press(state, META_SYM_ON, META_SYM_MASK, 454497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown META_SYM_LOCKED, META_SYM_PRESSED, META_SYM_RELEASED, META_SYM_USED); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return state; 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static long press(long state, int what, long mask, 460497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown long locked, long pressed, long released, long used) { 461497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & pressed) != 0) { 462497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown // repeat before use 463497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else if ((state & released) != 0) { 464497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state = (state &~ mask) | what | locked; 465497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else if ((state & used) != 0) { 466497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown // repeat after use 467497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else if ((state & locked) != 0) { 468497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~mask; 469497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else { 470497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state |= what | pressed; 471497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return state; 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handles release of the meta keys. 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long handleKeyUp(long state, int keyCode, KeyEvent event) { 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) { 480497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown return release(state, META_SHIFT_ON, META_SHIFT_MASK, 481497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown META_CAP_PRESSED, META_CAP_RELEASED, META_CAP_USED); 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || keyCode == KeyEvent.KEYCODE_NUM) { 486497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown return release(state, META_ALT_ON, META_ALT_MASK, 487497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown META_ALT_PRESSED, META_ALT_RELEASED, META_ALT_USED); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_SYM) { 491497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown return release(state, META_SYM_ON, META_SYM_MASK, 492497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown META_SYM_PRESSED, META_SYM_RELEASED, META_SYM_USED); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return state; 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 497497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown private static long release(long state, int what, long mask, 498497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown long pressed, long released, long used) { 499497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((state & used) != 0) { 500497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~mask; 501497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } else if ((state & pressed) != 0) { 502497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state |= what | released; 503497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return state; 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 507497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown /** 508497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * Clears the state of the specified meta key if it is locked. 509497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * @param state the meta key state 510497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * @param which meta keys to clear, may be a combination of {@link #META_SHIFT_ON}, 511497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown * {@link #META_ALT_ON} or {@link #META_SYM_ON}. 512497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown */ 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long clearMetaKeyState(long state, int which) { 514497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((which & META_SHIFT_ON_AND_LOCKED) == META_SHIFT_ON_AND_LOCKED) { 515497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~META_SHIFT_MASK; 516497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 517497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((which & META_ALT_ON_AND_LOCKED) == META_ALT_ON_AND_LOCKED) { 518497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~META_ALT_MASK; 519497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 520497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown if ((which & META_SYM_ON_AND_LOCKED) == META_SYM_ON_AND_LOCKED) { 521497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown state &= ~META_SYM_MASK; 522497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return state; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 525497a92cc5ba2176b8a8484b0a7da040eac0e887bJeff Brown 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The meta key has been pressed but has not yet been used. 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int PRESSED = 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_MARK_MARK | (1 << Spannable.SPAN_USER_SHIFT); 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The meta key has been pressed and released but has still 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not yet been used. 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int RELEASED = 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_MARK_MARK | (2 << Spannable.SPAN_USER_SHIFT); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The meta key has been pressed and used but has not yet been released. 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int USED = 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_MARK_MARK | (3 << Spannable.SPAN_USER_SHIFT); 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The meta key has been pressed and released without use, and then 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pressed again; it may also have been released again. 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCKED = 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_MARK_MARK | (4 << Spannable.SPAN_USER_SHIFT); 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 553