Update to VS Code 1.52.1
This commit is contained in:
@@ -28,7 +28,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ExtensionMessageCollector, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { IUserKeybindingItem, KeybindingIO, OutputBuilder } from 'vs/workbench/services/keybinding/common/keybindingIO';
|
||||
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { IKeyboardMapper } from 'vs/platform/keyboardLayout/common/keyboardMapper';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
@@ -40,8 +40,8 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { parse } from 'vs/base/common/json';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { IKeymapService } from 'vs/workbench/services/keybinding/common/keymapInfo';
|
||||
import { getDispatchConfig } from 'vs/workbench/services/keybinding/common/dispatchConfig';
|
||||
import { IKeyboardLayoutService } from 'vs/platform/keyboardLayout/common/keyboardLayout';
|
||||
import { getDispatchConfig } from 'vs/platform/keyboardLayout/common/dispatchConfig';
|
||||
import { isArray } from 'vs/base/common/types';
|
||||
import { INavigatorWithKeyboard, IKeyboard } from 'vs/workbench/services/keybinding/browser/navigatorKeyboard';
|
||||
import { ScanCode, ScanCodeUtils, IMMUTABLE_CODE_TO_KEY_CODE } from 'vs/base/common/scanCode';
|
||||
@@ -49,6 +49,7 @@ import { flatten } from 'vs/base/common/arrays';
|
||||
import { BrowserFeatures, KeyboardSupport } from 'vs/base/browser/canIUse';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { dirname } from 'vs/base/common/resources';
|
||||
|
||||
interface ContributedKeyBinding {
|
||||
command: string;
|
||||
@@ -194,7 +195,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IFileService fileService: IFileService,
|
||||
@ILogService logService: ILogService,
|
||||
@IKeymapService private readonly keymapService: IKeymapService
|
||||
@IKeyboardLayoutService private readonly keyboardLayoutService: IKeyboardLayoutService
|
||||
) {
|
||||
super(contextKeyService, commandService, telemetryService, notificationService, logService);
|
||||
|
||||
@@ -209,13 +210,13 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
}
|
||||
|
||||
dispatchConfig = newDispatchConfig;
|
||||
this._keyboardMapper = this.keymapService.getKeyboardMapper(dispatchConfig);
|
||||
this._keyboardMapper = this.keyboardLayoutService.getKeyboardMapper(dispatchConfig);
|
||||
this.updateResolver({ source: KeybindingSource.Default });
|
||||
});
|
||||
|
||||
this._keyboardMapper = this.keymapService.getKeyboardMapper(dispatchConfig);
|
||||
this.keymapService.onDidChangeKeyboardMapper(() => {
|
||||
this._keyboardMapper = this.keymapService.getKeyboardMapper(dispatchConfig);
|
||||
this._keyboardMapper = this.keyboardLayoutService.getKeyboardMapper(dispatchConfig);
|
||||
this.keyboardLayoutService.onDidChangeKeyboardLayout(() => {
|
||||
this._keyboardMapper = this.keyboardLayoutService.getKeyboardMapper(dispatchConfig);
|
||||
this.updateResolver({ source: KeybindingSource.Default });
|
||||
});
|
||||
|
||||
@@ -261,7 +262,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
this.isComposingGlobalContextKey.set(false);
|
||||
}));
|
||||
|
||||
let data = this.keymapService.getCurrentKeyboardLayout();
|
||||
let data = this.keyboardLayoutService.getCurrentKeyboardLayout();
|
||||
/* __GDPR__FRAGMENT__
|
||||
"IKeyboardLayoutInfo" : {
|
||||
"name" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
@@ -325,16 +326,16 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
}
|
||||
|
||||
public _dumpDebugInfo(): string {
|
||||
const layoutInfo = JSON.stringify(this.keymapService.getCurrentKeyboardLayout(), null, '\t');
|
||||
const layoutInfo = JSON.stringify(this.keyboardLayoutService.getCurrentKeyboardLayout(), null, '\t');
|
||||
const mapperInfo = this._keyboardMapper.dumpDebugInfo();
|
||||
const rawMapping = JSON.stringify(this.keymapService.getRawKeyboardMapping(), null, '\t');
|
||||
const rawMapping = JSON.stringify(this.keyboardLayoutService.getRawKeyboardMapping(), null, '\t');
|
||||
return `Layout info:\n${layoutInfo}\n${mapperInfo}\n\nRaw mapping:\n${rawMapping}`;
|
||||
}
|
||||
|
||||
public _dumpDebugInfoJSON(): string {
|
||||
const info = {
|
||||
layout: this.keymapService.getCurrentKeyboardLayout(),
|
||||
rawMapping: this.keymapService.getRawKeyboardMapping()
|
||||
layout: this.keyboardLayoutService.getCurrentKeyboardLayout(),
|
||||
rawMapping: this.keyboardLayoutService.getRawKeyboardMapping()
|
||||
};
|
||||
return JSON.stringify(info, null, '\t');
|
||||
}
|
||||
@@ -371,7 +372,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
const keybinding = item.keybinding;
|
||||
if (!keybinding) {
|
||||
// This might be a removal keybinding item in user settings => accept it
|
||||
result[resultLen++] = new ResolvedKeybindingItem(undefined, item.command, item.commandArgs, when, isDefault, item.extensionId);
|
||||
result[resultLen++] = new ResolvedKeybindingItem(undefined, item.command, item.commandArgs, when, isDefault, item.extensionId, item.isBuiltinExtension);
|
||||
} else {
|
||||
if (this._assertBrowserConflicts(keybinding, item.command)) {
|
||||
continue;
|
||||
@@ -380,7 +381,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
const resolvedKeybindings = this.resolveKeybinding(keybinding);
|
||||
for (let i = resolvedKeybindings.length - 1; i >= 0; i--) {
|
||||
const resolvedKeybinding = resolvedKeybindings[i];
|
||||
result[resultLen++] = new ResolvedKeybindingItem(resolvedKeybinding, item.command, item.commandArgs, when, isDefault, item.extensionId);
|
||||
result[resultLen++] = new ResolvedKeybindingItem(resolvedKeybinding, item.command, item.commandArgs, when, isDefault, item.extensionId, item.isBuiltinExtension);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -395,11 +396,11 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
const parts = item.parts;
|
||||
if (parts.length === 0) {
|
||||
// This might be a removal keybinding item in user settings => accept it
|
||||
result[resultLen++] = new ResolvedKeybindingItem(undefined, item.command, item.commandArgs, when, isDefault, null);
|
||||
result[resultLen++] = new ResolvedKeybindingItem(undefined, item.command, item.commandArgs, when, isDefault, null, false);
|
||||
} else {
|
||||
const resolvedKeybindings = this._keyboardMapper.resolveUserBinding(parts);
|
||||
for (const resolvedKeybinding of resolvedKeybindings) {
|
||||
result[resultLen++] = new ResolvedKeybindingItem(resolvedKeybinding, item.command, item.commandArgs, when, isDefault, null);
|
||||
result[resultLen++] = new ResolvedKeybindingItem(resolvedKeybinding, item.command, item.commandArgs, when, isDefault, null, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -440,23 +441,26 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
partModifiersMask |= KeyMod.WinCtrl;
|
||||
}
|
||||
|
||||
if ((partModifiersMask & modifiersMask) === KeyMod.CtrlCmd && part.keyCode === KeyCode.KEY_W) {
|
||||
// console.warn('Ctrl/Cmd+W keybindings should not be used by default in web. Offender: ', kb.getHashCode(), ' for ', commandId);
|
||||
// re https://github.com/microsoft/vscode/issues/108788.
|
||||
// since we introduced `window.confirmBeforeQuit`, we should probably not unbind cmd+w/t/n.
|
||||
|
||||
return true;
|
||||
}
|
||||
// if ((partModifiersMask & modifiersMask) === KeyMod.CtrlCmd && part.keyCode === KeyCode.KEY_W) {
|
||||
// // console.warn('Ctrl/Cmd+W keybindings should not be used by default in web. Offender: ', kb.getHashCode(), ' for ', commandId);
|
||||
|
||||
if ((partModifiersMask & modifiersMask) === KeyMod.CtrlCmd && part.keyCode === KeyCode.KEY_N) {
|
||||
// console.warn('Ctrl/Cmd+N keybindings should not be used by default in web. Offender: ', kb.getHashCode(), ' for ', commandId);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
// if ((partModifiersMask & modifiersMask) === KeyMod.CtrlCmd && part.keyCode === KeyCode.KEY_N) {
|
||||
// // console.warn('Ctrl/Cmd+N keybindings should not be used by default in web. Offender: ', kb.getHashCode(), ' for ', commandId);
|
||||
|
||||
if ((partModifiersMask & modifiersMask) === KeyMod.CtrlCmd && part.keyCode === KeyCode.KEY_T) {
|
||||
// console.warn('Ctrl/Cmd+T keybindings should not be used by default in web. Offender: ', kb.getHashCode(), ' for ', commandId);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
// if ((partModifiersMask & modifiersMask) === KeyMod.CtrlCmd && part.keyCode === KeyCode.KEY_T) {
|
||||
// // console.warn('Ctrl/Cmd+T keybindings should not be used by default in web. Offender: ', kb.getHashCode(), ' for ', commandId);
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
if ((partModifiersMask & modifiersMask) === (KeyMod.CtrlCmd | KeyMod.Alt) && (part.keyCode === KeyCode.LeftArrow || part.keyCode === KeyCode.RightArrow)) {
|
||||
// console.warn('Ctrl/Cmd+Arrow keybindings should not be used by default in web. Offender: ', kb.getHashCode(), ' for ', commandId);
|
||||
@@ -479,7 +483,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
}
|
||||
|
||||
public resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): ResolvedKeybinding {
|
||||
this.keymapService.validateCurrentKeyboardMapping(keyboardEvent);
|
||||
this.keyboardLayoutService.validateCurrentKeyboardMapping(keyboardEvent);
|
||||
return this._keyboardMapper.resolveKeyboardEvent(keyboardEvent);
|
||||
}
|
||||
|
||||
@@ -550,7 +554,8 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
mac: mac ? { primary: KeybindingParser.parseKeybinding(mac, OS) } : null,
|
||||
linux: linux ? { primary: KeybindingParser.parseKeybinding(linux, OS) } : null,
|
||||
win: win ? { primary: KeybindingParser.parseKeybinding(win, OS) } : null,
|
||||
extensionId: extensionId.value
|
||||
extensionId: extensionId.value,
|
||||
isBuiltinExtension: isBuiltin
|
||||
};
|
||||
|
||||
if (!desc.primary && !desc.mac && !desc.linux && !desc.win) {
|
||||
@@ -626,7 +631,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
}
|
||||
// consult the KeyboardMapperFactory to check the given event for
|
||||
// a printable value.
|
||||
const mapping = this.keymapService.getRawKeyboardMapping();
|
||||
const mapping = this.keyboardLayoutService.getRawKeyboardMapping();
|
||||
if (!mapping) {
|
||||
return false;
|
||||
}
|
||||
@@ -658,6 +663,7 @@ class UserKeybindings extends Disposable {
|
||||
) {
|
||||
super();
|
||||
|
||||
this._register(fileService.watch(dirname(keybindingsResource)));
|
||||
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.reload().then(changed => {
|
||||
if (changed) {
|
||||
this._onDidChange.fire();
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IKeymapService, IKeyboardLayoutInfo, IKeyboardMapping, IWindowsKeyboardMapping, KeymapInfo, IRawMixedKeyboardMapping, getKeyboardLayoutId, IKeymapInfo } from 'vs/workbench/services/keybinding/common/keymapInfo';
|
||||
import { KeymapInfo, IRawMixedKeyboardMapping, IKeymapInfo } from 'vs/workbench/services/keybinding/common/keymapInfo';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { DispatchConfig } from 'vs/workbench/services/keybinding/common/dispatchConfig';
|
||||
import { IKeyboardMapper, CachedKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { DispatchConfig } from 'vs/platform/keyboardLayout/common/dispatchConfig';
|
||||
import { IKeyboardMapper, CachedKeyboardMapper } from 'vs/platform/keyboardLayout/common/keyboardMapper';
|
||||
import { OS, OperatingSystem, isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
import { WindowsKeyboardMapper } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper';
|
||||
import { MacLinuxFallbackKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxFallbackKeyboardMapper';
|
||||
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IMacLinuxKeyboardMapping, MacLinuxKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxKeyboardMapper';
|
||||
import { MacLinuxKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxKeyboardMapper';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
@@ -29,6 +29,7 @@ import { INavigatorWithKeyboard } from 'vs/workbench/services/keybinding/browser
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { getKeyboardLayoutId, IKeyboardLayoutInfo, IKeyboardLayoutService, IKeyboardMapping, IMacLinuxKeyboardMapping, IWindowsKeyboardMapping } from 'vs/platform/keyboardLayout/common/keyboardLayout';
|
||||
|
||||
export class BrowserKeyboardMapperFactoryBase {
|
||||
// keyboard mapper
|
||||
@@ -502,11 +503,11 @@ class UserKeyboardLayout extends Disposable {
|
||||
|
||||
}
|
||||
|
||||
class BrowserKeymapService extends Disposable implements IKeymapService {
|
||||
export class BrowserKeyboardLayoutService extends Disposable implements IKeyboardLayoutService {
|
||||
public _serviceBrand: undefined;
|
||||
|
||||
private readonly _onDidChangeKeyboardMapper = new Emitter<void>();
|
||||
public readonly onDidChangeKeyboardMapper: Event<void> = this._onDidChangeKeyboardMapper.event;
|
||||
private readonly _onDidChangeKeyboardLayout = new Emitter<void>();
|
||||
public readonly onDidChangeKeyboardLayout: Event<void> = this._onDidChangeKeyboardLayout.event;
|
||||
|
||||
private _userKeyboardLayout: UserKeyboardLayout;
|
||||
|
||||
@@ -592,7 +593,7 @@ class BrowserKeymapService extends Disposable implements IKeymapService {
|
||||
|
||||
registerKeyboardListener() {
|
||||
this.layoutChangeListener.value = this._factory.onDidChangeKeyboardMapper(() => {
|
||||
this._onDidChangeKeyboardMapper.fire();
|
||||
this._onDidChangeKeyboardLayout.fire();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -617,7 +618,7 @@ class BrowserKeymapService extends Disposable implements IKeymapService {
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IKeymapService, BrowserKeymapService, true);
|
||||
registerSingleton(IKeyboardLayoutService, BrowserKeyboardLayoutService, true);
|
||||
|
||||
// Configuration
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigExtensions.Configuration);
|
||||
@@ -1,17 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
export const enum DispatchConfig {
|
||||
Code,
|
||||
KeyCode
|
||||
}
|
||||
|
||||
export function getDispatchConfig(configurationService: IConfigurationService): DispatchConfig {
|
||||
const keyboard = configurationService.getValue('keyboard');
|
||||
const r = (keyboard ? (<any>keyboard).dispatch : null);
|
||||
return (r === 'keyCode' ? DispatchConfig.KeyCode : DispatchConfig.Code);
|
||||
}
|
||||
@@ -33,6 +33,8 @@ export interface IKeybindingEditingService {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
addKeybinding(keybindingItem: ResolvedKeybindingItem, key: string, when: string | undefined): Promise<void>;
|
||||
|
||||
editKeybinding(keybindingItem: ResolvedKeybindingItem, key: string, when: string | undefined): Promise<void>;
|
||||
|
||||
removeKeybinding(keybindingItem: ResolvedKeybindingItem): Promise<void>;
|
||||
@@ -58,8 +60,12 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
|
||||
this.queue = new Queue<void>();
|
||||
}
|
||||
|
||||
addKeybinding(keybindingItem: ResolvedKeybindingItem, key: string, when: string | undefined): Promise<void> {
|
||||
return this.queue.queue(() => this.doEditKeybinding(keybindingItem, key, when, true)); // queue up writes to prevent race conditions
|
||||
}
|
||||
|
||||
editKeybinding(keybindingItem: ResolvedKeybindingItem, key: string, when: string | undefined): Promise<void> {
|
||||
return this.queue.queue(() => this.doEditKeybinding(keybindingItem, key, when)); // queue up writes to prevent race conditions
|
||||
return this.queue.queue(() => this.doEditKeybinding(keybindingItem, key, when, false)); // queue up writes to prevent race conditions
|
||||
}
|
||||
|
||||
resetKeybinding(keybindingItem: ResolvedKeybindingItem): Promise<void> {
|
||||
@@ -70,18 +76,24 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
|
||||
return this.queue.queue(() => this.doRemoveKeybinding(keybindingItem)); // queue up writes to prevent race conditions
|
||||
}
|
||||
|
||||
private doEditKeybinding(keybindingItem: ResolvedKeybindingItem, key: string, when: string | undefined): Promise<void> {
|
||||
return this.resolveAndValidate()
|
||||
.then(reference => {
|
||||
const model = reference.object.textEditorModel;
|
||||
const userKeybindingEntries = <IUserFriendlyKeybinding[]>json.parse(model.getValue());
|
||||
const userKeybindingEntryIndex = this.findUserKeybindingEntryIndex(keybindingItem, userKeybindingEntries);
|
||||
this.updateKeybinding(keybindingItem, key, when, model, userKeybindingEntryIndex);
|
||||
if (keybindingItem.isDefault && keybindingItem.resolvedKeybinding) {
|
||||
this.removeDefaultKeybinding(keybindingItem, model);
|
||||
}
|
||||
return this.save().finally(() => reference.dispose());
|
||||
});
|
||||
private async doEditKeybinding(keybindingItem: ResolvedKeybindingItem, key: string, when: string | undefined, add: boolean): Promise<void> {
|
||||
const reference = await this.resolveAndValidate();
|
||||
const model = reference.object.textEditorModel;
|
||||
if (add) {
|
||||
this.updateKeybinding(keybindingItem, key, when, model, -1);
|
||||
} else {
|
||||
const userKeybindingEntries = <IUserFriendlyKeybinding[]>json.parse(model.getValue());
|
||||
const userKeybindingEntryIndex = this.findUserKeybindingEntryIndex(keybindingItem, userKeybindingEntries);
|
||||
this.updateKeybinding(keybindingItem, key, when, model, userKeybindingEntryIndex);
|
||||
if (keybindingItem.isDefault && keybindingItem.resolvedKeybinding) {
|
||||
this.removeDefaultKeybinding(keybindingItem, model);
|
||||
}
|
||||
}
|
||||
try {
|
||||
await this.save();
|
||||
} finally {
|
||||
reference.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private doRemoveKeybinding(keybindingItem: ResolvedKeybindingItem): Promise<void> {
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Keybinding, ResolvedKeybinding, SimpleKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { ScanCodeBinding } from 'vs/base/common/scanCode';
|
||||
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
|
||||
export interface IKeyboardMapper {
|
||||
dumpDebugInfo(): string;
|
||||
resolveKeybinding(keybinding: Keybinding): ResolvedKeybinding[];
|
||||
resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): ResolvedKeybinding;
|
||||
resolveUserBinding(firstPart: (SimpleKeybinding | ScanCodeBinding)[]): ResolvedKeybinding[];
|
||||
}
|
||||
|
||||
export class CachedKeyboardMapper implements IKeyboardMapper {
|
||||
|
||||
private _actual: IKeyboardMapper;
|
||||
private _cache: Map<string, ResolvedKeybinding[]>;
|
||||
|
||||
constructor(actual: IKeyboardMapper) {
|
||||
this._actual = actual;
|
||||
this._cache = new Map<string, ResolvedKeybinding[]>();
|
||||
}
|
||||
|
||||
public dumpDebugInfo(): string {
|
||||
return this._actual.dumpDebugInfo();
|
||||
}
|
||||
|
||||
public resolveKeybinding(keybinding: Keybinding): ResolvedKeybinding[] {
|
||||
const hashCode = keybinding.getHashCode();
|
||||
const resolved = this._cache.get(hashCode);
|
||||
if (!resolved) {
|
||||
const r = this._actual.resolveKeybinding(keybinding);
|
||||
this._cache.set(hashCode, r);
|
||||
return r;
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
public resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): ResolvedKeybinding {
|
||||
return this._actual.resolveKeyboardEvent(keyboardEvent);
|
||||
}
|
||||
|
||||
public resolveUserBinding(parts: (SimpleKeybinding | ScanCodeBinding)[]): ResolvedKeybinding[] {
|
||||
return this._actual.resolveUserBinding(parts);
|
||||
}
|
||||
}
|
||||
@@ -3,191 +3,8 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { isWindows, isLinux } from 'vs/base/common/platform';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { DispatchConfig } from 'vs/workbench/services/keybinding/common/dispatchConfig';
|
||||
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
|
||||
|
||||
export interface IWindowsKeyMapping {
|
||||
vkey: string;
|
||||
value: string;
|
||||
withShift: string;
|
||||
withAltGr: string;
|
||||
withShiftAltGr: string;
|
||||
}
|
||||
export interface IWindowsKeyboardMapping {
|
||||
[code: string]: IWindowsKeyMapping;
|
||||
}
|
||||
export interface ILinuxKeyMapping {
|
||||
value: string;
|
||||
withShift: string;
|
||||
withAltGr: string;
|
||||
withShiftAltGr: string;
|
||||
}
|
||||
export interface ILinuxKeyboardMapping {
|
||||
[code: string]: ILinuxKeyMapping;
|
||||
}
|
||||
export interface IMacKeyMapping {
|
||||
value: string;
|
||||
withShift: string;
|
||||
withAltGr: string;
|
||||
withShiftAltGr: string;
|
||||
valueIsDeadKey: boolean;
|
||||
withShiftIsDeadKey: boolean;
|
||||
withAltGrIsDeadKey: boolean;
|
||||
withShiftAltGrIsDeadKey: boolean;
|
||||
}
|
||||
export interface IMacKeyboardMapping {
|
||||
[code: string]: IMacKeyMapping;
|
||||
}
|
||||
|
||||
export type IKeyboardMapping = IWindowsKeyboardMapping | ILinuxKeyboardMapping | IMacKeyboardMapping;
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"IKeyboardLayoutInfo" : {
|
||||
"name" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"id": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"text": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
export interface IWindowsKeyboardLayoutInfo {
|
||||
name: string;
|
||||
id: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"IKeyboardLayoutInfo" : {
|
||||
"model" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"layout": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"variant": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"options": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"rules": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
export interface ILinuxKeyboardLayoutInfo {
|
||||
model: string;
|
||||
layout: string;
|
||||
variant: string;
|
||||
options: string;
|
||||
rules: string;
|
||||
}
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"IKeyboardLayoutInfo" : {
|
||||
"id" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"lang": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"localizedName": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
export interface IMacKeyboardLayoutInfo {
|
||||
id: string;
|
||||
lang: string;
|
||||
localizedName?: string;
|
||||
}
|
||||
|
||||
export type IKeyboardLayoutInfo = (IWindowsKeyboardLayoutInfo | ILinuxKeyboardLayoutInfo | IMacKeyboardLayoutInfo) & { isUserKeyboardLayout?: boolean; isUSStandard?: true };
|
||||
|
||||
export const IKeymapService = createDecorator<IKeymapService>('keymapService');
|
||||
|
||||
export interface IKeymapService {
|
||||
readonly _serviceBrand: undefined;
|
||||
onDidChangeKeyboardMapper: Event<void>;
|
||||
getKeyboardMapper(dispatchConfig: DispatchConfig): IKeyboardMapper;
|
||||
getCurrentKeyboardLayout(): IKeyboardLayoutInfo | null;
|
||||
getAllKeyboardLayouts(): IKeyboardLayoutInfo[];
|
||||
getRawKeyboardMapping(): IKeyboardMapping | null;
|
||||
validateCurrentKeyboardMapping(keyboardEvent: IKeyboardEvent): void;
|
||||
}
|
||||
|
||||
export function areKeyboardLayoutsEqual(a: IKeyboardLayoutInfo | null, b: IKeyboardLayoutInfo | null): boolean {
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((<IWindowsKeyboardLayoutInfo>a).name && (<IWindowsKeyboardLayoutInfo>b).name && (<IWindowsKeyboardLayoutInfo>a).name === (<IWindowsKeyboardLayoutInfo>b).name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((<IMacKeyboardLayoutInfo>a).id && (<IMacKeyboardLayoutInfo>b).id && (<IMacKeyboardLayoutInfo>a).id === (<IMacKeyboardLayoutInfo>b).id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((<ILinuxKeyboardLayoutInfo>a).model &&
|
||||
(<ILinuxKeyboardLayoutInfo>b).model &&
|
||||
(<ILinuxKeyboardLayoutInfo>a).model === (<ILinuxKeyboardLayoutInfo>b).model &&
|
||||
(<ILinuxKeyboardLayoutInfo>a).layout === (<ILinuxKeyboardLayoutInfo>b).layout
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function parseKeyboardLayoutDescription(layout: IKeyboardLayoutInfo | null): { label: string, description: string } {
|
||||
if (!layout) {
|
||||
return { label: '', description: '' };
|
||||
}
|
||||
|
||||
if ((<IWindowsKeyboardLayoutInfo>layout).name) {
|
||||
// windows
|
||||
let windowsLayout = <IWindowsKeyboardLayoutInfo>layout;
|
||||
return {
|
||||
label: windowsLayout.text,
|
||||
description: ''
|
||||
};
|
||||
}
|
||||
|
||||
if ((<IMacKeyboardLayoutInfo>layout).id) {
|
||||
let macLayout = <IMacKeyboardLayoutInfo>layout;
|
||||
if (macLayout.localizedName) {
|
||||
return {
|
||||
label: macLayout.localizedName,
|
||||
description: ''
|
||||
};
|
||||
}
|
||||
|
||||
if (/^com\.apple\.keylayout\./.test(macLayout.id)) {
|
||||
return {
|
||||
label: macLayout.id.replace(/^com\.apple\.keylayout\./, '').replace(/-/, ' '),
|
||||
description: ''
|
||||
};
|
||||
}
|
||||
if (/^.*inputmethod\./.test(macLayout.id)) {
|
||||
return {
|
||||
label: macLayout.id.replace(/^.*inputmethod\./, '').replace(/[-\.]/, ' '),
|
||||
description: `Input Method (${macLayout.lang})`
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
label: macLayout.lang,
|
||||
description: ''
|
||||
};
|
||||
}
|
||||
|
||||
let linuxLayout = <ILinuxKeyboardLayoutInfo>layout;
|
||||
|
||||
return {
|
||||
label: linuxLayout.layout,
|
||||
description: ''
|
||||
};
|
||||
}
|
||||
|
||||
export function getKeyboardLayoutId(layout: IKeyboardLayoutInfo): string {
|
||||
if ((<IWindowsKeyboardLayoutInfo>layout).name) {
|
||||
return (<IWindowsKeyboardLayoutInfo>layout).name;
|
||||
}
|
||||
|
||||
if ((<IMacKeyboardLayoutInfo>layout).id) {
|
||||
return (<IMacKeyboardLayoutInfo>layout).id;
|
||||
}
|
||||
|
||||
return (<ILinuxKeyboardLayoutInfo>layout).layout;
|
||||
}
|
||||
import { getKeyboardLayoutId, IKeyboardLayoutInfo } from 'vs/platform/keyboardLayout/common/keyboardLayout';
|
||||
|
||||
function deserializeMapping(serializedMapping: ISerializedMapping) {
|
||||
let mapping = serializedMapping;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { OperatingSystem } from 'vs/base/common/platform';
|
||||
import { IMMUTABLE_CODE_TO_KEY_CODE, ScanCode, ScanCodeBinding } from 'vs/base/common/scanCode';
|
||||
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { IKeyboardMapper } from 'vs/platform/keyboardLayout/common/keyboardMapper';
|
||||
import { removeElementsAfterNulls } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,52 +8,9 @@ import { KeyCode, KeyCodeUtils, Keybinding, ResolvedKeybinding, SimpleKeybinding
|
||||
import { OperatingSystem } from 'vs/base/common/platform';
|
||||
import { IMMUTABLE_CODE_TO_KEY_CODE, IMMUTABLE_KEY_CODE_TO_CODE, ScanCode, ScanCodeBinding, ScanCodeUtils } from 'vs/base/common/scanCode';
|
||||
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { IKeyboardMapper } from 'vs/platform/keyboardLayout/common/keyboardMapper';
|
||||
import { BaseResolvedKeybinding } from 'vs/platform/keybinding/common/baseResolvedKeybinding';
|
||||
|
||||
export interface IMacLinuxKeyMapping {
|
||||
value: string;
|
||||
withShift: string;
|
||||
withAltGr: string;
|
||||
withShiftAltGr: string;
|
||||
}
|
||||
|
||||
function macLinuxKeyMappingEquals(a: IMacLinuxKeyMapping, b: IMacLinuxKeyMapping): boolean {
|
||||
if (!a && !b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
a.value === b.value
|
||||
&& a.withShift === b.withShift
|
||||
&& a.withAltGr === b.withAltGr
|
||||
&& a.withShiftAltGr === b.withShiftAltGr
|
||||
);
|
||||
}
|
||||
|
||||
export interface IMacLinuxKeyboardMapping {
|
||||
[scanCode: string]: IMacLinuxKeyMapping;
|
||||
}
|
||||
|
||||
export function macLinuxKeyboardMappingEquals(a: IMacLinuxKeyboardMapping | null, b: IMacLinuxKeyboardMapping | null): boolean {
|
||||
if (!a && !b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
for (let scanCode = 0; scanCode < ScanCode.MAX_VALUE; scanCode++) {
|
||||
const strScanCode = ScanCodeUtils.toString(scanCode);
|
||||
const aEntry = a[strScanCode];
|
||||
const bEntry = b[strScanCode];
|
||||
if (!macLinuxKeyMappingEquals(aEntry, bEntry)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
import { IMacLinuxKeyboardMapping, IMacLinuxKeyMapping } from 'vs/platform/keyboardLayout/common/keyboardLayout';
|
||||
|
||||
/**
|
||||
* A map from character to key codes.
|
||||
|
||||
@@ -9,56 +9,10 @@ import { UILabelProvider } from 'vs/base/common/keybindingLabels';
|
||||
import { OperatingSystem } from 'vs/base/common/platform';
|
||||
import { IMMUTABLE_CODE_TO_KEY_CODE, ScanCode, ScanCodeBinding, ScanCodeUtils } from 'vs/base/common/scanCode';
|
||||
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { IKeyboardMapper } from 'vs/platform/keyboardLayout/common/keyboardMapper';
|
||||
import { BaseResolvedKeybinding } from 'vs/platform/keybinding/common/baseResolvedKeybinding';
|
||||
import { removeElementsAfterNulls } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
|
||||
export interface IWindowsKeyMapping {
|
||||
vkey: string;
|
||||
value: string;
|
||||
withShift: string;
|
||||
withAltGr: string;
|
||||
withShiftAltGr: string;
|
||||
}
|
||||
|
||||
function windowsKeyMappingEquals(a: IWindowsKeyMapping, b: IWindowsKeyMapping): boolean {
|
||||
if (!a && !b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
a.vkey === b.vkey
|
||||
&& a.value === b.value
|
||||
&& a.withShift === b.withShift
|
||||
&& a.withAltGr === b.withAltGr
|
||||
&& a.withShiftAltGr === b.withShiftAltGr
|
||||
);
|
||||
}
|
||||
|
||||
export interface IWindowsKeyboardMapping {
|
||||
[scanCode: string]: IWindowsKeyMapping;
|
||||
}
|
||||
|
||||
export function windowsKeyboardMappingEquals(a: IWindowsKeyboardMapping | null, b: IWindowsKeyboardMapping | null): boolean {
|
||||
if (!a && !b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
for (let scanCode = 0; scanCode < ScanCode.MAX_VALUE; scanCode++) {
|
||||
const strScanCode = ScanCodeUtils.toString(scanCode);
|
||||
const aEntry = a[strScanCode];
|
||||
const bEntry = b[strScanCode];
|
||||
if (!windowsKeyMappingEquals(aEntry, bEntry)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
import { IWindowsKeyboardMapping } from 'vs/platform/keyboardLayout/common/keyboardLayout';
|
||||
|
||||
const LOG = false;
|
||||
function log(str: string): void {
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nativeKeymap from 'native-keymap';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IKeymapService, IKeyboardLayoutInfo, IKeyboardMapping } from 'vs/workbench/services/keybinding/common/keymapInfo';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IKeyboardMapper, CachedKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { DispatchConfig } from 'vs/workbench/services/keybinding/common/dispatchConfig';
|
||||
import { MacLinuxFallbackKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxFallbackKeyboardMapper';
|
||||
import { OS, OperatingSystem } from 'vs/base/common/platform';
|
||||
import { WindowsKeyboardMapper, windowsKeyboardMappingEquals } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper';
|
||||
import { MacLinuxKeyboardMapper, macLinuxKeyboardMappingEquals, IMacLinuxKeyboardMapping } from 'vs/workbench/services/keybinding/common/macLinuxKeyboardMapper';
|
||||
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
|
||||
export class KeyboardMapperFactory {
|
||||
public static readonly INSTANCE = new KeyboardMapperFactory();
|
||||
|
||||
private _layoutInfo: nativeKeymap.IKeyboardLayoutInfo | null;
|
||||
private _rawMapping: nativeKeymap.IKeyboardMapping | null;
|
||||
private _keyboardMapper: IKeyboardMapper | null;
|
||||
private _initialized: boolean;
|
||||
|
||||
private readonly _onDidChangeKeyboardMapper = new Emitter<void>();
|
||||
public readonly onDidChangeKeyboardMapper: Event<void> = this._onDidChangeKeyboardMapper.event;
|
||||
|
||||
private constructor() {
|
||||
this._layoutInfo = null;
|
||||
this._rawMapping = null;
|
||||
this._keyboardMapper = null;
|
||||
this._initialized = false;
|
||||
}
|
||||
|
||||
public _onKeyboardLayoutChanged(): void {
|
||||
if (this._initialized) {
|
||||
this._setKeyboardData(nativeKeymap.getCurrentKeyboardLayout(), nativeKeymap.getKeyMap());
|
||||
}
|
||||
}
|
||||
|
||||
public getKeyboardMapper(dispatchConfig: DispatchConfig): IKeyboardMapper {
|
||||
if (!this._initialized) {
|
||||
this._setKeyboardData(nativeKeymap.getCurrentKeyboardLayout(), nativeKeymap.getKeyMap());
|
||||
}
|
||||
if (dispatchConfig === DispatchConfig.KeyCode) {
|
||||
// Forcefully set to use keyCode
|
||||
return new MacLinuxFallbackKeyboardMapper(OS);
|
||||
}
|
||||
return this._keyboardMapper!;
|
||||
}
|
||||
|
||||
public getCurrentKeyboardLayout(): nativeKeymap.IKeyboardLayoutInfo | null {
|
||||
if (!this._initialized) {
|
||||
this._setKeyboardData(nativeKeymap.getCurrentKeyboardLayout(), nativeKeymap.getKeyMap());
|
||||
}
|
||||
return this._layoutInfo;
|
||||
}
|
||||
|
||||
private static _isUSStandard(_kbInfo: nativeKeymap.IKeyboardLayoutInfo): boolean {
|
||||
if (OS === OperatingSystem.Linux) {
|
||||
const kbInfo = <nativeKeymap.ILinuxKeyboardLayoutInfo>_kbInfo;
|
||||
return (kbInfo && (kbInfo.layout === 'us' || /^us,/.test(kbInfo.layout)));
|
||||
}
|
||||
|
||||
if (OS === OperatingSystem.Macintosh) {
|
||||
const kbInfo = <nativeKeymap.IMacKeyboardLayoutInfo>_kbInfo;
|
||||
return (kbInfo && kbInfo.id === 'com.apple.keylayout.US');
|
||||
}
|
||||
|
||||
if (OS === OperatingSystem.Windows) {
|
||||
const kbInfo = <nativeKeymap.IWindowsKeyboardLayoutInfo>_kbInfo;
|
||||
return (kbInfo && kbInfo.name === '00000409');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public getRawKeyboardMapping(): nativeKeymap.IKeyboardMapping | null {
|
||||
if (!this._initialized) {
|
||||
this._setKeyboardData(nativeKeymap.getCurrentKeyboardLayout(), nativeKeymap.getKeyMap());
|
||||
}
|
||||
return this._rawMapping;
|
||||
}
|
||||
|
||||
private _setKeyboardData(layoutInfo: nativeKeymap.IKeyboardLayoutInfo, rawMapping: nativeKeymap.IKeyboardMapping): void {
|
||||
this._layoutInfo = layoutInfo;
|
||||
|
||||
if (this._initialized && KeyboardMapperFactory._equals(this._rawMapping, rawMapping)) {
|
||||
// nothing to do...
|
||||
return;
|
||||
}
|
||||
|
||||
this._initialized = true;
|
||||
this._rawMapping = rawMapping;
|
||||
this._keyboardMapper = new CachedKeyboardMapper(
|
||||
KeyboardMapperFactory._createKeyboardMapper(this._layoutInfo, this._rawMapping)
|
||||
);
|
||||
this._onDidChangeKeyboardMapper.fire();
|
||||
}
|
||||
|
||||
private static _createKeyboardMapper(layoutInfo: nativeKeymap.IKeyboardLayoutInfo, rawMapping: nativeKeymap.IKeyboardMapping): IKeyboardMapper {
|
||||
const isUSStandard = KeyboardMapperFactory._isUSStandard(layoutInfo);
|
||||
if (OS === OperatingSystem.Windows) {
|
||||
return new WindowsKeyboardMapper(isUSStandard, <nativeKeymap.IWindowsKeyboardMapping>rawMapping);
|
||||
}
|
||||
|
||||
if (Object.keys(rawMapping).length === 0) {
|
||||
// Looks like reading the mappings failed (most likely Mac + Japanese/Chinese keyboard layouts)
|
||||
return new MacLinuxFallbackKeyboardMapper(OS);
|
||||
}
|
||||
|
||||
if (OS === OperatingSystem.Macintosh) {
|
||||
const kbInfo = <nativeKeymap.IMacKeyboardLayoutInfo>layoutInfo;
|
||||
if (kbInfo.id === 'com.apple.keylayout.DVORAK-QWERTYCMD') {
|
||||
// Use keyCode based dispatching for DVORAK - QWERTY ⌘
|
||||
return new MacLinuxFallbackKeyboardMapper(OS);
|
||||
}
|
||||
}
|
||||
|
||||
return new MacLinuxKeyboardMapper(isUSStandard, <IMacLinuxKeyboardMapping>rawMapping, OS);
|
||||
}
|
||||
|
||||
private static _equals(a: nativeKeymap.IKeyboardMapping | null, b: nativeKeymap.IKeyboardMapping | null): boolean {
|
||||
if (OS === OperatingSystem.Windows) {
|
||||
return windowsKeyboardMappingEquals(<nativeKeymap.IWindowsKeyboardMapping>a, <nativeKeymap.IWindowsKeyboardMapping>b);
|
||||
}
|
||||
|
||||
return macLinuxKeyboardMappingEquals(<IMacLinuxKeyboardMapping>a, <IMacLinuxKeyboardMapping>b);
|
||||
}
|
||||
}
|
||||
|
||||
class NativeKeymapService extends Disposable implements IKeymapService {
|
||||
public _serviceBrand: undefined;
|
||||
|
||||
private readonly _onDidChangeKeyboardMapper = this._register(new Emitter<void>());
|
||||
public readonly onDidChangeKeyboardMapper: Event<void> = this._onDidChangeKeyboardMapper.event;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._register(KeyboardMapperFactory.INSTANCE.onDidChangeKeyboardMapper(() => {
|
||||
this._onDidChangeKeyboardMapper.fire();
|
||||
}));
|
||||
|
||||
ipcRenderer.on('vscode:keyboardLayoutChanged', () => {
|
||||
KeyboardMapperFactory.INSTANCE._onKeyboardLayoutChanged();
|
||||
});
|
||||
}
|
||||
|
||||
getKeyboardMapper(dispatchConfig: DispatchConfig): IKeyboardMapper {
|
||||
return KeyboardMapperFactory.INSTANCE.getKeyboardMapper(dispatchConfig);
|
||||
}
|
||||
|
||||
public getCurrentKeyboardLayout(): IKeyboardLayoutInfo | null {
|
||||
return KeyboardMapperFactory.INSTANCE.getCurrentKeyboardLayout();
|
||||
}
|
||||
|
||||
getAllKeyboardLayouts(): IKeyboardLayoutInfo[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
public getRawKeyboardMapping(): IKeyboardMapping | null {
|
||||
return KeyboardMapperFactory.INSTANCE.getRawKeyboardMapping();
|
||||
}
|
||||
|
||||
public validateCurrentKeyboardMapping(keyboardEvent: IKeyboardEvent): void {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IKeymapService, NativeKeymapService, true);
|
||||
@@ -0,0 +1,144 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IKeyboardLayoutInfo, IKeyboardLayoutService, IKeyboardMapping, ILinuxKeyboardLayoutInfo, IMacKeyboardLayoutInfo, IMacLinuxKeyboardMapping, IWindowsKeyboardLayoutInfo, IWindowsKeyboardMapping, macLinuxKeyboardMappingEquals, windowsKeyboardMappingEquals } from 'vs/platform/keyboardLayout/common/keyboardLayout';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { OperatingSystem, OS } from 'vs/base/common/platform';
|
||||
import { CachedKeyboardMapper, IKeyboardMapper } from 'vs/platform/keyboardLayout/common/keyboardMapper';
|
||||
import { WindowsKeyboardMapper } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper';
|
||||
import { MacLinuxFallbackKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxFallbackKeyboardMapper';
|
||||
import { MacLinuxKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxKeyboardMapper';
|
||||
import { DispatchConfig } from 'vs/platform/keyboardLayout/common/dispatchConfig';
|
||||
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
|
||||
import { IKeyboardLayoutMainService } from 'vs/platform/keyboardLayout/common/keyboardLayoutMainService';
|
||||
import { createChannelSender } from 'vs/base/parts/ipc/common/ipc';
|
||||
|
||||
export class KeyboardLayoutService extends Disposable implements IKeyboardLayoutService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _onDidChangeKeyboardLayout = this._register(new Emitter<void>());
|
||||
readonly onDidChangeKeyboardLayout = this._onDidChangeKeyboardLayout.event;
|
||||
|
||||
private readonly _keyboardLayoutMainService: IKeyboardLayoutMainService;
|
||||
private _initPromise: Promise<void> | null;
|
||||
private _keyboardMapping: IKeyboardMapping | null;
|
||||
private _keyboardLayoutInfo: IKeyboardLayoutInfo | null;
|
||||
private _keyboardMapper: IKeyboardMapper;
|
||||
|
||||
constructor(
|
||||
@IMainProcessService mainProcessService: IMainProcessService
|
||||
) {
|
||||
super();
|
||||
this._keyboardLayoutMainService = createChannelSender<IKeyboardLayoutMainService>(mainProcessService.getChannel('keyboardLayout'));
|
||||
this._initPromise = null;
|
||||
this._keyboardMapping = null;
|
||||
this._keyboardLayoutInfo = null;
|
||||
this._keyboardMapper = new MacLinuxFallbackKeyboardMapper(OS);
|
||||
|
||||
this._register(this._keyboardLayoutMainService.onDidChangeKeyboardLayout(async ({ keyboardLayoutInfo, keyboardMapping }) => {
|
||||
await this.initialize();
|
||||
if (keyboardMappingEquals(this._keyboardMapping, keyboardMapping)) {
|
||||
// the mappings are equal
|
||||
return;
|
||||
}
|
||||
|
||||
this._keyboardMapping = keyboardMapping;
|
||||
this._keyboardLayoutInfo = keyboardLayoutInfo;
|
||||
this._keyboardMapper = new CachedKeyboardMapper(createKeyboardMapper(this._keyboardLayoutInfo, this._keyboardMapping));
|
||||
this._onDidChangeKeyboardLayout.fire();
|
||||
}));
|
||||
}
|
||||
|
||||
public initialize(): Promise<void> {
|
||||
if (!this._initPromise) {
|
||||
this._initPromise = this._doInitialize();
|
||||
}
|
||||
return this._initPromise;
|
||||
}
|
||||
|
||||
private async _doInitialize(): Promise<void> {
|
||||
const keyboardLayoutData = await this._keyboardLayoutMainService.getKeyboardLayoutData();
|
||||
const { keyboardLayoutInfo, keyboardMapping } = keyboardLayoutData;
|
||||
this._keyboardMapping = keyboardMapping;
|
||||
this._keyboardLayoutInfo = keyboardLayoutInfo;
|
||||
this._keyboardMapper = new CachedKeyboardMapper(createKeyboardMapper(this._keyboardLayoutInfo, this._keyboardMapping));
|
||||
}
|
||||
|
||||
public getRawKeyboardMapping(): IKeyboardMapping | null {
|
||||
return this._keyboardMapping;
|
||||
}
|
||||
|
||||
public getCurrentKeyboardLayout(): IKeyboardLayoutInfo | null {
|
||||
return this._keyboardLayoutInfo;
|
||||
}
|
||||
|
||||
public getAllKeyboardLayouts(): IKeyboardLayoutInfo[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
public getKeyboardMapper(dispatchConfig: DispatchConfig): IKeyboardMapper {
|
||||
if (dispatchConfig === DispatchConfig.KeyCode) {
|
||||
// Forcefully set to use keyCode
|
||||
return new MacLinuxFallbackKeyboardMapper(OS);
|
||||
}
|
||||
return this._keyboardMapper;
|
||||
}
|
||||
|
||||
public validateCurrentKeyboardMapping(keyboardEvent: IKeyboardEvent): void {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function keyboardMappingEquals(a: IKeyboardMapping | null, b: IKeyboardMapping | null): boolean {
|
||||
if (OS === OperatingSystem.Windows) {
|
||||
return windowsKeyboardMappingEquals(<IWindowsKeyboardMapping | null>a, <IWindowsKeyboardMapping | null>b);
|
||||
}
|
||||
|
||||
return macLinuxKeyboardMappingEquals(<IMacLinuxKeyboardMapping | null>a, <IMacLinuxKeyboardMapping | null>b);
|
||||
}
|
||||
|
||||
function createKeyboardMapper(layoutInfo: IKeyboardLayoutInfo | null, rawMapping: IKeyboardMapping | null): IKeyboardMapper {
|
||||
const _isUSStandard = isUSStandard(layoutInfo);
|
||||
if (OS === OperatingSystem.Windows) {
|
||||
return new WindowsKeyboardMapper(_isUSStandard, <IWindowsKeyboardMapping>rawMapping);
|
||||
}
|
||||
|
||||
if (!rawMapping || Object.keys(rawMapping).length === 0) {
|
||||
// Looks like reading the mappings failed (most likely Mac + Japanese/Chinese keyboard layouts)
|
||||
return new MacLinuxFallbackKeyboardMapper(OS);
|
||||
}
|
||||
|
||||
if (OS === OperatingSystem.Macintosh) {
|
||||
const kbInfo = <IMacKeyboardLayoutInfo>layoutInfo;
|
||||
if (kbInfo.id === 'com.apple.keylayout.DVORAK-QWERTYCMD') {
|
||||
// Use keyCode based dispatching for DVORAK - QWERTY ⌘
|
||||
return new MacLinuxFallbackKeyboardMapper(OS);
|
||||
}
|
||||
}
|
||||
|
||||
return new MacLinuxKeyboardMapper(_isUSStandard, <IMacLinuxKeyboardMapping>rawMapping, OS);
|
||||
}
|
||||
|
||||
function isUSStandard(_kbInfo: IKeyboardLayoutInfo | null): boolean {
|
||||
if (OS === OperatingSystem.Linux) {
|
||||
const kbInfo = <ILinuxKeyboardLayoutInfo>_kbInfo;
|
||||
return (kbInfo && (kbInfo.layout === 'us' || /^us,/.test(kbInfo.layout)));
|
||||
}
|
||||
|
||||
if (OS === OperatingSystem.Macintosh) {
|
||||
const kbInfo = <IMacKeyboardLayoutInfo>_kbInfo;
|
||||
return (kbInfo && kbInfo.id === 'com.apple.keylayout.US');
|
||||
}
|
||||
|
||||
if (OS === OperatingSystem.Windows) {
|
||||
const kbInfo = <IWindowsKeyboardLayoutInfo>_kbInfo;
|
||||
return (kbInfo && kbInfo.name === '00000409');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import * as assert from 'assert';
|
||||
import 'vs/workbench/services/keybinding/browser/keyboardLayouts/en.darwin'; // 15%
|
||||
import 'vs/workbench/services/keybinding/browser/keyboardLayouts/de.darwin';
|
||||
import { KeyboardLayoutContribution } from 'vs/workbench/services/keybinding/browser/keyboardLayouts/_.contribution';
|
||||
import { BrowserKeyboardMapperFactoryBase } from 'vs/workbench/services/keybinding/browser/keymapService';
|
||||
import { BrowserKeyboardMapperFactoryBase } from 'vs/workbench/services/keybinding/browser/keyboardLayoutService';
|
||||
import { KeymapInfo, IKeymapInfo } from 'vs/workbench/services/keybinding/common/keymapInfo';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
|
||||
@@ -117,7 +117,7 @@ suite('KeybindingsEditing', () => {
|
||||
const fileService = new FileService(new NullLogService());
|
||||
const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService());
|
||||
fileService.registerProvider(Schemas.file, diskFileSystemProvider);
|
||||
fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, undefined, diskFileSystemProvider, environmentService, new NullLogService()));
|
||||
fileService.registerProvider(Schemas.userData, new FileUserDataProvider(Schemas.file, diskFileSystemProvider, Schemas.userData, new NullLogService()));
|
||||
instantiationService.stub(IFileService, fileService);
|
||||
instantiationService.stub(IUriIdentityService, new UriIdentityService(fileService));
|
||||
instantiationService.stub(IWorkingCopyService, new TestWorkingCopyService());
|
||||
@@ -194,7 +194,19 @@ suite('KeybindingsEditing', () => {
|
||||
.then(() => assert.deepEqual(getUserKeybindings(), expected));
|
||||
});
|
||||
|
||||
test('add another keybinding', () => {
|
||||
const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: 'a' }];
|
||||
return testObject.addKeybinding(aResolvedKeybindingItem({ firstPart: { keyCode: KeyCode.Escape }, command: 'a' }), 'alt+c', undefined)
|
||||
.then(() => assert.deepEqual(getUserKeybindings(), expected));
|
||||
});
|
||||
|
||||
test('add a new default keybinding', () => {
|
||||
const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: 'a' }];
|
||||
return testObject.addKeybinding(aResolvedKeybindingItem({ command: 'a' }), 'alt+c', undefined)
|
||||
.then(() => assert.deepEqual(getUserKeybindings(), expected));
|
||||
});
|
||||
|
||||
test('add a new default keybinding using edit', () => {
|
||||
const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: 'a' }];
|
||||
return testObject.editKeybinding(aResolvedKeybindingItem({ command: 'a' }), 'alt+c', undefined)
|
||||
.then(() => assert.deepEqual(getUserKeybindings(), expected));
|
||||
@@ -312,7 +324,7 @@ suite('KeybindingsEditing', () => {
|
||||
}
|
||||
}
|
||||
const keybinding = parts.length > 0 ? new USLayoutResolvedKeybinding(new ChordKeybinding(parts), OS) : undefined;
|
||||
return new ResolvedKeybindingItem(keybinding, command || 'some command', null, when ? ContextKeyExpr.deserialize(when) : undefined, isDefault === undefined ? true : isDefault, null);
|
||||
return new ResolvedKeybindingItem(keybinding, command || 'some command', null, when ? ContextKeyExpr.deserialize(when) : undefined, isDefault === undefined ? true : isDefault, null, false);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Keybinding, ResolvedKeybinding, SimpleKeybinding } from 'vs/base/common
|
||||
import { ScanCodeBinding } from 'vs/base/common/scanCode';
|
||||
import { readFile, writeFile } from 'vs/base/node/pfs';
|
||||
import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { IKeyboardMapper } from 'vs/platform/keyboardLayout/common/keyboardMapper';
|
||||
|
||||
export interface IResolvedKeybinding {
|
||||
label: string | null;
|
||||
|
||||
@@ -9,8 +9,9 @@ import { UserSettingsLabelProvider } from 'vs/base/common/keybindingLabels';
|
||||
import { OperatingSystem } from 'vs/base/common/platform';
|
||||
import { ScanCode, ScanCodeBinding, ScanCodeUtils } from 'vs/base/common/scanCode';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { IMacLinuxKeyboardMapping, MacLinuxKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxKeyboardMapper';
|
||||
import { MacLinuxKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxKeyboardMapper';
|
||||
import { IResolvedKeybinding, assertMapping, assertResolveKeybinding, assertResolveKeyboardEvent, assertResolveUserBinding, readRawMapping } from 'vs/workbench/services/keybinding/test/electron-browser/keyboardMapperTestUtils';
|
||||
import { IMacLinuxKeyboardMapping } from 'vs/platform/keyboardLayout/common/keyboardLayout';
|
||||
|
||||
const WRITE_FILE_IF_DIFFERENT = false;
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
import { KeyChord, KeyCode, KeyMod, SimpleKeybinding, createKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { OperatingSystem } from 'vs/base/common/platform';
|
||||
import { ScanCode, ScanCodeBinding } from 'vs/base/common/scanCode';
|
||||
import { IWindowsKeyboardMapping, WindowsKeyboardMapper } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper';
|
||||
import { WindowsKeyboardMapper } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper';
|
||||
import { IResolvedKeybinding, assertMapping, assertResolveKeybinding, assertResolveKeyboardEvent, assertResolveUserBinding, readRawMapping } from 'vs/workbench/services/keybinding/test/electron-browser/keyboardMapperTestUtils';
|
||||
import { IWindowsKeyboardMapping } from 'vs/platform/keyboardLayout/common/keyboardLayout';
|
||||
|
||||
const WRITE_FILE_IF_DIFFERENT = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user