下面列出了android.view.KeyEvent#getMetaState ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private KeyEvent convertKeyEventInArc(KeyEvent event) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_HOME:
case KeyEvent.KEYCODE_BACK:
// In Arc, Search + X is sent as KEYCODE_X with META_META_ON in Android. Android
// converts META_META_ON + KEYCODE_ENTER and META_META_ON + KEYCODE_DEL to
// KEYCODE_HOME and KEYCODE_BACK without META_META_ON. We add META_META_ON to this
// key event to satisfy trigger modifier condition. We don't need to do this in
// non-Arc since Search + X is usually sent as KEYCODE_X with META_META_ON and
// META_META_LEFT_ON or META_META_RIGHT_ON.
return new KeyEvent(
event.getDownTime(),
event.getEventTime(),
event.getAction(),
event.getKeyCode(),
event.getRepeatCount(),
event.getMetaState() | KeyEvent.META_META_ON);
default:
return event;
}
}
public void onKeyDown(@Nonnull final KeyEvent keyEvent) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - considering " + keyEvent);
}
final Pair<Integer, Integer> key =
Pair.create(keyEvent.getKeyCode(), keyEvent.getMetaState());
if (mKeySet.contains(key)) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - enabling action");
}
mCanFire = true;
mMetaState = keyEvent.getMetaState();
} else if (mCanFire) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - disabling action");
}
mCanFire = false;
}
}
public void onKeyDown(@Nonnull final KeyEvent keyEvent) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - considering " + keyEvent);
}
final Pair<Integer, Integer> key =
Pair.create(keyEvent.getKeyCode(), keyEvent.getMetaState());
if (mKeySet.contains(key)) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - enabling action");
}
mCanFire = true;
mMetaState = keyEvent.getMetaState();
} else if (mCanFire) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - disabling action");
}
mCanFire = false;
}
}
private boolean moveend(TextView widget, Spannable buffer, KeyEvent event) {
boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
KeyEvent.META_SHIFT_ON) == 1) ||
(JotaTextKeyListener.getMetaStateSelecting(buffer) != 0);
Layout layout = widget.getLayout();
boolean ctrl = (event.getMetaState() & mShortcutCtrlKey)!=0;
if ( ctrl ){
if (cap) {
Selection.extendSelection(buffer, buffer.length());
return true;
} else {
Selection.setSelection(buffer, buffer.length());
return true;
}
}else{
if (cap) {
return Selection.extendToRightEdge(buffer, layout);
} else {
return Selection.moveToRightEdge(buffer, layout);
}
}
}
public void onKeyDown(@Nonnull final KeyEvent keyEvent) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - considering " + keyEvent);
}
final Pair<Integer, Integer> key =
Pair.create(keyEvent.getKeyCode(), keyEvent.getMetaState());
if (mKeySet.contains(key)) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - enabling action");
}
mCanFire = true;
mMetaState = keyEvent.getMetaState();
} else if (mCanFire) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyDown() - " + mName + " - disabling action");
}
mCanFire = false;
}
}
@Override
public boolean onKeyShortcut(int keyCode, KeyEvent event) {
final int filteredMetaState = event.getMetaState() & ~KeyEvent.META_CTRL_MASK;
if (KeyEvent.metaStateHasNoModifiers(filteredMetaState)) {
switch (keyCode) {
case KeyEvent.KEYCODE_A:
selectAll();
return true;
case KeyEvent.KEYCODE_X:
cut();
return true;
case KeyEvent.KEYCODE_C:
copy();
return true;
case KeyEvent.KEYCODE_V:
paste();
return true;
}
}
return super.onKeyShortcut(keyCode, event);
}
private boolean moveend(TextView widget, Spannable buffer, KeyEvent event) {
boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
KeyEvent.META_SHIFT_ON) == 1) ||
(JotaTextKeyListener.getMetaStateSelecting(buffer) != 0);
Layout layout = widget.getLayout();
boolean ctrl = (event.getMetaState() & mShortcutCtrlKey)!=0;
if ( ctrl ){
if (cap) {
Selection.extendSelection(buffer, buffer.length());
return true;
} else {
Selection.setSelection(buffer, buffer.length());
return true;
}
}else{
if (cap) {
return Selection.extendToRightEdge(buffer, layout);
} else {
return Selection.moveToRightEdge(buffer, layout);
}
}
}
@SuppressWarnings("deprecation")
MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
// Get all items that can be associated directly or indirectly with the keyCode
ArrayList<MenuItemImpl> items = mTempShortcutItemList;
items.clear();
findItemsWithShortcutForKey(items, keyCode, event);
if (items.isEmpty()) {
return null;
}
final int metaState = event.getMetaState();
final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
// Get the chars associated with the keyCode (i.e using any chording combo)
event.getKeyData(possibleChars);
// If we have only one element, we can safely returns it
final int size = items.size();
if (size == 1) {
return items.get(0);
}
final boolean qwerty = isQwertyMode();
// If we found more than one item associated with the key,
// we have to return the exact match
for (int i = 0; i < size; i++) {
final MenuItemImpl item = items.get(i);
final char shortcutChar = qwerty ? item.getAlphabeticShortcut() :
item.getNumericShortcut();
if ((shortcutChar == possibleChars.meta[0] &&
(metaState & KeyEvent.META_ALT_ON) == 0)
|| (shortcutChar == possibleChars.meta[2] &&
(metaState & KeyEvent.META_ALT_ON) != 0)
|| (qwerty && shortcutChar == '\b' &&
keyCode == KeyEvent.KEYCODE_DEL)) {
return item;
}
}
return null;
}
@SuppressWarnings("deprecation")
MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
// Get all items that can be associated directly or indirectly with the keyCode
ArrayList<MenuItemImpl> items = mTempShortcutItemList;
items.clear();
findItemsWithShortcutForKey(items, keyCode, event);
if (items.isEmpty()) {
return null;
}
final int metaState = event.getMetaState();
final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
// Get the chars associated with the keyCode (i.e using any chording combo)
event.getKeyData(possibleChars);
// If we have only one element, we can safely returns it
final int size = items.size();
if (size == 1) {
return items.get(0);
}
final boolean qwerty = isQwertyMode();
// If we found more than one item associated with the key,
// we have to return the exact match
for (int i = 0; i < size; i++) {
final MenuItemImpl item = items.get(i);
final char shortcutChar = qwerty ? item.getAlphabeticShortcut() :
item.getNumericShortcut();
if ((shortcutChar == possibleChars.meta[0] &&
(metaState & KeyEvent.META_ALT_ON) == 0)
|| (shortcutChar == possibleChars.meta[2] &&
(metaState & KeyEvent.META_ALT_ON) != 0)
|| (qwerty && shortcutChar == '\b' &&
keyCode == KeyEvent.KEYCODE_DEL)) {
return item;
}
}
return null;
}
@SuppressWarnings("deprecation")
void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
final boolean qwerty = isQwertyMode();
final int metaState = event.getMetaState();
final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
// Get the chars associated with the keyCode (i.e using any chording combo)
final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
// The delete key is not mapped to '\b' so we treat it specially
if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
return;
}
// Look for an item whose shortcut is this key.
final int N = mItems.size();
for (int i = 0; i < N; i++) {
MenuItemImpl item = mItems.get(i);
if (item.hasSubMenu()) {
((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event);
}
final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
(shortcutChar != 0) &&
(shortcutChar == possibleChars.meta[0]
|| shortcutChar == possibleChars.meta[2]
|| (qwerty && shortcutChar == '\b' &&
keyCode == KeyEvent.KEYCODE_DEL)) &&
item.isEnabled()) {
items.add(item);
}
}
}
@SuppressWarnings("deprecation")
MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
// Get all items that can be associated directly or indirectly with the keyCode
ArrayList<MenuItemImpl> items = mTempShortcutItemList;
items.clear();
findItemsWithShortcutForKey(items, keyCode, event);
if (items.isEmpty()) {
return null;
}
final int metaState = event.getMetaState();
final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
// Get the chars associated with the keyCode (i.e using any chording combo)
event.getKeyData(possibleChars);
// If we have only one element, we can safely returns it
final int size = items.size();
if (size == 1) {
return items.get(0);
}
final boolean qwerty = isQwertyMode();
// If we found more than one item associated with the key,
// we have to return the exact match
for (int i = 0; i < size; i++) {
final MenuItemImpl item = items.get(i);
final char shortcutChar = qwerty ? item.getAlphabeticShortcut() :
item.getNumericShortcut();
if ((shortcutChar == possibleChars.meta[0] &&
(metaState & KeyEvent.META_ALT_ON) == 0)
|| (shortcutChar == possibleChars.meta[2] &&
(metaState & KeyEvent.META_ALT_ON) != 0)
|| (qwerty && shortcutChar == '\b' &&
keyCode == KeyEvent.KEYCODE_DEL)) {
return item;
}
}
return null;
}
@SuppressWarnings("deprecation")
void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
final boolean qwerty = isQwertyMode();
final int metaState = event.getMetaState();
final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
// Get the chars associated with the keyCode (i.e using any chording combo)
final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
// The delete key is not mapped to '\b' so we treat it specially
if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
return;
}
// Look for an item whose shortcut is this key.
final int N = mItems.size();
for (int i = 0; i < N; i++) {
MenuItemImpl item = mItems.get(i);
if (item.hasSubMenu()) {
((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event);
}
final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
(shortcutChar != 0) &&
(shortcutChar == possibleChars.meta[0]
|| shortcutChar == possibleChars.meta[2]
|| (qwerty && shortcutChar == '\b' &&
keyCode == KeyEvent.KEYCODE_DEL)) &&
item.isEnabled()) {
items.add(item);
}
}
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (sTrapAltAndMeta) {
boolean altEsc = mKeyListener.getAltSendsEsc();
boolean altOn = (event.getMetaState() & KeyEvent.META_ALT_ON) != 0;
boolean metaOn = (event.getMetaState() & KeyEvent.META_META_ON) != 0;
boolean altPressed = (keyCode == KeyEvent.KEYCODE_ALT_LEFT)
|| (keyCode == KeyEvent.KEYCODE_ALT_RIGHT);
boolean altActive = mKeyListener.isAltActive();
if (altEsc && (altOn || altPressed || altActive || metaOn)) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
return onKeyDown(keyCode, event);
} else {
return onKeyUp(keyCode, event);
}
}
}
if (handleHardwareControlKey(keyCode, event)) {
return true;
}
if (mKeyListener.isCtrlActive()) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
return onKeyDown(keyCode, event);
} else {
return onKeyUp(keyCode, event);
}
}
return super.onKeyPreIme(keyCode, event);
}
@SuppressWarnings("deprecation")
void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
final boolean qwerty = isQwertyMode();
final int metaState = event.getMetaState();
final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
// Get the chars associated with the keyCode (i.e using any chording combo)
final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
// The delete key is not mapped to '\b' so we treat it specially
if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
return;
}
// Look for an item whose shortcut is this key.
final int N = mItems.size();
for (int i = 0; i < N; i++) {
MenuItemImpl item = mItems.get(i);
if (item.hasSubMenu()) {
((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event);
}
final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
(shortcutChar != 0) &&
(shortcutChar == possibleChars.meta[0]
|| shortcutChar == possibleChars.meta[2]
|| (qwerty && shortcutChar == '\b' &&
keyCode == KeyEvent.KEYCODE_DEL)) &&
item.isEnabled()) {
items.add(item);
}
}
}
public void onKeyUp(@Nonnull final KeyEvent keyEvent) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - considering " + keyEvent);
}
final int keyCode = keyEvent.getKeyCode();
int metaState = keyEvent.getMetaState();
if (KeyEvent.isModifierKey(keyCode)) {
// Try restoring meta stat in case the released key was a modifier.
// I am sure one can come up with scenarios to break this, but it
// seems to work well in practice.
metaState |= mMetaState;
}
final Pair<Integer, Integer> key = Pair.create(keyCode, metaState);
if (mKeySet.contains(key)) {
if (mCanFire) {
if (!keyEvent.isCanceled()) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - firing action");
}
action();
} else {
// This key up event was a part of key combinations and
// should be ignored.
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - canceled, ignoring action");
}
}
mCanFire = false;
}
}
if (mCanFire) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - disabling action");
}
mCanFire = false;
}
}
@SuppressWarnings("deprecation")
void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
final boolean qwerty = isQwertyMode();
final int metaState = event.getMetaState();
final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
// Get the chars associated with the keyCode (i.e using any chording combo)
final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
// The delete key is not mapped to '\b' so we treat it specially
if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
return;
}
// Look for an item whose shortcut is this key.
final int N = mItems.size();
for (int i = 0; i < N; i++) {
MenuItemImpl item = mItems.get(i);
if (item.hasSubMenu()) {
((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event);
}
final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
(shortcutChar != 0) &&
(shortcutChar == possibleChars.meta[0]
|| shortcutChar == possibleChars.meta[2]
|| (qwerty && shortcutChar == '\b' &&
keyCode == KeyEvent.KEYCODE_DEL)) &&
item.isEnabled()) {
items.add(item);
}
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int keycode = event.getKeyCode();
if ( !mCtrlPreIme ){
// CTRL + KEYDOWN
int meta = (int)event.getMetaState();
boolean ctrl = (meta & mShortcutCtrlKey)!=0 ; // one of meta keies is pressed
if ( ctrl ){
if (event.getAction() == KeyEvent.ACTION_DOWN ){
Log.d("=================>", ""+keycode);
if (doShortcut(keycode)){
return true;
}
}else if (event.getAction() == KeyEvent.ACTION_UP){
return true;
}
}
}
if ( IS01FullScreen.isIS01orLynx() ){
if ( keycode == KeyEvent.KEYCODE_PAGE_UP ||
keycode == KeyEvent.KEYCODE_PAGE_DOWN ){
return true;
}
}
return super.dispatchKeyEvent(event);
}
public void onKeyUp(@Nonnull final KeyEvent keyEvent) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - considering " + keyEvent);
}
final int keyCode = keyEvent.getKeyCode();
int metaState = keyEvent.getMetaState();
if (KeyEvent.isModifierKey(keyCode)) {
// Try restoring meta stat in case the released key was a modifier.
// I am sure one can come up with scenarios to break this, but it
// seems to work well in practice.
metaState |= mMetaState;
}
final Pair<Integer, Integer> key = Pair.create(keyCode, metaState);
if (mKeySet.contains(key)) {
if (mCanFire) {
if (!keyEvent.isCanceled()) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - firing action");
}
action();
} else {
// This key up event was a part of key combinations and
// should be ignored.
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - canceled, ignoring action");
}
}
mCanFire = false;
}
}
if (mCanFire) {
if (DEBUG) {
Log.d(TAG, "EmojiHotKeys.onKeyUp() - " + mName + " - disabling action");
}
mCanFire = false;
}
}
public boolean handleKeyCode(int keyCode, KeyEvent event, boolean appMode) throws IOException {
String code = null;
if (event != null) {
int keyMod = 0;
// META_CTRL_ON was added only in API 11, so don't use it,
// use our own tracking of Ctrl key instead.
// (event.getMetaState() & META_CTRL_ON) != 0
if (mHardwareControlKey || mControlKey.isActive()) {
keyMod |= KEYMOD_CTRL;
}
if ((event.getMetaState() & META_ALT_ON) != 0) {
keyMod |= KEYMOD_ALT;
}
if ((event.getMetaState() & META_SHIFT_ON) != 0) {
keyMod |= KEYMOD_SHIFT;
}
// First try to map scancode
code = mKeyMap.get(event.getScanCode() | KEYMOD_SCAN | keyMod);
if (code == null) {
code = mKeyMap.get(keyCode | keyMod);
}
}
if (code == null && keyCode >= 0 && keyCode < mKeyCodes.length) {
if (appMode) {
code = mAppKeyCodes[keyCode];
}
if (code == null) {
code = mKeyCodes[keyCode];
}
}
if (code != null) {
if (EmulatorDebug.LOG_CHARACTERS_FLAG) {
byte[] bytes = code.getBytes();
Log.d(EmulatorDebug.LOG_TAG, "Out: '" + EmulatorDebug.bytesToString(bytes, 0, bytes.length) + "'");
}
mTermSession.write(code);
return true;
}
return false;
}
/**
* Gets the state of the meta keys for a specific key event.
*
* For input devices that use toggled key modifiers, the `toggled' state
* is stored into the text buffer. This method retrieves the meta state
* for this event, accounting for the stored state. If the event has been
* created by a device that does not support toggled key modifiers, like
* a virtual device for example, the stored state is ignored.
*
* @param text the buffer in which the meta key would have been pressed.
* @param event the event for which to evaluate the meta state.
* @return an integer in which each bit set to one represents a pressed
* or locked meta key.
*/
public static final int getMetaState(final CharSequence text, final KeyEvent event) {
int metaState = event.getMetaState();
if (event.getKeyCharacterMap().getModifierBehavior()
== KeyCharacterMap.MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED) {
metaState |= getMetaState(text);
}
return metaState;
}