All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robolectric.shadows.ShadowKeyCharacterMap Maven / Gradle / Ivy

package org.robolectric.shadows;

import static android.os.Build.VERSION_CODES.KITKAT;
import static android.os.Build.VERSION_CODES.KITKAT_WATCH;

import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import java.util.HashMap;
import java.util.Map;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.util.ReflectionHelpers;

@Implements(KeyCharacterMap.class)
public class ShadowKeyCharacterMap {
  private static final Map CHAR_TO_KEY_CODE = new HashMap<>();
  private static final Map CHAR_TO_KEY_CODE_SHIFT_ON = new HashMap<>();

  private static final Map KEY_CODE_TO_CHAR = new HashMap<>();
  private static final Map KEY_CODE_TO_CHAR_SHIFT_ON = new HashMap<>();

  static {
    CHAR_TO_KEY_CODE.put('0', KeyEvent.KEYCODE_0);
    CHAR_TO_KEY_CODE.put('1', KeyEvent.KEYCODE_1);
    CHAR_TO_KEY_CODE.put('2', KeyEvent.KEYCODE_2);
    CHAR_TO_KEY_CODE.put('3', KeyEvent.KEYCODE_3);
    CHAR_TO_KEY_CODE.put('4', KeyEvent.KEYCODE_4);
    CHAR_TO_KEY_CODE.put('5', KeyEvent.KEYCODE_5);
    CHAR_TO_KEY_CODE.put('6', KeyEvent.KEYCODE_6);
    CHAR_TO_KEY_CODE.put('7', KeyEvent.KEYCODE_7);
    CHAR_TO_KEY_CODE.put('8', KeyEvent.KEYCODE_8);
    CHAR_TO_KEY_CODE.put('9', KeyEvent.KEYCODE_9);
    CHAR_TO_KEY_CODE.put('A', KeyEvent.KEYCODE_A);
    CHAR_TO_KEY_CODE.put('B', KeyEvent.KEYCODE_B);
    CHAR_TO_KEY_CODE.put('C', KeyEvent.KEYCODE_C);
    CHAR_TO_KEY_CODE.put('D', KeyEvent.KEYCODE_D);
    CHAR_TO_KEY_CODE.put('E', KeyEvent.KEYCODE_E);
    CHAR_TO_KEY_CODE.put('F', KeyEvent.KEYCODE_F);
    CHAR_TO_KEY_CODE.put('G', KeyEvent.KEYCODE_G);
    CHAR_TO_KEY_CODE.put('H', KeyEvent.KEYCODE_H);
    CHAR_TO_KEY_CODE.put('I', KeyEvent.KEYCODE_I);
    CHAR_TO_KEY_CODE.put('J', KeyEvent.KEYCODE_J);
    CHAR_TO_KEY_CODE.put('K', KeyEvent.KEYCODE_K);
    CHAR_TO_KEY_CODE.put('L', KeyEvent.KEYCODE_L);
    CHAR_TO_KEY_CODE.put('M', KeyEvent.KEYCODE_M);
    CHAR_TO_KEY_CODE.put('N', KeyEvent.KEYCODE_N);
    CHAR_TO_KEY_CODE.put('O', KeyEvent.KEYCODE_O);
    CHAR_TO_KEY_CODE.put('P', KeyEvent.KEYCODE_P);
    CHAR_TO_KEY_CODE.put('Q', KeyEvent.KEYCODE_Q);
    CHAR_TO_KEY_CODE.put('R', KeyEvent.KEYCODE_R);
    CHAR_TO_KEY_CODE.put('S', KeyEvent.KEYCODE_S);
    CHAR_TO_KEY_CODE.put('T', KeyEvent.KEYCODE_T);
    CHAR_TO_KEY_CODE.put('U', KeyEvent.KEYCODE_U);
    CHAR_TO_KEY_CODE.put('V', KeyEvent.KEYCODE_V);
    CHAR_TO_KEY_CODE.put('W', KeyEvent.KEYCODE_W);
    CHAR_TO_KEY_CODE.put('X', KeyEvent.KEYCODE_X);
    CHAR_TO_KEY_CODE.put('Y', KeyEvent.KEYCODE_Y);
    CHAR_TO_KEY_CODE.put('Z', KeyEvent.KEYCODE_Z);
    CHAR_TO_KEY_CODE.put(' ', KeyEvent.KEYCODE_SPACE);
    CHAR_TO_KEY_CODE.put('-', KeyEvent.KEYCODE_MINUS);
    CHAR_TO_KEY_CODE.put('+', KeyEvent.KEYCODE_PLUS);
    CHAR_TO_KEY_CODE.put('@', KeyEvent.KEYCODE_AT);
    CHAR_TO_KEY_CODE.put('.', KeyEvent.KEYCODE_PERIOD);
    CHAR_TO_KEY_CODE.put(',', KeyEvent.KEYCODE_COMMA);
    CHAR_TO_KEY_CODE.put('[', KeyEvent.KEYCODE_LEFT_BRACKET);
    CHAR_TO_KEY_CODE.put(']', KeyEvent.KEYCODE_RIGHT_BRACKET);
    CHAR_TO_KEY_CODE.put('\'', KeyEvent.KEYCODE_APOSTROPHE);
    CHAR_TO_KEY_CODE.put(')', KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN);
    CHAR_TO_KEY_CODE.put('(', KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN);
    CHAR_TO_KEY_CODE.put('#', KeyEvent.KEYCODE_POUND);
    CHAR_TO_KEY_CODE.put('*', KeyEvent.KEYCODE_STAR);
    CHAR_TO_KEY_CODE.put('/', KeyEvent.KEYCODE_SLASH);
    CHAR_TO_KEY_CODE.put('=', KeyEvent.KEYCODE_EQUALS);
    CHAR_TO_KEY_CODE.put('`', KeyEvent.KEYCODE_GRAVE);
    CHAR_TO_KEY_CODE.put('\\', KeyEvent.KEYCODE_BACKSLASH);
    CHAR_TO_KEY_CODE.put('\n', KeyEvent.KEYCODE_ENTER);

    CHAR_TO_KEY_CODE_SHIFT_ON.put('_', KeyEvent.KEYCODE_MINUS);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('{', KeyEvent.KEYCODE_LEFT_BRACKET);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('}', KeyEvent.KEYCODE_RIGHT_BRACKET);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('\"', KeyEvent.KEYCODE_APOSTROPHE);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('!', KeyEvent.KEYCODE_1);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('$', KeyEvent.KEYCODE_4);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('%', KeyEvent.KEYCODE_5);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('^', KeyEvent.KEYCODE_6);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('&', KeyEvent.KEYCODE_7);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('?', KeyEvent.KEYCODE_SLASH);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('|', KeyEvent.KEYCODE_BACKSLASH);
    CHAR_TO_KEY_CODE_SHIFT_ON.put('~', KeyEvent.KEYCODE_GRAVE);

    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_0, '0');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_1, '1');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_2, '2');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_3, '3');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_4, '4');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_5, '5');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_6, '6');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_7, '7');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_8, '8');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_9, '9');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_A, 'A');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_B, 'B');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_C, 'C');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_D, 'D');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_E, 'E');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_F, 'F');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_G, 'G');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_H, 'H');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_I, 'I');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_J, 'J');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_K, 'K');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_L, 'L');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_M, 'M');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_N, 'N');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_O, 'O');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_P, 'P');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_Q, 'Q');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_R, 'R');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_S, 'S');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_T, 'T');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_U, 'U');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_V, 'V');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_W, 'W');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_X, 'X');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_Y, 'Y');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_Z, 'Z');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_SPACE, ' ');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_MINUS, '-');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_PLUS, '+');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_AT, '@');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_PERIOD, '.');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_COMMA, ',');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_LEFT_BRACKET, '[');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_RIGHT_BRACKET, ']');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_APOSTROPHE, '\'');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN, ')');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN, '(');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_POUND, '#');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_STAR, '*');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_SLASH, '/');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_EQUALS, '=');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_GRAVE, '`');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_BACKSLASH, '\\');
    KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_ENTER, '\n');

    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_MINUS, '_');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_LEFT_BRACKET, '{');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_RIGHT_BRACKET, '}');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_APOSTROPHE, '\"');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_1, '!');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_4, '$');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_5, '%');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_6, '^');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_7, '&');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_SLASH, '?');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_BACKSLASH, '|');
    KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_GRAVE, '~');
  }

  @Implementation
  protected static KeyCharacterMap load(int deviceId) {
    return ReflectionHelpers.callConstructor(KeyCharacterMap.class);
  }

  @Implementation
  protected KeyEvent[] getEvents(char[] chars) {
    if (chars == null) {
      throw new IllegalArgumentException("chars must not be null.");
    }
    int eventsPerChar = 2;
    KeyEvent[] events = new KeyEvent[chars.length * eventsPerChar];

    for (int i = 0; i < chars.length; i++) {
      events[eventsPerChar * i] = getDownEvent(chars[i]);
      events[eventsPerChar * i + 1] = getUpEvent(chars[i]);
    }

    return events;
  }

  @Implementation
  protected int getKeyboardType() {
    return KeyCharacterMap.FULL;
  }

  @Implementation
  protected int get(int keyCode, int metaState) {
    boolean metaShiftOn = (metaState & KeyEvent.META_SHIFT_ON) != 0;
    Character character = KEY_CODE_TO_CHAR.get(keyCode);
    if (character == null) {
      return 0;
    } else if (metaShiftOn) {
      return KEY_CODE_TO_CHAR_SHIFT_ON.getOrDefault(keyCode, character);
    } else {
      return Character.toLowerCase(character);
    }
  }

  public KeyEvent getDownEvent(char a) {
    return new KeyEvent(
        0,
        0,
        KeyEvent.ACTION_DOWN,
        toCharKeyCode(a),
        0,
        getMetaState(a),
        KeyCharacterMap.VIRTUAL_KEYBOARD,
        0);
  }

  public KeyEvent getUpEvent(char a) {
    return new KeyEvent(
        0,
        0,
        KeyEvent.ACTION_UP,
        toCharKeyCode(a),
        0,
        getMetaState(a),
        KeyCharacterMap.VIRTUAL_KEYBOARD,
        0);
  }

  @Implementation
  protected char getDisplayLabel(int keyCode) {
    return KEY_CODE_TO_CHAR.getOrDefault(keyCode, (char) 0);
  }

  @Implementation
  protected boolean isPrintingKey(int keyCode) {
    int type = Character.getType(getDisplayLabel(keyCode));
    switch (type) {
      case Character.SPACE_SEPARATOR:
      case Character.LINE_SEPARATOR:
      case Character.PARAGRAPH_SEPARATOR:
      case Character.CONTROL:
      case Character.FORMAT:
        return false;
      default:
        return true;
    }
  }

  @Implementation(minSdk = KITKAT_WATCH)
  protected static char nativeGetNumber(long ptr, int keyCode) {
    Character character = KEY_CODE_TO_CHAR.get(keyCode);
    if (character == null) {
      return 0;
    }
    return character;
  }

  @Implementation(maxSdk = KITKAT)
  protected static char nativeGetNumber(int ptr, int keyCode) {
    Character character = KEY_CODE_TO_CHAR.get(keyCode);
    if (character == null) {
      return 0;
    }
    return character;
  }

  private int toCharKeyCode(char a) {
    if (CHAR_TO_KEY_CODE.containsKey(Character.toUpperCase(a))) {
      return CHAR_TO_KEY_CODE.get(Character.toUpperCase(a));
    } else if (CHAR_TO_KEY_CODE_SHIFT_ON.containsKey(a)) {
      return CHAR_TO_KEY_CODE_SHIFT_ON.get(a);
    } else {
      return 0;
    }
  }

  private int getMetaState(char a) {
    if (Character.isUpperCase(a) || CHAR_TO_KEY_CODE_SHIFT_ON.containsKey(a)) {
      return KeyEvent.META_SHIFT_ON;
    } else {
      return 0;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy