Path: blob/main/src/vs/workbench/services/keybinding/common/keymapInfo.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { isWindows, isLinux } from '../../../../base/common/platform.js';6import { getKeyboardLayoutId, IKeyboardLayoutInfo } from '../../../../platform/keyboardLayout/common/keyboardLayout.js';78function deserializeMapping(serializedMapping: ISerializedMapping) {9const mapping = serializedMapping;1011const ret: { [key: string]: any } = {};12for (const key in mapping) {13const result: (string | number)[] = mapping[key];14if (result.length) {15const value = result[0];16const withShift = result[1];17const withAltGr = result[2];18const withShiftAltGr = result[3];19const mask = Number(result[4]);20const vkey = result.length === 6 ? result[5] : undefined;21ret[key] = {22'value': value,23'vkey': vkey,24'withShift': withShift,25'withAltGr': withAltGr,26'withShiftAltGr': withShiftAltGr,27'valueIsDeadKey': (mask & 1) > 0,28'withShiftIsDeadKey': (mask & 2) > 0,29'withAltGrIsDeadKey': (mask & 4) > 0,30'withShiftAltGrIsDeadKey': (mask & 8) > 031};32} else {33ret[key] = {34'value': '',35'valueIsDeadKey': false,36'withShift': '',37'withShiftIsDeadKey': false,38'withAltGr': '',39'withAltGrIsDeadKey': false,40'withShiftAltGr': '',41'withShiftAltGrIsDeadKey': false42};43}44}4546return ret;47}4849export interface IRawMixedKeyboardMapping {50[key: string]: {51value: string;52withShift: string;53withAltGr: string;54withShiftAltGr: string;55valueIsDeadKey?: boolean;56withShiftIsDeadKey?: boolean;57withAltGrIsDeadKey?: boolean;58withShiftAltGrIsDeadKey?: boolean;5960};61}6263interface ISerializedMapping {64[key: string]: (string | number)[];65}6667export interface IKeymapInfo {68layout: IKeyboardLayoutInfo;69secondaryLayouts: IKeyboardLayoutInfo[];70mapping: ISerializedMapping;71isUserKeyboardLayout?: boolean;72}7374export class KeymapInfo {75mapping: IRawMixedKeyboardMapping;76isUserKeyboardLayout: boolean;7778constructor(public layout: IKeyboardLayoutInfo, public secondaryLayouts: IKeyboardLayoutInfo[], keyboardMapping: ISerializedMapping, isUserKeyboardLayout?: boolean) {79this.mapping = deserializeMapping(keyboardMapping);80this.isUserKeyboardLayout = !!isUserKeyboardLayout;81this.layout.isUserKeyboardLayout = !!isUserKeyboardLayout;82}8384static createKeyboardLayoutFromDebugInfo(layout: IKeyboardLayoutInfo, value: IRawMixedKeyboardMapping, isUserKeyboardLayout?: boolean): KeymapInfo {85const keyboardLayoutInfo = new KeymapInfo(layout, [], {}, true);86keyboardLayoutInfo.mapping = value;87return keyboardLayoutInfo;88}8990update(other: KeymapInfo) {91this.layout = other.layout;92this.secondaryLayouts = other.secondaryLayouts;93this.mapping = other.mapping;94this.isUserKeyboardLayout = other.isUserKeyboardLayout;95this.layout.isUserKeyboardLayout = other.isUserKeyboardLayout;96}9798getScore(other: IRawMixedKeyboardMapping): number {99let score = 0;100for (const key in other) {101if (isWindows && (key === 'Backslash' || key === 'KeyQ')) {102// keymap from Chromium is probably wrong.103continue;104}105106if (isLinux && (key === 'Backspace' || key === 'Escape')) {107// native keymap doesn't align with keyboard event108continue;109}110111const currentMapping = this.mapping[key];112113if (currentMapping === undefined) {114score -= 1;115}116117const otherMapping = other[key];118119if (currentMapping && otherMapping && currentMapping.value !== otherMapping.value) {120score -= 1;121}122}123124return score;125}126127equal(other: KeymapInfo): boolean {128if (this.isUserKeyboardLayout !== other.isUserKeyboardLayout) {129return false;130}131132if (getKeyboardLayoutId(this.layout) !== getKeyboardLayoutId(other.layout)) {133return false;134}135136return this.fuzzyEqual(other.mapping);137}138139fuzzyEqual(other: IRawMixedKeyboardMapping): boolean {140for (const key in other) {141if (isWindows && (key === 'Backslash' || key === 'KeyQ')) {142// keymap from Chromium is probably wrong.143continue;144}145if (this.mapping[key] === undefined) {146return false;147}148149const currentMapping = this.mapping[key];150const otherMapping = other[key];151152if (currentMapping.value !== otherMapping.value) {153return false;154}155}156157return true;158}159}160161162