1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.view; 18 19import android.view.KeyEvent; 20 21/** 22 * Helper for accessing features in {@link KeyEvent} introduced after 23 * API level 4 in a backwards compatible fashion. 24 */ 25public class KeyEventCompat { 26 /** 27 * Interface for the full API. 28 */ 29 interface KeyEventVersionImpl { 30 public int normalizeMetaState(int metaState); 31 public boolean metaStateHasModifiers(int metaState, int modifiers); 32 public boolean metaStateHasNoModifiers(int metaState); 33 } 34 35 /** 36 * Interface implementation that doesn't use anything about v4 APIs. 37 */ 38 static class BaseKeyEventVersionImpl implements KeyEventVersionImpl { 39 private static final int META_MODIFIER_MASK = 40 KeyEvent.META_SHIFT_ON | KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_RIGHT_ON 41 | KeyEvent.META_ALT_ON | KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_RIGHT_ON 42 | KeyEvent.META_SYM_ON; 43 44 // Mask of all lock key meta states. 45 private static final int META_ALL_MASK = META_MODIFIER_MASK; 46 47 private static int metaStateFilterDirectionalModifiers(int metaState, 48 int modifiers, int basic, int left, int right) { 49 final boolean wantBasic = (modifiers & basic) != 0; 50 final int directional = left | right; 51 final boolean wantLeftOrRight = (modifiers & directional) != 0; 52 53 if (wantBasic) { 54 if (wantLeftOrRight) { 55 throw new IllegalArgumentException("bad arguments"); 56 } 57 return metaState & ~directional; 58 } else if (wantLeftOrRight) { 59 return metaState & ~basic; 60 } else { 61 return metaState; 62 } 63 } 64 65 @Override 66 public int normalizeMetaState(int metaState) { 67 if ((metaState & (KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_RIGHT_ON)) != 0) { 68 metaState |= KeyEvent.META_SHIFT_ON; 69 } 70 if ((metaState & (KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_RIGHT_ON)) != 0) { 71 metaState |= KeyEvent.META_ALT_ON; 72 } 73 return metaState & META_ALL_MASK; 74 } 75 76 @Override 77 public boolean metaStateHasModifiers(int metaState, int modifiers) { 78 metaState = normalizeMetaState(metaState) & META_MODIFIER_MASK; 79 metaState = metaStateFilterDirectionalModifiers(metaState, modifiers, 80 KeyEvent.META_SHIFT_ON, KeyEvent.META_SHIFT_LEFT_ON, KeyEvent.META_SHIFT_RIGHT_ON); 81 metaState = metaStateFilterDirectionalModifiers(metaState, modifiers, 82 KeyEvent.META_ALT_ON, KeyEvent.META_ALT_LEFT_ON, KeyEvent.META_ALT_RIGHT_ON); 83 return metaState == modifiers; 84 } 85 86 @Override 87 public boolean metaStateHasNoModifiers(int metaState) { 88 return (normalizeMetaState(metaState) & META_MODIFIER_MASK) == 0; 89 } 90 } 91 92 /** 93 * Interface implementation for devices with at least v11 APIs. 94 */ 95 static class HoneycombKeyEventVersionImpl implements KeyEventVersionImpl { 96 @Override 97 public int normalizeMetaState(int metaState) { 98 return KeyEventCompatHoneycomb.normalizeMetaState(metaState); 99 } 100 101 @Override 102 public boolean metaStateHasModifiers(int metaState, int modifiers) { 103 return KeyEventCompatHoneycomb.metaStateHasModifiers(metaState, modifiers); 104 } 105 106 @Override 107 public boolean metaStateHasNoModifiers(int metaState) { 108 return KeyEventCompatHoneycomb.metaStateHasNoModifiers(metaState); 109 } 110 } 111 112 /** 113 * Select the correct implementation to use for the current platform. 114 */ 115 static final KeyEventVersionImpl IMPL; 116 static { 117 if (android.os.Build.VERSION.SDK_INT >= 11) { 118 IMPL = new HoneycombKeyEventVersionImpl(); 119 } else { 120 IMPL = new BaseKeyEventVersionImpl(); 121 } 122 } 123 124 // ------------------------------------------------------------------- 125 126 public static int normalizeMetaState(int metaState) { 127 return IMPL.normalizeMetaState(metaState); 128 } 129 130 public static boolean metaStateHasModifiers(int metaState, int modifiers) { 131 return IMPL.metaStateHasModifiers(metaState, modifiers); 132 } 133 134 public static boolean metaStateHasNoModifiers(int metaState) { 135 return IMPL.metaStateHasNoModifiers(metaState); 136 } 137 138 public static boolean hasModifiers(KeyEvent event, int modifiers) { 139 return IMPL.metaStateHasModifiers(event.getMetaState(), modifiers); 140 } 141 142 public static boolean hasNoModifiers(KeyEvent event) { 143 return IMPL.metaStateHasNoModifiers(event.getMetaState()); 144 } 145} 146