使用的vscode版本 1.30.0
总纲
—- 主进程 —-
- src/main.js
- vs/code/electron-main/main.ts
- vs/code/electron-main/app.ts
- vs/code/electron-main/window.ts 启动渲染进程的关键
—- 渲染进程 —-
- vs/code/electron-browser/workbench/workbench.html 渲染进程的html
- vs/workbench/electron-browser/main.ts
- vs/workbench/electron-browser/shell.ts
- vs/workbench/electron-browser/workbench.ts 界面渲染逻辑的核心,重点关注的
- vs/workbench/browser/parts/titlebar/titlebarPart
src/main.js
electron-main/main.ts
做了那几件事情?
electron-main/app.ts
electron-main/window.ts
创建渲染进程的关键
CodeWindow 这个类
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage } from 'electron';export class CodeWindow extends Disposable implements ICodeWindow {private createBrowserWindow(config: IWindowCreationOptions): void {this._win = new BrowserWindow(options);}load(config: IWindowConfiguration, isReload?: boolean, disableExtensions?: boolean): void {this._win.loadURL(this.getUrl(configuration));}private doGetUrl(config: object): string {// 通过url参数把配置传入workbench.htmlreturn `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;}}
workbench.html(渲染进程)
<!-- Copyright (C) Microsoft Corporation. All rights reserved. --><!DOCTYPE html><html><head><meta charset="utf-8" /><meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: vscode-remote:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;"></head><body class="monaco-shell vs-dark" aria-label=""></body><!-- Startup via workbench.js --><script src="workbench.js"></script></html>
workbench.js(渲染进程)
先加载了非常多前置的依赖,然后运行了主进程
// Load workbench main// 要先加载三个文件bootstrapWindow.load(['vs/workbench/workbench.main','vs/nls!vs/workbench/workbench.main','vs/css!vs/workbench/workbench.main'],function (workbench, configuration) {perf.mark('didLoadWorkbenchMain');return process['lazyEnv'].then(function () {perf.mark('main/startup');// @ts-ignore// 即运行下面的主进程return require('vs/workbench/electron-browser/main').startup(configuration);});}, {
workbench.main
// Baseimport 'vs/base/common/strings';import 'vs/base/common/errors';// Configurationimport 'vs/workbench/services/configuration/common/configurationExtensionPoint';// Editorimport 'vs/editor/editor.all';// Platformimport 'vs/platform/widget/browser/contextScopedHistoryWidget';import 'vs/platform/label/electron-browser/label.contribution';
main (vs/workbench/electron-browser/main.ts)
openWorkbench -> WorkbenchShell.open
import * as browser from 'vs/base/browser/browser';export function startup(configuration: IWindowConfiguration): Promise<void> {// Massage configuration file URIsrevive(configuration);// Setup perfperf.importEntries(configuration.perfEntries);// Configure emitter leak warning thresholdsetGlobalLeakWarningThreshold(-1);// Browser configbrowser.setZoomFactor(webFrame.getZoomFactor()); // Ensure others can listen to zoom level changesbrowser.setZoomLevel(webFrame.getZoomLevel(), true /* isTrusted */); // Can be trusted because we are not setting it ourselves (https://github.com/Microsoft/vscode/issues/26151)browser.setFullscreen(!!configuration.fullscreen);browser.setAccessibilitySupport(configuration.accessibilitySupport ? platform.AccessibilitySupport.Enabled : platform.AccessibilitySupport.Disabled);// Keyboard supportKeyboardMapperFactory.INSTANCE._onKeyboardLayoutChanged();// Setup Intl for comparerscomparer.setFileNameComparer(new IdleValue(() => {const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });return {collator: collator,collatorIsNumeric: collator.resolvedOptions().numeric};}));// Open workbenchreturn openWorkbench(configuration);}
shell (vs/workbench/electron-browser/shell.ts)
open -> renderContents -> createWorkbench -> workbench.startup()
export class WorkbenchShell extends Disposable {open(){// Listen on unhandled rejection eventswindow.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {// See https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEventerrors.onUnexpectedError(event.reason);// Prevent the printing of this event to the consoleevent.preventDefault();});// Listen on unexpected errorserrors.setUnexpectedErrorHandler((error: any) => {this.onUnexpectedError(error);});// Shell Class for CSS ScopingaddClass(this.container, 'monaco-shell');// Create Contentsthis.renderContents();// Layoutthis.layout();// Listenersthis.registerListeners();// Set lifecycle phase to `Ready`this.lifecycleService.phase = LifecyclePhase.Ready;}private renderContents(): void {// ARIAaria.setARIAContainer(document.body);// Instantiation service with servicesconst [instantiationService, serviceCollection] = this.initServiceCollection(this.container);// Warm up font cache information before building up too many dom elementsrestoreFontInfo(this.storageService);readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getValue('editor'), browser.getZoomLevel()));this._register(this.storageService.onWillSaveState(() => {saveFontInfo(this.storageService); // Keep font info for next startup around}));// Workbenchthis.workbench = this.createWorkbench(instantiationService, serviceCollection, this.container);// Windowthis.workbench.getInstantiationService().createInstance(ElectronWindow);// Handle case where workbench is not starting up properlyconst timeoutHandle = setTimeout(() => {this.logService.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.');}, 10000);this.lifecycleService.when(LifecyclePhase.Restored).then(() => {clearTimeout(timeoutHandle);});}}
workbench (vs/workbench/electron-browser/workbench.ts)
这个起什么作用?
- 初始化各种服务 dom容器,全局action,初始services,上下文按键,监听工作区变化和逻辑
- 渲染工作区
- 恢复之前打开的内容
export class Workbench extends Disposable implements IPartService {startup(): Thenable<IWorkbenchStartedInfo> {this.workbenchStarted = true;// Create Workbench Containerthis.createWorkbench();// Install some global actionsthis.createGlobalActions();// Servicesthis.initServices();// Context Keysthis.handleContextKeys();// Register Listenersthis.registerListeners();// Settingsthis.initSettings();// Create Workbench and Partsthis.renderWorkbench();// Workbench Layoutthis.createWorkbenchLayout();// Driverif (this.environmentService.driverHandle) {registerWindowDriver(this.mainProcessClient, this.configuration.windowId, this.instantiationService).then(disposable => this._register(disposable));}// Restore Partsreturn this.restoreParts();}private renderWorkbench(): void {// Apply sidebar state as CSS classif (this.sideBarHidden) {DOM.addClass(this.workbench, 'nosidebar');}if (this.panelHidden) {DOM.addClass(this.workbench, 'nopanel');}if (this.statusBarHidden) {DOM.addClass(this.workbench, 'nostatusbar');}// Apply font aliasingthis.setFontAliasing(this.fontAliasing);// Apply fullscreen stateif (browser.isFullscreen()) {DOM.addClass(this.workbench, 'fullscreen');}// Create Partsthis.createTitlebarPart();this.createActivityBarPart();this.createSidebarPart();this.createEditorPart();this.createPanelPart();this.createStatusbarPart();// Notification Handlersthis.createNotificationsHandlers();// Menubar visibility changesif ((isWindows || isLinux) && this.useCustomTitleBarStyle()) {this.titlebarPart.onMenubarVisibilityChange()(e => this.onMenubarToggled(e));}// Add Workbench to DOMthis.container.appendChild(this.workbench);}private createTitlebarPart(): void {const titlebarContainer = this.createPart(Identifiers.TITLEBAR_PART, ['part', 'titlebar'], 'contentinfo');this.titlebarPart.create(titlebarContainer);}}
