KeyEventCompat.java revision f185f104c4786740765e549d535f9ba1052f96cc
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. 160 */ 161 @Deprecated 162 public static void startTracking(KeyEvent event) { 163 event.startTracking(); 164 } 165 166 /** 167 * @deprecated Call {@link KeyEvent#isTracking()} directly. 168 */ 169 @Deprecated 170 public static boolean isTracking(KeyEvent event) { 171 return event.isTracking(); 172 } 173 174 /** 175 * @deprecated Call {@link View#getKeyDispatcherState()} directly. 176 */ 177 @Deprecated 178 public static Object getKeyDispatcherState(View view) { 179 return view.getKeyDispatcherState(); 180 } 181 182 /** 183 * @deprecated Call 184 * {@link KeyEvent#dispatch(KeyEvent.Callback, KeyEvent.DispatcherState, Object)} directly. 185 */ 186 @Deprecated 187 public static boolean dispatch(KeyEvent event, KeyEvent.Callback receiver, Object state, 188 Object target) { 189 return event.dispatch(receiver, (KeyEvent.DispatcherState)state, target); 190 } 191 192 public static boolean isCtrlPressed(KeyEvent event) { 193 return IMPL.isCtrlPressed(event); 194 } 195 196 private KeyEventCompat() {} 197} 198