Loading core/java/android/hardware/input/KeyboardLayout.java +65 −20 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.os.Parcelable; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * Describes a keyboard layout. Loading @@ -30,6 +31,37 @@ import java.util.Map; * @hide */ public final class KeyboardLayout implements Parcelable, Comparable<KeyboardLayout> { /** Undefined keyboard layout */ public static final String LAYOUT_TYPE_UNDEFINED = "undefined"; /** Qwerty-based keyboard layout */ public static final String LAYOUT_TYPE_QWERTY = "qwerty"; /** Qwertz-based keyboard layout */ public static final String LAYOUT_TYPE_QWERTZ = "qwertz"; /** Azerty-based keyboard layout */ public static final String LAYOUT_TYPE_AZERTY = "azerty"; /** Dvorak keyboard layout */ public static final String LAYOUT_TYPE_DVORAK = "dvorak"; /** Colemak keyboard layout */ public static final String LAYOUT_TYPE_COLEMAK = "colemak"; /** Workman keyboard layout */ public static final String LAYOUT_TYPE_WORKMAN = "workman"; /** Turkish-F keyboard layout */ public static final String LAYOUT_TYPE_TURKISH_F = "turkish_f"; /** Turkish-Q keyboard layout */ public static final String LAYOUT_TYPE_TURKISH_Q = "turkish_q"; /** Keyboard layout that has been enhanced with a large number of extra characters */ public static final String LAYOUT_TYPE_EXTENDED = "extended"; private final String mDescriptor; private final String mLabel; private final String mCollection; Loading @@ -42,31 +74,24 @@ public final class KeyboardLayout implements Parcelable, Comparable<KeyboardLayo /** Currently supported Layout types in the KCM files */ private enum LayoutType { UNDEFINED(0, "undefined"), QWERTY(1, "qwerty"), QWERTZ(2, "qwertz"), AZERTY(3, "azerty"), DVORAK(4, "dvorak"), COLEMAK(5, "colemak"), WORKMAN(6, "workman"), TURKISH_F(7, "turkish_f"), TURKISH_Q(8, "turkish_q"), EXTENDED(9, "extended"); UNDEFINED(0, LAYOUT_TYPE_UNDEFINED), QWERTY(1, LAYOUT_TYPE_QWERTY), QWERTZ(2, LAYOUT_TYPE_QWERTZ), AZERTY(3, LAYOUT_TYPE_AZERTY), DVORAK(4, LAYOUT_TYPE_DVORAK), COLEMAK(5, LAYOUT_TYPE_COLEMAK), WORKMAN(6, LAYOUT_TYPE_WORKMAN), TURKISH_F(7, LAYOUT_TYPE_TURKISH_F), TURKISH_Q(8, LAYOUT_TYPE_TURKISH_Q), EXTENDED(9, LAYOUT_TYPE_EXTENDED); private final int mValue; private final String mName; private static final Map<Integer, LayoutType> VALUE_TO_ENUM_MAP = new HashMap<>(); static { VALUE_TO_ENUM_MAP.put(UNDEFINED.mValue, UNDEFINED); VALUE_TO_ENUM_MAP.put(QWERTY.mValue, QWERTY); VALUE_TO_ENUM_MAP.put(QWERTZ.mValue, QWERTZ); VALUE_TO_ENUM_MAP.put(AZERTY.mValue, AZERTY); VALUE_TO_ENUM_MAP.put(DVORAK.mValue, DVORAK); VALUE_TO_ENUM_MAP.put(COLEMAK.mValue, COLEMAK); VALUE_TO_ENUM_MAP.put(WORKMAN.mValue, WORKMAN); VALUE_TO_ENUM_MAP.put(TURKISH_F.mValue, TURKISH_F); VALUE_TO_ENUM_MAP.put(TURKISH_Q.mValue, TURKISH_Q); VALUE_TO_ENUM_MAP.put(EXTENDED.mValue, EXTENDED); for (LayoutType type : LayoutType.values()) { VALUE_TO_ENUM_MAP.put(type.mValue, type); } } private static LayoutType of(int value) { Loading Loading @@ -206,6 +231,9 @@ public final class KeyboardLayout implements Parcelable, Comparable<KeyboardLayo // Note that these arguments are intentionally flipped since you want higher priority // keyboards to be listed before lower priority keyboards. int result = Integer.compare(another.mPriority, mPriority); if (result == 0) { result = Integer.compare(mLayoutType.mValue, another.mLayoutType.mValue); } if (result == 0) { result = mLabel.compareToIgnoreCase(another.mLabel); } Loading @@ -226,4 +254,21 @@ public final class KeyboardLayout implements Parcelable, Comparable<KeyboardLayo + ", vendorId: " + mVendorId + ", productId: " + mProductId; } /** * Check if the provided layout type is supported/valid. * * @param layoutName name of layout type * @return {@code true} if the provided layout type is supported/valid. */ public static boolean isLayoutTypeValid(@NonNull String layoutName) { Objects.requireNonNull(layoutName, "Provided layout name should not be null"); for (LayoutType layoutType : LayoutType.values()) { if (layoutName.equals(layoutType.getName())) { return true; } } // Layout doesn't match any supported layout types return false; } } services/core/java/com/android/server/input/InputManagerService.java +1 −4 Original line number Diff line number Diff line Loading @@ -3346,10 +3346,7 @@ public class InputManagerService extends IInputManager.Stub public void onInputMethodSubtypeChangedForKeyboardLayoutMapping(@UserIdInt int userId, @Nullable InputMethodSubtypeHandle subtypeHandle, @Nullable InputMethodSubtype subtype) { if (DEBUG) { Slog.i(TAG, "InputMethodSubtype changed: userId=" + userId + " subtypeHandle=" + subtypeHandle); } mKeyboardLayoutManager.onInputMethodSubtypeChanged(userId, subtypeHandle, subtype); } @Override Loading services/core/java/com/android/server/input/KeyboardLayoutManager.java +433 −42 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/input/PersistentDataStore.java +61 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.input; import android.annotation.Nullable; import android.hardware.input.TouchCalibration; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.Slog; import android.util.SparseIntArray; Loading @@ -42,6 +43,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.OptionalInt; Loading Loading @@ -121,6 +123,7 @@ final class PersistentDataStore { return false; } @Nullable public String getCurrentKeyboardLayout(String inputDeviceDescriptor) { InputDeviceState state = getInputDeviceState(inputDeviceDescriptor); return state != null ? state.getCurrentKeyboardLayout() : null; Loading @@ -136,6 +139,22 @@ final class PersistentDataStore { return false; } @Nullable public String getKeyboardLayout(String inputDeviceDescriptor, String key) { InputDeviceState state = getInputDeviceState(inputDeviceDescriptor); return state != null ? state.getKeyboardLayout(key) : null; } public boolean setKeyboardLayout(String inputDeviceDescriptor, String key, String keyboardLayoutDescriptor) { InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor); if (state.setKeyboardLayout(key, keyboardLayoutDescriptor)) { setDirty(); return true; } return false; } public String[] getKeyboardLayouts(String inputDeviceDescriptor) { InputDeviceState state = getInputDeviceState(inputDeviceDescriptor); if (state == null) { Loading Loading @@ -387,6 +406,8 @@ final class PersistentDataStore { private final ArrayList<String> mKeyboardLayouts = new ArrayList<String>(); private final SparseIntArray mKeyboardBacklightBrightnessMap = new SparseIntArray(); private final Map<String, String> mKeyboardLayoutMap = new ArrayMap<>(); public TouchCalibration getTouchCalibration(int surfaceRotation) { try { return mTouchCalibration[surfaceRotation]; Loading @@ -409,6 +430,15 @@ final class PersistentDataStore { } } @Nullable public String getKeyboardLayout(String key) { return mKeyboardLayoutMap.get(key); } public boolean setKeyboardLayout(String key, String keyboardLayout) { return !Objects.equals(mKeyboardLayoutMap.put(key, keyboardLayout), keyboardLayout); } @Nullable public String getCurrentKeyboardLayout() { return mCurrentKeyboardLayout; Loading Loading @@ -507,6 +537,18 @@ final class PersistentDataStore { changed = true; } } List<String> removedEntries = new ArrayList<>(); for (String key : mKeyboardLayoutMap.keySet()) { if (!availableKeyboardLayouts.contains(mKeyboardLayoutMap.get(key))) { removedEntries.add(key); } } if (!removedEntries.isEmpty()) { for (String key : removedEntries) { mKeyboardLayoutMap.remove(key); } changed = true; } return changed; } Loading Loading @@ -534,6 +576,18 @@ final class PersistentDataStore { } mCurrentKeyboardLayout = descriptor; } } else if (parser.getName().equals("keyed-keyboard-layout")) { String key = parser.getAttributeValue(null, "key"); if (key == null) { throw new XmlPullParserException( "Missing key attribute on keyed-keyboard-layout."); } String layout = parser.getAttributeValue(null, "layout"); if (layout == null) { throw new XmlPullParserException( "Missing layout attribute on keyed-keyboard-layout."); } mKeyboardLayoutMap.put(key, layout); } else if (parser.getName().equals("light-info")) { int lightId = parser.getAttributeInt(null, "light-id"); int lightBrightness = parser.getAttributeInt(null, "light-brightness"); Loading Loading @@ -607,6 +661,13 @@ final class PersistentDataStore { serializer.endTag(null, "keyboard-layout"); } for (String key : mKeyboardLayoutMap.keySet()) { serializer.startTag(null, "keyed-keyboard-layout"); serializer.attribute(null, "key", key); serializer.attribute(null, "layout", mKeyboardLayoutMap.get(key)); serializer.endTag(null, "keyed-keyboard-layout"); } for (int i = 0; i < mKeyboardBacklightBrightnessMap.size(); i++) { serializer.startTag(null, "light-info"); serializer.attributeInt(null, "light-id", mKeyboardBacklightBrightnessMap.keyAt(i)); Loading services/tests/servicestests/res/raw/dummy_keyboard_layout.kcm 0 → 100644 +311 −0 Original line number Diff line number Diff line # Copyright (C) 2023 The Android Open Source Project # # 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. # # English (US) keyboard layout. # Unlike the default (generic) keyboard layout, English (US) does not contain any # special ALT characters. # type OVERLAY ### ROW 1 key GRAVE { label: '`' base: '`' shift: '~' } key 1 { label: '1' base: '1' shift: '!' } key 2 { label: '2' base: '2' shift: '@' } key 3 { label: '3' base: '3' shift: '#' } key 4 { label: '4' base: '4' shift: '$' } key 5 { label: '5' base: '5' shift: '%' } key 6 { label: '6' base: '6' shift: '^' } key 7 { label: '7' base: '7' shift: '&' } key 8 { label: '8' base: '8' shift: '*' } key 9 { label: '9' base: '9' shift: '(' } key 0 { label: '0' base: '0' shift: ')' } key MINUS { label: '-' base: '-' shift: '_' } key EQUALS { label: '=' base: '=' shift: '+' } ### ROW 2 key Q { label: 'Q' base: 'q' shift, capslock: 'Q' } key W { label: 'W' base: 'w' shift, capslock: 'W' } key E { label: 'E' base: 'e' shift, capslock: 'E' } key R { label: 'R' base: 'r' shift, capslock: 'R' } key T { label: 'T' base: 't' shift, capslock: 'T' } key Y { label: 'Y' base: 'y' shift, capslock: 'Y' } key U { label: 'U' base: 'u' shift, capslock: 'U' } key I { label: 'I' base: 'i' shift, capslock: 'I' } key O { label: 'O' base: 'o' shift, capslock: 'O' } key P { label: 'P' base: 'p' shift, capslock: 'P' } key LEFT_BRACKET { label: '[' base: '[' shift: '{' } key RIGHT_BRACKET { label: ']' base: ']' shift: '}' } key BACKSLASH { label: '\\' base: '\\' shift: '|' } ### ROW 3 key A { label: 'A' base: 'a' shift, capslock: 'A' } key S { label: 'S' base: 's' shift, capslock: 'S' } key D { label: 'D' base: 'd' shift, capslock: 'D' } key F { label: 'F' base: 'f' shift, capslock: 'F' } key G { label: 'G' base: 'g' shift, capslock: 'G' } key H { label: 'H' base: 'h' shift, capslock: 'H' } key J { label: 'J' base: 'j' shift, capslock: 'J' } key K { label: 'K' base: 'k' shift, capslock: 'K' } key L { label: 'L' base: 'l' shift, capslock: 'L' } key SEMICOLON { label: ';' base: ';' shift: ':' } key APOSTROPHE { label: '\'' base: '\'' shift: '"' } ### ROW 4 key Z { label: 'Z' base: 'z' shift, capslock: 'Z' } key X { label: 'X' base: 'x' shift, capslock: 'X' } key C { label: 'C' base: 'c' shift, capslock: 'C' } key V { label: 'V' base: 'v' shift, capslock: 'V' } key B { label: 'B' base: 'b' shift, capslock: 'B' } key N { label: 'N' base: 'n' shift, capslock: 'N' } key M { label: 'M' base: 'm' shift, capslock: 'M' } key COMMA { label: ',' base: ',' shift: '<' } key PERIOD { label: '.' base: '.' shift: '>' } key SLASH { label: '/' base: '/' shift: '?' } Loading
core/java/android/hardware/input/KeyboardLayout.java +65 −20 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.os.Parcelable; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * Describes a keyboard layout. Loading @@ -30,6 +31,37 @@ import java.util.Map; * @hide */ public final class KeyboardLayout implements Parcelable, Comparable<KeyboardLayout> { /** Undefined keyboard layout */ public static final String LAYOUT_TYPE_UNDEFINED = "undefined"; /** Qwerty-based keyboard layout */ public static final String LAYOUT_TYPE_QWERTY = "qwerty"; /** Qwertz-based keyboard layout */ public static final String LAYOUT_TYPE_QWERTZ = "qwertz"; /** Azerty-based keyboard layout */ public static final String LAYOUT_TYPE_AZERTY = "azerty"; /** Dvorak keyboard layout */ public static final String LAYOUT_TYPE_DVORAK = "dvorak"; /** Colemak keyboard layout */ public static final String LAYOUT_TYPE_COLEMAK = "colemak"; /** Workman keyboard layout */ public static final String LAYOUT_TYPE_WORKMAN = "workman"; /** Turkish-F keyboard layout */ public static final String LAYOUT_TYPE_TURKISH_F = "turkish_f"; /** Turkish-Q keyboard layout */ public static final String LAYOUT_TYPE_TURKISH_Q = "turkish_q"; /** Keyboard layout that has been enhanced with a large number of extra characters */ public static final String LAYOUT_TYPE_EXTENDED = "extended"; private final String mDescriptor; private final String mLabel; private final String mCollection; Loading @@ -42,31 +74,24 @@ public final class KeyboardLayout implements Parcelable, Comparable<KeyboardLayo /** Currently supported Layout types in the KCM files */ private enum LayoutType { UNDEFINED(0, "undefined"), QWERTY(1, "qwerty"), QWERTZ(2, "qwertz"), AZERTY(3, "azerty"), DVORAK(4, "dvorak"), COLEMAK(5, "colemak"), WORKMAN(6, "workman"), TURKISH_F(7, "turkish_f"), TURKISH_Q(8, "turkish_q"), EXTENDED(9, "extended"); UNDEFINED(0, LAYOUT_TYPE_UNDEFINED), QWERTY(1, LAYOUT_TYPE_QWERTY), QWERTZ(2, LAYOUT_TYPE_QWERTZ), AZERTY(3, LAYOUT_TYPE_AZERTY), DVORAK(4, LAYOUT_TYPE_DVORAK), COLEMAK(5, LAYOUT_TYPE_COLEMAK), WORKMAN(6, LAYOUT_TYPE_WORKMAN), TURKISH_F(7, LAYOUT_TYPE_TURKISH_F), TURKISH_Q(8, LAYOUT_TYPE_TURKISH_Q), EXTENDED(9, LAYOUT_TYPE_EXTENDED); private final int mValue; private final String mName; private static final Map<Integer, LayoutType> VALUE_TO_ENUM_MAP = new HashMap<>(); static { VALUE_TO_ENUM_MAP.put(UNDEFINED.mValue, UNDEFINED); VALUE_TO_ENUM_MAP.put(QWERTY.mValue, QWERTY); VALUE_TO_ENUM_MAP.put(QWERTZ.mValue, QWERTZ); VALUE_TO_ENUM_MAP.put(AZERTY.mValue, AZERTY); VALUE_TO_ENUM_MAP.put(DVORAK.mValue, DVORAK); VALUE_TO_ENUM_MAP.put(COLEMAK.mValue, COLEMAK); VALUE_TO_ENUM_MAP.put(WORKMAN.mValue, WORKMAN); VALUE_TO_ENUM_MAP.put(TURKISH_F.mValue, TURKISH_F); VALUE_TO_ENUM_MAP.put(TURKISH_Q.mValue, TURKISH_Q); VALUE_TO_ENUM_MAP.put(EXTENDED.mValue, EXTENDED); for (LayoutType type : LayoutType.values()) { VALUE_TO_ENUM_MAP.put(type.mValue, type); } } private static LayoutType of(int value) { Loading Loading @@ -206,6 +231,9 @@ public final class KeyboardLayout implements Parcelable, Comparable<KeyboardLayo // Note that these arguments are intentionally flipped since you want higher priority // keyboards to be listed before lower priority keyboards. int result = Integer.compare(another.mPriority, mPriority); if (result == 0) { result = Integer.compare(mLayoutType.mValue, another.mLayoutType.mValue); } if (result == 0) { result = mLabel.compareToIgnoreCase(another.mLabel); } Loading @@ -226,4 +254,21 @@ public final class KeyboardLayout implements Parcelable, Comparable<KeyboardLayo + ", vendorId: " + mVendorId + ", productId: " + mProductId; } /** * Check if the provided layout type is supported/valid. * * @param layoutName name of layout type * @return {@code true} if the provided layout type is supported/valid. */ public static boolean isLayoutTypeValid(@NonNull String layoutName) { Objects.requireNonNull(layoutName, "Provided layout name should not be null"); for (LayoutType layoutType : LayoutType.values()) { if (layoutName.equals(layoutType.getName())) { return true; } } // Layout doesn't match any supported layout types return false; } }
services/core/java/com/android/server/input/InputManagerService.java +1 −4 Original line number Diff line number Diff line Loading @@ -3346,10 +3346,7 @@ public class InputManagerService extends IInputManager.Stub public void onInputMethodSubtypeChangedForKeyboardLayoutMapping(@UserIdInt int userId, @Nullable InputMethodSubtypeHandle subtypeHandle, @Nullable InputMethodSubtype subtype) { if (DEBUG) { Slog.i(TAG, "InputMethodSubtype changed: userId=" + userId + " subtypeHandle=" + subtypeHandle); } mKeyboardLayoutManager.onInputMethodSubtypeChanged(userId, subtypeHandle, subtype); } @Override Loading
services/core/java/com/android/server/input/KeyboardLayoutManager.java +433 −42 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/input/PersistentDataStore.java +61 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.input; import android.annotation.Nullable; import android.hardware.input.TouchCalibration; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.Slog; import android.util.SparseIntArray; Loading @@ -42,6 +43,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.OptionalInt; Loading Loading @@ -121,6 +123,7 @@ final class PersistentDataStore { return false; } @Nullable public String getCurrentKeyboardLayout(String inputDeviceDescriptor) { InputDeviceState state = getInputDeviceState(inputDeviceDescriptor); return state != null ? state.getCurrentKeyboardLayout() : null; Loading @@ -136,6 +139,22 @@ final class PersistentDataStore { return false; } @Nullable public String getKeyboardLayout(String inputDeviceDescriptor, String key) { InputDeviceState state = getInputDeviceState(inputDeviceDescriptor); return state != null ? state.getKeyboardLayout(key) : null; } public boolean setKeyboardLayout(String inputDeviceDescriptor, String key, String keyboardLayoutDescriptor) { InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor); if (state.setKeyboardLayout(key, keyboardLayoutDescriptor)) { setDirty(); return true; } return false; } public String[] getKeyboardLayouts(String inputDeviceDescriptor) { InputDeviceState state = getInputDeviceState(inputDeviceDescriptor); if (state == null) { Loading Loading @@ -387,6 +406,8 @@ final class PersistentDataStore { private final ArrayList<String> mKeyboardLayouts = new ArrayList<String>(); private final SparseIntArray mKeyboardBacklightBrightnessMap = new SparseIntArray(); private final Map<String, String> mKeyboardLayoutMap = new ArrayMap<>(); public TouchCalibration getTouchCalibration(int surfaceRotation) { try { return mTouchCalibration[surfaceRotation]; Loading @@ -409,6 +430,15 @@ final class PersistentDataStore { } } @Nullable public String getKeyboardLayout(String key) { return mKeyboardLayoutMap.get(key); } public boolean setKeyboardLayout(String key, String keyboardLayout) { return !Objects.equals(mKeyboardLayoutMap.put(key, keyboardLayout), keyboardLayout); } @Nullable public String getCurrentKeyboardLayout() { return mCurrentKeyboardLayout; Loading Loading @@ -507,6 +537,18 @@ final class PersistentDataStore { changed = true; } } List<String> removedEntries = new ArrayList<>(); for (String key : mKeyboardLayoutMap.keySet()) { if (!availableKeyboardLayouts.contains(mKeyboardLayoutMap.get(key))) { removedEntries.add(key); } } if (!removedEntries.isEmpty()) { for (String key : removedEntries) { mKeyboardLayoutMap.remove(key); } changed = true; } return changed; } Loading Loading @@ -534,6 +576,18 @@ final class PersistentDataStore { } mCurrentKeyboardLayout = descriptor; } } else if (parser.getName().equals("keyed-keyboard-layout")) { String key = parser.getAttributeValue(null, "key"); if (key == null) { throw new XmlPullParserException( "Missing key attribute on keyed-keyboard-layout."); } String layout = parser.getAttributeValue(null, "layout"); if (layout == null) { throw new XmlPullParserException( "Missing layout attribute on keyed-keyboard-layout."); } mKeyboardLayoutMap.put(key, layout); } else if (parser.getName().equals("light-info")) { int lightId = parser.getAttributeInt(null, "light-id"); int lightBrightness = parser.getAttributeInt(null, "light-brightness"); Loading Loading @@ -607,6 +661,13 @@ final class PersistentDataStore { serializer.endTag(null, "keyboard-layout"); } for (String key : mKeyboardLayoutMap.keySet()) { serializer.startTag(null, "keyed-keyboard-layout"); serializer.attribute(null, "key", key); serializer.attribute(null, "layout", mKeyboardLayoutMap.get(key)); serializer.endTag(null, "keyed-keyboard-layout"); } for (int i = 0; i < mKeyboardBacklightBrightnessMap.size(); i++) { serializer.startTag(null, "light-info"); serializer.attributeInt(null, "light-id", mKeyboardBacklightBrightnessMap.keyAt(i)); Loading
services/tests/servicestests/res/raw/dummy_keyboard_layout.kcm 0 → 100644 +311 −0 Original line number Diff line number Diff line # Copyright (C) 2023 The Android Open Source Project # # 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. # # English (US) keyboard layout. # Unlike the default (generic) keyboard layout, English (US) does not contain any # special ALT characters. # type OVERLAY ### ROW 1 key GRAVE { label: '`' base: '`' shift: '~' } key 1 { label: '1' base: '1' shift: '!' } key 2 { label: '2' base: '2' shift: '@' } key 3 { label: '3' base: '3' shift: '#' } key 4 { label: '4' base: '4' shift: '$' } key 5 { label: '5' base: '5' shift: '%' } key 6 { label: '6' base: '6' shift: '^' } key 7 { label: '7' base: '7' shift: '&' } key 8 { label: '8' base: '8' shift: '*' } key 9 { label: '9' base: '9' shift: '(' } key 0 { label: '0' base: '0' shift: ')' } key MINUS { label: '-' base: '-' shift: '_' } key EQUALS { label: '=' base: '=' shift: '+' } ### ROW 2 key Q { label: 'Q' base: 'q' shift, capslock: 'Q' } key W { label: 'W' base: 'w' shift, capslock: 'W' } key E { label: 'E' base: 'e' shift, capslock: 'E' } key R { label: 'R' base: 'r' shift, capslock: 'R' } key T { label: 'T' base: 't' shift, capslock: 'T' } key Y { label: 'Y' base: 'y' shift, capslock: 'Y' } key U { label: 'U' base: 'u' shift, capslock: 'U' } key I { label: 'I' base: 'i' shift, capslock: 'I' } key O { label: 'O' base: 'o' shift, capslock: 'O' } key P { label: 'P' base: 'p' shift, capslock: 'P' } key LEFT_BRACKET { label: '[' base: '[' shift: '{' } key RIGHT_BRACKET { label: ']' base: ']' shift: '}' } key BACKSLASH { label: '\\' base: '\\' shift: '|' } ### ROW 3 key A { label: 'A' base: 'a' shift, capslock: 'A' } key S { label: 'S' base: 's' shift, capslock: 'S' } key D { label: 'D' base: 'd' shift, capslock: 'D' } key F { label: 'F' base: 'f' shift, capslock: 'F' } key G { label: 'G' base: 'g' shift, capslock: 'G' } key H { label: 'H' base: 'h' shift, capslock: 'H' } key J { label: 'J' base: 'j' shift, capslock: 'J' } key K { label: 'K' base: 'k' shift, capslock: 'K' } key L { label: 'L' base: 'l' shift, capslock: 'L' } key SEMICOLON { label: ';' base: ';' shift: ':' } key APOSTROPHE { label: '\'' base: '\'' shift: '"' } ### ROW 4 key Z { label: 'Z' base: 'z' shift, capslock: 'Z' } key X { label: 'X' base: 'x' shift, capslock: 'X' } key C { label: 'C' base: 'c' shift, capslock: 'C' } key V { label: 'V' base: 'v' shift, capslock: 'V' } key B { label: 'B' base: 'b' shift, capslock: 'B' } key N { label: 'N' base: 'n' shift, capslock: 'N' } key M { label: 'M' base: 'm' shift, capslock: 'M' } key COMMA { label: ',' base: ',' shift: '<' } key PERIOD { label: '.' base: '.' shift: '>' } key SLASH { label: '/' base: '/' shift: '?' }