mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
browser keybinding service
This commit is contained in:
@@ -13,7 +13,7 @@ import { Event } from 'vs/base/common/event';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
// tslint:disable-next-line: import-patterns no-standalone-editor
|
||||
import { StandaloneKeybindingService, SimpleResourcePropertiesService } from 'vs/editor/standalone/browser/simpleServices';
|
||||
import { SimpleResourcePropertiesService } from 'vs/editor/standalone/browser/simpleServices';
|
||||
import { IDownloadService } from 'vs/platform/download/common/download';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IExtensionHostDebugParams, IDebugParams } from 'vs/platform/environment/common/environment';
|
||||
@@ -21,10 +21,7 @@ import { IExtensionGalleryService, IQueryOptions, IGalleryExtension, InstallOper
|
||||
import { IPager } from 'vs/base/common/paging';
|
||||
import { IExtensionManifest, ExtensionType, ExtensionIdentifier, IExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { IURLHandler, IURLService } from 'vs/platform/url/common/url';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { ITelemetryService, ITelemetryData, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { AbstractLifecycleService } from 'vs/platform/lifecycle/common/lifecycleService';
|
||||
import { ILogService, LogLevel, ConsoleLogService } from 'vs/platform/log/common/log';
|
||||
import { ShutdownReason, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
@@ -40,7 +37,6 @@ import { IRecentlyOpened, IRecent } from 'vs/platform/history/common/history';
|
||||
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
|
||||
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ITunnelService } from 'vs/platform/remote/common/tunnel';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IReloadSessionEvent, IExtensionHostDebugService, ICloseSessionEvent, IAttachSessionEvent, ILogToSessionEvent, ITerminateSessionEvent } from 'vs/workbench/services/extensions/common/extensionHostDebug';
|
||||
@@ -638,23 +634,6 @@ registerSingleton(IExtensionUrlHandler, SimpleExtensionURLHandler, true);
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Keybinding
|
||||
|
||||
export class SimpleKeybindingService extends StandaloneKeybindingService {
|
||||
constructor(
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@ICommandService commandService: ICommandService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@INotificationService notificationService: INotificationService,
|
||||
) {
|
||||
super(contextKeyService, commandService, telemetryService, notificationService, window.document.body);
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IKeybindingService, SimpleKeybindingService);
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Lifecycle
|
||||
|
||||
export class SimpleLifecycleService extends AbstractLifecycleService {
|
||||
|
||||
@@ -19,7 +19,7 @@ import { WorkbenchEnvironmentService } from 'vs/workbench/services/environment/n
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { stat } from 'vs/base/node/pfs';
|
||||
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
|
||||
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/nativeKeymapService';
|
||||
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
|
||||
import { webFrame } from 'electron';
|
||||
import { ISingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
|
||||
@@ -21,7 +21,7 @@ import { IWorkbenchThemeService, VS_HC_THEME } from 'vs/workbench/services/theme
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IResourceInput } from 'vs/platform/editor/common/editor';
|
||||
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
|
||||
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/nativeKeymapService';
|
||||
import { ipcRenderer as ipc, webFrame, crashReporter, Event } from 'electron';
|
||||
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
|
||||
import { IMenuService, MenuId, IMenu, MenuItemAction, ICommandAction } from 'vs/platform/actions/common/actions';
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IKeymapService, IKeyboardLayoutInfo, IKeyboardMapping } from 'vs/workbench/services/keybinding/common/keymapService';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { DispatchConfig } from 'vs/workbench/services/keybinding/common/dispatchConfig';
|
||||
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { OS, OperatingSystem } from 'vs/base/common/platform';
|
||||
import { WindowsKeyboardMapper } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper';
|
||||
import { MacLinuxFallbackKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxFallbackKeyboardMapper';
|
||||
|
||||
class BrowserKeymapService extends Disposable implements IKeymapService {
|
||||
public _serviceBrand: any;
|
||||
|
||||
private readonly _onDidChangeKeyboardMapper = new Emitter<void>();
|
||||
public readonly onDidChangeKeyboardMapper: Event<void> = this._onDidChangeKeyboardMapper.event;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
getKeyboardMapper(dispatchConfig: DispatchConfig): IKeyboardMapper {
|
||||
return this._createKeyboardMapper(dispatchConfig);
|
||||
}
|
||||
|
||||
private _createKeyboardMapper(dispatchConfig: DispatchConfig): IKeyboardMapper {
|
||||
if (OS === OperatingSystem.Windows) {
|
||||
return new WindowsKeyboardMapper(true, {});
|
||||
}
|
||||
|
||||
// Looks like reading the mappings failed (most likely Mac + Japanese/Chinese keyboard layouts)
|
||||
return new MacLinuxFallbackKeyboardMapper(OS);
|
||||
}
|
||||
|
||||
public getCurrentKeyboardLayout(): IKeyboardLayoutInfo | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
public getRawKeyboardMapping(): IKeyboardMapping | null {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IKeymapService, BrowserKeymapService, true);
|
||||
+15
-147
@@ -4,8 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import * as nativeKeymap from 'native-keymap';
|
||||
import { release } from 'os';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
@@ -30,14 +28,12 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { keybindingsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { ExtensionMessageCollector, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { IUserKeybindingItem, KeybindingIO, OutputBuilder } from 'vs/workbench/services/keybinding/common/keybindingIO';
|
||||
import { CachedKeyboardMapper, IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { MacLinuxFallbackKeyboardMapper } from 'vs/workbench/services/keybinding/common/macLinuxFallbackKeyboardMapper';
|
||||
import { IMacLinuxKeyboardMapping, MacLinuxKeyboardMapper, macLinuxKeyboardMappingEquals } from 'vs/workbench/services/keybinding/common/macLinuxKeyboardMapper';
|
||||
import { IWindowsKeyboardMapping, WindowsKeyboardMapper, windowsKeyboardMappingEquals } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper';
|
||||
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
// tslint:disable-next-line: import-patterns
|
||||
import { commandsExtensionPoint } from 'vs/workbench/api/common/menusExtensionPoint';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
@@ -46,121 +42,8 @@ import { IFileService, FileChangesEvent, FileChangeType } from 'vs/platform/file
|
||||
import { dirname, isEqual } from 'vs/base/common/resources';
|
||||
import { parse } from 'vs/base/common/json';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
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, <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(<IWindowsKeyboardMapping>a, <IWindowsKeyboardMapping>b);
|
||||
}
|
||||
|
||||
return macLinuxKeyboardMappingEquals(<IMacLinuxKeyboardMapping>a, <IMacLinuxKeyboardMapping>b);
|
||||
}
|
||||
}
|
||||
import { IKeymapService } from 'vs/workbench/services/keybinding/common/keymapService';
|
||||
import { getDispatchConfig } from 'vs/workbench/services/keybinding/common/dispatchConfig';
|
||||
|
||||
interface ContributedKeyBinding {
|
||||
command: string;
|
||||
@@ -257,17 +140,6 @@ const keybindingsExtPoint = ExtensionsRegistry.registerExtensionPoint<Contribute
|
||||
}
|
||||
});
|
||||
|
||||
export const enum DispatchConfig {
|
||||
Code,
|
||||
KeyCode
|
||||
}
|
||||
|
||||
function getDispatchConfig(configurationService: IConfigurationService): DispatchConfig {
|
||||
const keyboard = configurationService.getValue('keyboard');
|
||||
const r = (keyboard ? (<any>keyboard).dispatch : null);
|
||||
return (r === 'keyCode' ? DispatchConfig.KeyCode : DispatchConfig.Code);
|
||||
}
|
||||
|
||||
export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
|
||||
private _keyboardMapper: IKeyboardMapper;
|
||||
@@ -283,7 +155,8 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IFileService fileService: IFileService
|
||||
@IFileService fileService: IFileService,
|
||||
@IKeymapService private readonly keymapService: IKeymapService
|
||||
) {
|
||||
super(contextKeyService, commandService, telemetryService, notificationService);
|
||||
|
||||
@@ -297,13 +170,13 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
}
|
||||
|
||||
dispatchConfig = newDispatchConfig;
|
||||
this._keyboardMapper = KeyboardMapperFactory.INSTANCE.getKeyboardMapper(dispatchConfig);
|
||||
this._keyboardMapper = this.keymapService.getKeyboardMapper(dispatchConfig);
|
||||
this.updateResolver({ source: KeybindingSource.Default });
|
||||
});
|
||||
|
||||
this._keyboardMapper = KeyboardMapperFactory.INSTANCE.getKeyboardMapper(dispatchConfig);
|
||||
KeyboardMapperFactory.INSTANCE.onDidChangeKeyboardMapper(() => {
|
||||
this._keyboardMapper = KeyboardMapperFactory.INSTANCE.getKeyboardMapper(dispatchConfig);
|
||||
this._keyboardMapper = this.keymapService.getKeyboardMapper(dispatchConfig);
|
||||
this.keymapService.onDidChangeKeyboardMapper(() => {
|
||||
this._keyboardMapper = this.keymapService.getKeyboardMapper(dispatchConfig);
|
||||
this.updateResolver({ source: KeybindingSource.Default });
|
||||
});
|
||||
|
||||
@@ -353,7 +226,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
}));
|
||||
|
||||
keybindingsTelemetry(telemetryService, this);
|
||||
let data = KeyboardMapperFactory.INSTANCE.getCurrentKeyboardLayout();
|
||||
let data = this.keymapService.getCurrentKeyboardLayout();
|
||||
/* __GDPR__
|
||||
"keyboardLayout" : {
|
||||
"currentKeyboardLayout": { "${inline}": [ "${IKeyboardLayoutInfo}" ] }
|
||||
@@ -365,9 +238,9 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
}
|
||||
|
||||
public _dumpDebugInfo(): string {
|
||||
const layoutInfo = JSON.stringify(KeyboardMapperFactory.INSTANCE.getCurrentKeyboardLayout(), null, '\t');
|
||||
const layoutInfo = JSON.stringify(this.keymapService.getCurrentKeyboardLayout(), null, '\t');
|
||||
const mapperInfo = this._keyboardMapper.dumpDebugInfo();
|
||||
const rawMapping = JSON.stringify(KeyboardMapperFactory.INSTANCE.getRawKeyboardMapping(), null, '\t');
|
||||
const rawMapping = JSON.stringify(this.keymapService.getRawKeyboardMapping(), null, '\t');
|
||||
return `Layout info:\n${layoutInfo}\n${mapperInfo}\n\nRaw mapping:\n${rawMapping}`;
|
||||
}
|
||||
|
||||
@@ -559,7 +432,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
|
||||
}
|
||||
// consult the KeyboardMapperFactory to check the given event for
|
||||
// a printable value.
|
||||
const mapping = KeyboardMapperFactory.INSTANCE.getRawKeyboardMapping();
|
||||
const mapping = this.keymapService.getRawKeyboardMapping();
|
||||
if (!mapping) {
|
||||
return false;
|
||||
}
|
||||
@@ -799,13 +672,8 @@ const keyboardConfiguration: IConfigurationNode = {
|
||||
'default': 'code',
|
||||
'markdownDescription': nls.localize('dispatch', "Controls the dispatching logic for key presses to use either `code` (recommended) or `keyCode`."),
|
||||
'included': OS === OperatingSystem.Macintosh || OS === OperatingSystem.Linux
|
||||
},
|
||||
'keyboard.touchbar.enabled': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('touchbar.enabled', "Enables the macOS touchbar buttons on the keyboard if available."),
|
||||
'included': OS === OperatingSystem.Macintosh && parseFloat(release()) >= 16 // Minimum: macOS Sierra (10.12.x = darwin 16.x)
|
||||
}
|
||||
// no touch bar support
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { DispatchConfig } from 'vs/workbench/services/keybinding/common/dispatchConfig';
|
||||
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
|
||||
|
||||
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" }
|
||||
}
|
||||
*/
|
||||
export interface IMacKeyboardLayoutInfo {
|
||||
id: string;
|
||||
lang: string;
|
||||
}
|
||||
|
||||
export type IKeyboardLayoutInfo = IWindowsKeyboardLayoutInfo | ILinuxKeyboardLayoutInfo | IMacKeyboardLayoutInfo;
|
||||
|
||||
export const IKeymapService = createDecorator<IKeymapService>('keymapService');
|
||||
|
||||
export interface IKeymapService {
|
||||
_serviceBrand: ServiceIdentifier<any>;
|
||||
onDidChangeKeyboardMapper: Event<void>;
|
||||
getKeyboardMapper(dispatchConfig: DispatchConfig): IKeyboardMapper;
|
||||
getCurrentKeyboardLayout(): IKeyboardLayoutInfo | null;
|
||||
getRawKeyboardMapping(): IKeyboardMapping | null;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { release } from 'os';
|
||||
import { OS, OperatingSystem } from 'vs/base/common/platform';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Extensions as ConfigExtensions, IConfigurationNode, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigExtensions.Configuration);
|
||||
const keyboardConfiguration: IConfigurationNode = {
|
||||
'id': 'keyboard',
|
||||
'order': 15,
|
||||
'type': 'object',
|
||||
'title': nls.localize('keyboardConfigurationTitle', "Keyboard"),
|
||||
'overridable': true,
|
||||
'properties': {
|
||||
'keyboard.dispatch': {
|
||||
'type': 'string',
|
||||
'enum': ['code', 'keyCode'],
|
||||
'default': 'code',
|
||||
'markdownDescription': nls.localize('dispatch', "Controls the dispatching logic for key presses to use either `code` (recommended) or `keyCode`."),
|
||||
'included': OS === OperatingSystem.Macintosh || OS === OperatingSystem.Linux
|
||||
},
|
||||
'keyboard.touchbar.enabled': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('touchbar.enabled', "Enables the macOS touchbar buttons on the keyboard if available."),
|
||||
'included': OS === OperatingSystem.Macintosh && parseFloat(release()) >= 16 // Minimum: macOS Sierra (10.12.x = darwin 16.x)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
configurationRegistry.registerConfiguration(keyboardConfiguration);
|
||||
@@ -0,0 +1,160 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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/keymapService';
|
||||
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';
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
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: any;
|
||||
|
||||
private readonly _onDidChangeKeyboardMapper = new Emitter<void>();
|
||||
public readonly onDidChangeKeyboardMapper: Event<void> = this._onDidChangeKeyboardMapper.event;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._register(KeyboardMapperFactory.INSTANCE.onDidChangeKeyboardMapper(() => {
|
||||
this._onDidChangeKeyboardMapper.fire();
|
||||
}));
|
||||
}
|
||||
|
||||
getKeyboardMapper(dispatchConfig: DispatchConfig): IKeyboardMapper {
|
||||
return KeyboardMapperFactory.INSTANCE.getKeyboardMapper(dispatchConfig);
|
||||
}
|
||||
|
||||
public getCurrentKeyboardLayout(): IKeyboardLayoutInfo | null {
|
||||
return KeyboardMapperFactory.INSTANCE.getCurrentKeyboardLayout();
|
||||
}
|
||||
|
||||
public getRawKeyboardMapping(): IKeyboardMapping | null {
|
||||
return KeyboardMapperFactory.INSTANCE.getRawKeyboardMapping();
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IKeymapService, NativeKeymapService, true);
|
||||
@@ -117,7 +117,9 @@ import 'vs/workbench/services/editor/browser/editorService';
|
||||
import 'vs/workbench/services/history/browser/history';
|
||||
import 'vs/workbench/services/activity/browser/activityService';
|
||||
import 'vs/workbench/browser/parts/views/views';
|
||||
import 'vs/workbench/services/keybinding/electron-browser/keybindingService';
|
||||
import 'vs/workbench/services/keybinding/electron-browser/nativeKeymapService';
|
||||
import 'vs/workbench/services/keybinding/electron-browser/keybinding.contribution';
|
||||
import 'vs/workbench/services/keybinding/browser/keybindingService';
|
||||
import 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
import 'vs/workbench/services/textfile/node/textResourcePropertiesService';
|
||||
import 'vs/workbench/services/mode/common/workbenchModeService';
|
||||
|
||||
@@ -117,7 +117,8 @@ import 'vs/workbench/services/editor/browser/editorService';
|
||||
import 'vs/workbench/services/history/browser/history';
|
||||
import 'vs/workbench/services/activity/browser/activityService';
|
||||
import 'vs/workbench/browser/parts/views/views';
|
||||
// import 'vs/workbench/services/keybinding/electron-browser/keybindingService';
|
||||
import 'vs/workbench/services/keybinding/browser/browserKeymapService';
|
||||
import 'vs/workbench/services/keybinding/browser/keybindingService';
|
||||
import 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
// import 'vs/workbench/services/textfile/node/textResourcePropertiesService';
|
||||
import 'vs/workbench/services/mode/common/workbenchModeService';
|
||||
|
||||
Reference in New Issue
Block a user