Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79 (#14050)

* Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79

* Fix breaks

* Extension management fixes

* Fix breaks in windows bundling

* Fix/skip failing tests

* Update distro

* Add clear to nuget.config

* Add hygiene task

* Bump distro

* Fix hygiene issue

* Add build to hygiene exclusion

* Update distro

* Update hygiene

* Hygiene exclusions

* Update tsconfig

* Bump distro for server breaks

* Update build config

* Update darwin path

* Add done calls to notebook tests

* Skip failing tests

* Disable smoke tests
This commit is contained in:
Karl Burtram
2021-02-09 16:15:05 -08:00
committed by GitHub
parent 6f192f9af5
commit ce612a3d96
1929 changed files with 68012 additions and 34564 deletions

View File

@@ -15,7 +15,7 @@ import { OS, OperatingSystem, isMacintosh } from 'vs/base/common/platform';
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Extensions as ConfigExtensions, IConfigurationNode, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { ContextKeyExpr, IContextKeyService, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyExpr, IContextKeyService, ContextKeyExpression, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { Extensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { AbstractKeybindingService } from 'vs/platform/keybinding/common/abstractKeybindingService';
@@ -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;
@@ -180,6 +181,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
private _keyboardMapper: IKeyboardMapper;
private _cachedResolver: KeybindingResolver | null;
private userKeybindings: UserKeybindings;
private isComposingGlobalContextKey: IContextKey<boolean>;
private readonly _contributions: KeybindingsSchemaContribution[] = [];
constructor(
@@ -193,10 +195,11 @@ 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);
this.isComposingGlobalContextKey = contextKeyService.createKey('isComposing', false);
this.updateSchema();
let dispatchConfig = getDispatchConfig(configurationService);
@@ -207,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 });
});
@@ -248,6 +251,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
this._register(extensionService.onDidRegisterExtensions(() => this.updateSchema()));
this._register(dom.addDisposableListener(window, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {
this.isComposingGlobalContextKey.set(e.isComposing);
const keyEvent = new StandardKeyboardEvent(e);
this._log(`/ Received keydown event - ${printKeyboardEvent(e)}`);
this._log(`| Converted keydown event - ${printStandardKeyboardEvent(keyEvent)}`);
@@ -255,9 +259,10 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
if (shouldPreventDefault) {
keyEvent.preventDefault();
}
this.isComposingGlobalContextKey.set(false);
}));
let data = this.keymapService.getCurrentKeyboardLayout();
let data = this.keyboardLayoutService.getCurrentKeyboardLayout();
/* __GDPR__FRAGMENT__
"IKeyboardLayoutInfo" : {
"name" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
@@ -321,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');
}
@@ -367,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;
@@ -376,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);
}
}
}
@@ -391,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);
}
}
}
@@ -436,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);
@@ -475,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);
}
@@ -546,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) {
@@ -622,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;
}
@@ -654,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();

View File

@@ -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);

View File

@@ -1,17 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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);
}

View File

@@ -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> {

View File

@@ -1,49 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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);
}
}

View File

@@ -3,191 +3,8 @@
* Licensed under the Source EULA. 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;
@@ -292,14 +109,15 @@ export class KeymapInfo {
continue;
}
if (this.mapping[key] === undefined) {
let currentMapping = this.mapping[key];
if (currentMapping === undefined) {
score -= 1;
}
let currentMapping = this.mapping[key];
let otherMapping = other[key];
if (currentMapping.value !== otherMapping.value) {
if (currentMapping && otherMapping && currentMapping.value !== otherMapping.value) {
score -= 1;
}
}

View File

@@ -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';
/**

View File

@@ -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.
@@ -956,6 +913,12 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
}
}
// See https://github.com/microsoft/vscode/issues/108880
if (this._OS === OperatingSystem.Macintosh && binding.ctrlKey && !binding.metaKey && !binding.altKey && constantKeyCode === KeyCode.US_MINUS) {
// ctrl+- and ctrl+shift+- render very similarly in native macOS menus, leading to confusion
return null;
}
if (constantKeyCode !== -1) {
return this._getElectronLabelForKeyCode(constantKeyCode);
}
@@ -1016,7 +979,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
|| (keyCode === KeyCode.PageUp)
) {
// "Dispatch" on keyCode for these key codes to workaround issues with remote desktoping software
// where the scan codes appear to be incorrect (see https://github.com/Microsoft/vscode/issues/24107)
// where the scan codes appear to be incorrect (see https://github.com/microsoft/vscode/issues/24107)
const immutableScanCode = IMMUTABLE_KEY_CODE_TO_CODE[keyCode];
if (immutableScanCode !== -1) {
code = immutableScanCode;

View File

@@ -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 {
@@ -503,7 +457,7 @@ export class WindowsKeyboardMapper implements IKeyboardMapper {
// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
// See https://github.com/Microsoft/node-native-keymap/blob/master/deps/chromium/keyboard_codes_win.h
// See https://github.com/microsoft/node-native-keymap/blob/master/deps/chromium/keyboard_codes_win.h
function _getNativeMap() {
return {
VK_BACK: KeyCode.Backspace,

View File

@@ -1,174 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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);

View File

@@ -0,0 +1,144 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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;
}

View File

@@ -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';

View File

@@ -27,7 +27,7 @@ import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybindin
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
@@ -38,7 +38,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
import { KeybindingsEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
import { TestBackupFileService, TestEditorGroupsService, TestEditorService, TestLifecycleService, TestPathService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestBackupFileService, TestEditorGroupsService, TestEditorService, TestLifecycleService, TestPathService, TestProductService } from 'vs/workbench/test/browser/workbenchTestServices';
import { FileService } from 'vs/platform/files/common/fileService';
import { Schemas } from 'vs/base/common/network';
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
@@ -64,7 +64,7 @@ import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uri
class TestWorkbenchEnvironmentService extends NativeWorkbenchEnvironmentService {
constructor(private _appSettingsHome: URI) {
super(TestWorkbenchConfiguration);
super(TestWorkbenchConfiguration, TestProductService);
}
get appSettingsHome() { return this._appSettingsHome; }
@@ -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);
}
});

View File

@@ -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;

View File

@@ -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;
@@ -1318,7 +1319,7 @@ suite('keyboardMapper', () => {
);
}
// https://github.com/Microsoft/vscode/issues/24107#issuecomment-292318497
// https://github.com/microsoft/vscode/issues/24107#issuecomment-292318497
assertKeyboardEvent(KeyCode.UpArrow, 'Lang3', 'UpArrow', 'Up', 'up', '[ArrowUp]');
assertKeyboardEvent(KeyCode.DownArrow, 'NumpadEnter', 'DownArrow', 'Down', 'down', '[ArrowDown]');
assertKeyboardEvent(KeyCode.LeftArrow, 'Convert', 'LeftArrow', 'Left', 'left', '[ArrowLeft]');
@@ -1330,7 +1331,7 @@ suite('keyboardMapper', () => {
assertKeyboardEvent(KeyCode.PageDown, 'ControlRight', 'PageDown', 'PageDown', 'pagedown', '[PageDown]');
assertKeyboardEvent(KeyCode.PageUp, 'Lang4', 'PageUp', 'PageUp', 'pageup', '[PageUp]');
// https://github.com/Microsoft/vscode/issues/24107#issuecomment-292323924
// https://github.com/microsoft/vscode/issues/24107#issuecomment-292323924
assertKeyboardEvent(KeyCode.PageDown, 'ControlRight', 'PageDown', 'PageDown', 'pagedown', '[PageDown]');
assertKeyboardEvent(KeyCode.PageUp, 'Lang4', 'PageUp', 'PageUp', 'pageup', '[PageUp]');
assertKeyboardEvent(KeyCode.End, '', 'End', 'End', 'end', '[End]');

View File

@@ -345,9 +345,9 @@ isUSStandard: true
| HW Code combination | Key | KeyCode combination | Pri | UI label | User settings | Electron accelerator | Dispatching string | WYSIWYG |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Minus | - | - | | - | - | - | [Minus] | |
| Ctrl+Minus | - | Ctrl+- | | Ctrl+- | ctrl+- | Ctrl+- | ctrl+[Minus] | |
| Ctrl+Minus | - | Ctrl+- | | Ctrl+- | ctrl+- | null | ctrl+[Minus] | |
| Shift+Minus | _ | Shift+- | | Shift+- | shift+- | Shift+- | shift+[Minus] | |
| Ctrl+Shift+Minus | _ | Ctrl+Shift+- | | Ctrl+Shift+- | ctrl+shift+- | Ctrl+Shift+- | ctrl+shift+[Minus] | |
| Ctrl+Shift+Minus | _ | Ctrl+Shift+- | | Ctrl+Shift+- | ctrl+shift+- | null | ctrl+shift+[Minus] | |
| Alt+Minus | - | Alt+- | | Alt+- | alt+- | Alt+- | alt+[Minus] | |
| Ctrl+Alt+Minus | | Ctrl+Alt+- | | Ctrl+Alt+- | ctrl+alt+- | Ctrl+Alt+- | ctrl+alt+[Minus] | |
| Shift+Alt+Minus | _ | Shift+Alt+- | | Shift+Alt+- | shift+alt+- | Shift+Alt+- | shift+alt+[Minus] | |

View File

@@ -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;