KeyEventCompat.java revision 17d15d92db2288bd27b8710c68e5bc1b9b5945f0
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; 20import android.view.View; 21 22/** 23 * Helper for accessing features in {@link KeyEvent} introduced after 24 * API level 4 in a backwards compatible fashion. 25 */ 26public final class KeyEventCompat { 27 /** 28 * Interface for the full API. 29 */ 30 interface KeyEventVersionImpl { 31 int normalizeMetaState(int metaState); 32 boolean metaStateHasModifiers(int metaState, int modifiers); 33 boolean metaStateHasNoModifiers(int metaState); 34 boolean isCtrlPressed(KeyEvent event); 35 } 36 37 /** 38 * Interface implementation that doesn't use anything about v4 APIs. 39 */ 40 static class BaseKeyEventVersionImpl implements KeyEventVersionImpl { 41 private static final int META_MODIFIER_MASK = 42 KeyEvent.META_SHIFT_ON | KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_RIGHT_ON 43 | KeyEvent.META_ALT_ON | KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_RIGHT_ON 44 | KeyEvent.META_SYM_ON; 45 46 // Mask of all lock key meta states. 47 private static final int META_ALL_MASK = META_MODIFIER_MASK; 48 49 private static int metaStateFilterDirectionalModifiers(int metaState, 50 int modifiers, int basic, int left, int right) { 51 final boolean wantBasic = (modifiers & basic) != 0; 52 final int directional = left | right; 53 final boolean wantLeftOrRight = (modifiers & directional) != 0; 54 55 if (wantBasic) { 56 if (wantLeftOrRight) { 57 throw new IllegalArgumentException("bad arguments"); 58 } 59 return metaState & ~directional; 60 } else if (wantLeftOrRight) { 61 return metaState & ~basic; 62 } else { 63 return metaState; 64 } 65 } 66 67 @Override 68 public int normalizeMetaState(int metaState) { 69 if ((metaState & (KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_RIGHT_ON)) != 0) { 70 metaState |= KeyEvent.META_SHIFT_ON; 71 } 72 if ((metaState & (KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_RIGHT_ON)) != 0) { 73 metaState |= KeyEvent.META_ALT_ON; 74 } 75 return metaState & META_ALL_MASK; 76 } 77 78 @Override 79 public boolean metaStateHasModifiers(int metaState, int modifiers) { 80 metaState = normalizeMetaState(metaState) & META_MODIFIER_MASK; 81 metaState = metaStateFilterDirectionalModifiers(metaState, modifiers, 82 KeyEvent.META_SHIFT_ON, KeyEvent.META_SHIFT_LEFT_ON, KeyEvent.META_SHIFT_RIGHT_ON); 83 metaState = metaStateFilterDirectionalModifiers(metaState, modifiers, 84 KeyEvent.META_ALT_ON, KeyEvent.META_ALT_LEFT_ON, KeyEvent.META_ALT_RIGHT_ON); 85 return metaState == modifiers; 86 } 87 88 @Override 89 public boolean metaStateHasNoModifiers(int metaState) { 90 return (normalizeMetaState(metaState) & META_MODIFIER_MASK) == 0; 91 } 92 93 @Override 94 public boolean isCtrlPressed(KeyEvent event) { 95 return false; 96 } 97 } 98 99 /** 100 * Interface implementation for devices with at least v11 APIs. 101 */ 102 static class HoneycombKeyEventVersionImpl extends BaseKeyEventVersionImpl { 103 @Override 104 public int normalizeMetaState(int metaState) { 105 return KeyEventCompatHoneycomb.normalizeMetaState(metaState); 106 } 107 108 @Override 109 public boolean metaStateHasModifiers(int metaState, int modifiers) { 110 return KeyEventCompatHoneycomb.metaStateHasModifiers(metaState, modifiers); 111 } 112 113 @Override 114 public boolean metaStateHasNoModifiers(int metaState) { 115 return KeyEventCompatHoneycomb.metaStateHasNoModifiers(metaState); 116 } 117 118 @Override 119 public boolean isCtrlPressed(KeyEvent event) { 120 return KeyEventCompatHoneycomb.isCtrlPressed(event); 121 } 122 } 123 124 /** 125 * Select the correct implementation to use for the current platform. 126 */ 127 static final KeyEventVersionImpl IMPL; 128 static { 129 if (android.os.Build.VERSION.SDK_INT >= 11) { 130 IMPL = new HoneycombKeyEventVersionImpl(); 131 } else { 132 IMPL = new BaseKeyEventVersionImpl(); 133 } 134 } 135 136 // ------------------------------------------------------------------- 137 138 public static int normalizeMetaState(int metaState) { 139 return IMPL.normalizeMetaState(metaState); 140 } 141 142 public static boolean metaStateHasModifiers(int metaState, int modifiers) { 143 return IMPL.metaStateHasModifiers(metaState, modifiers); 144 } 145 146 public static boolean metaStateHasNoModifiers(int metaState) { 147 return IMPL.metaStateHasNoModifiers(metaState); 148 } 149 150 public static boolean hasModifiers(KeyEvent event, int modifiers) { 151 return IMPL.metaStateHasModifiers(event.getMetaState(), modifiers); 152 } 153 154 public static boolean hasNoModifiers(KeyEvent event) { 155 return IMPL.metaStateHasNoModifiers(event.getMetaState()); 156 } 157 158 /** 159 * @deprecated Call {@link KeyEvent#startTracking()} directly. This method will be removed in a 160 * future release. 161 */ 162 @Deprecated 163 public static void startTracking(KeyEvent event) { 164 event.startTracking(); 165 } 166 167 /** 168 * @deprecated Call {@link KeyEvent#isTracking()} directly. This method will be removed in a 169 * future release. 170 */ 171 @Deprecated 172 public static boolean isTracking(KeyEvent event) { 173 return event.isTracking(); 174 } 175 176 /** 177 * @deprecated Call {@link View#getKeyDispatcherState()} directly. This method will be removed 178 * in a future release. 179 */ 180 @Deprecated 181 public static Object getKeyDispatcherState(View view) { 182 return view.getKeyDispatcherState(); 183 } 184 185 /** 186 * @deprecated Call 187 * {@link KeyEvent#dispatch(KeyEvent.Callback, KeyEvent.DispatcherState, Object)} directly. 188 * This method will be removed in a future release. 189 */ 190 @Deprecated 191 public static boolean dispatch(KeyEvent event, KeyEvent.Callback receiver, Object state, 192 Object target) { 193 return event.dispatch(receiver, (KeyEvent.DispatcherState)state, target); 194 } 195 196 public static boolean isCtrlPressed(KeyEvent event) { 197 return IMPL.isCtrlPressed(event); 198 } 199 200 private KeyEventCompat() {} 201} 202