KeyEventCompat.java revision 791f31bbba40b8b51694a1b2cdc804f360786ed1
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 public void startTracking(KeyEvent event); 34 public boolean isTracking(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 void startTracking(KeyEvent event) { 95 } 96 97 @Override 98 public boolean isTracking(KeyEvent event) { 99 return false; 100 } 101 } 102 103 static class EclairKeyEventVersionImpl extends BaseKeyEventVersionImpl { 104 @Override 105 public void startTracking(KeyEvent event) { 106 KeyEventCompatEclair.startTracking(event); 107 } 108 109 @Override 110 public boolean isTracking(KeyEvent event) { 111 return KeyEventCompatEclair.isTracking(event); 112 } 113 } 114 115 /** 116 * Interface implementation for devices with at least v11 APIs. 117 */ 118 static class HoneycombKeyEventVersionImpl extends EclairKeyEventVersionImpl { 119 @Override 120 public int normalizeMetaState(int metaState) { 121 return KeyEventCompatHoneycomb.normalizeMetaState(metaState); 122 } 123 124 @Override 125 public boolean metaStateHasModifiers(int metaState, int modifiers) { 126 return KeyEventCompatHoneycomb.metaStateHasModifiers(metaState, modifiers); 127 } 128 129 @Override 130 public boolean metaStateHasNoModifiers(int metaState) { 131 return KeyEventCompatHoneycomb.metaStateHasNoModifiers(metaState); 132 } 133 } 134 135 /** 136 * Select the correct implementation to use for the current platform. 137 */ 138 static final KeyEventVersionImpl IMPL; 139 static { 140 if (android.os.Build.VERSION.SDK_INT >= 11) { 141 IMPL = new HoneycombKeyEventVersionImpl(); 142 } else { 143 IMPL = new BaseKeyEventVersionImpl(); 144 } 145 } 146 147 // ------------------------------------------------------------------- 148 149 public static int normalizeMetaState(int metaState) { 150 return IMPL.normalizeMetaState(metaState); 151 } 152 153 public static boolean metaStateHasModifiers(int metaState, int modifiers) { 154 return IMPL.metaStateHasModifiers(metaState, modifiers); 155 } 156 157 public static boolean metaStateHasNoModifiers(int metaState) { 158 return IMPL.metaStateHasNoModifiers(metaState); 159 } 160 161 public static boolean hasModifiers(KeyEvent event, int modifiers) { 162 return IMPL.metaStateHasModifiers(event.getMetaState(), modifiers); 163 } 164 165 public static boolean hasNoModifiers(KeyEvent event) { 166 return IMPL.metaStateHasNoModifiers(event.getMetaState()); 167 } 168 169 public static void startTracking(KeyEvent event) { 170 IMPL.startTracking(event); 171 } 172 173 public static boolean isTracking(KeyEvent event) { 174 return IMPL.isTracking(event); 175 } 176} 177