/* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.util.ui; import com.intellij.openapi.util.SystemInfo; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtilRt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.util.Map; /** * @author gregsh */ public class KeyboardLayoutUtil { private static final Map<Character, Character> ourLLtoASCII = ContainerUtil.newConcurrentMap(); @Nullable public static Character getAsciiForChar(char a) { char lc = Character.toLowerCase(a); Character c = ourLLtoASCII.get(lc); if (c == null && (ourLLtoASCII.isEmpty() || SystemInfo.isLinux)) { // Linux note: // KeyEvent provides 'rawCode' (a physical |row|column| coordinate) instead of 'keyCode'. // ASCII rawCodes can be collected to map chars via their rawCode in future. // That would also allow map latin chars to latin chars when a layout switches latin keys. c = HardCoded.LL.get(lc); } return c == null ? null : lc == a ? c : Character.toUpperCase(c); } public static void storeAsciiForChar(@NotNull KeyEvent e) { int id = e.getID(); if (id != KeyEvent.KEY_PRESSED) return; int mods = e.getModifiers(); int code = e.getKeyCode(); char aChar = e.getKeyChar(); if ((mods & ~InputEvent.SHIFT_MASK & ~InputEvent.SHIFT_DOWN_MASK) != 0) return; if (code < KeyEvent.VK_A || code > KeyEvent.VK_Z) return; if (aChar == KeyEvent.CHAR_UNDEFINED) return; if ('a' <= aChar && aChar <= 'z' || 'A' <= aChar && aChar <= 'Z') return; if (ourLLtoASCII.containsKey(aChar)) return; ourLLtoASCII.put(aChar, (char)((int)'a' + (code - KeyEvent.VK_A))); } private static class HardCoded { private static final Map<Character, Character> LL = ContainerUtilRt.newHashMap(33); static { // keyboard layouts in lowercase char[] layout = new char[] { // Russian-PC 'й', 'q', 'ц', 'w', 'у', 'e', 'к', 'r', 'е', 't', 'н', 'y', 'г', 'u', 'ш', 'i', 'щ', 'o', 'з', 'p', 'х', '[', 'ъ', ']', 'ф', 'a', 'ы', 's', 'в', 'd', 'а', 'f', 'п', 'g', 'р', 'h', 'о', 'j', 'л', 'k', 'д', 'l', 'ж', ';', 'э', '\'', 'я', 'z', 'ч', 'x', 'с', 'c', 'м', 'v', 'и', 'b', 'т', 'n', 'ь', 'm', 'б', ',', 'ю', '.', '.', '/' }; int i = 0; while (i < layout.length) { LL.put(layout[i++], layout[i++]); } } } }