使用的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 这个类

  1. import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage } from 'electron';
  2. export class CodeWindow extends Disposable implements ICodeWindow {
  3. private createBrowserWindow(config: IWindowCreationOptions): void {
  4. this._win = new BrowserWindow(options);
  5. }
  6. load(config: IWindowConfiguration, isReload?: boolean, disableExtensions?: boolean): void {
  7. this._win.loadURL(this.getUrl(configuration));
  8. }
  9. private doGetUrl(config: object): string {
  10. // 通过url参数把配置传入workbench.html
  11. return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
  12. }
  13. }

workbench.html(渲染进程)

  1. <!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <meta charset="utf-8" />
  6. <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:;">
  7. </head>
  8. <body class="monaco-shell vs-dark" aria-label="">
  9. </body>
  10. <!-- Startup via workbench.js -->
  11. <script src="workbench.js"></script>
  12. </html>

workbench.js(渲染进程)

先加载了非常多前置的依赖,然后运行了主进程

  1. // Load workbench main
  2. // 要先加载三个文件
  3. bootstrapWindow.load([
  4. 'vs/workbench/workbench.main',
  5. 'vs/nls!vs/workbench/workbench.main',
  6. 'vs/css!vs/workbench/workbench.main'
  7. ],
  8. function (workbench, configuration) {
  9. perf.mark('didLoadWorkbenchMain');
  10. return process['lazyEnv'].then(function () {
  11. perf.mark('main/startup');
  12. // @ts-ignore
  13. // 即运行下面的主进程
  14. return require('vs/workbench/electron-browser/main').startup(configuration);
  15. });
  16. }, {

workbench.main

  1. // Base
  2. import 'vs/base/common/strings';
  3. import 'vs/base/common/errors';
  4. // Configuration
  5. import 'vs/workbench/services/configuration/common/configurationExtensionPoint';
  6. // Editor
  7. import 'vs/editor/editor.all';
  8. // Platform
  9. import 'vs/platform/widget/browser/contextScopedHistoryWidget';
  10. import 'vs/platform/label/electron-browser/label.contribution';

main (vs/workbench/electron-browser/main.ts)

openWorkbench -> WorkbenchShell.open

  1. import * as browser from 'vs/base/browser/browser';
  2. export function startup(configuration: IWindowConfiguration): Promise<void> {
  3. // Massage configuration file URIs
  4. revive(configuration);
  5. // Setup perf
  6. perf.importEntries(configuration.perfEntries);
  7. // Configure emitter leak warning threshold
  8. setGlobalLeakWarningThreshold(-1);
  9. // Browser config
  10. browser.setZoomFactor(webFrame.getZoomFactor()); // Ensure others can listen to zoom level changes
  11. browser.setZoomLevel(webFrame.getZoomLevel(), true /* isTrusted */); // Can be trusted because we are not setting it ourselves (https://github.com/Microsoft/vscode/issues/26151)
  12. browser.setFullscreen(!!configuration.fullscreen);
  13. browser.setAccessibilitySupport(configuration.accessibilitySupport ? platform.AccessibilitySupport.Enabled : platform.AccessibilitySupport.Disabled);
  14. // Keyboard support
  15. KeyboardMapperFactory.INSTANCE._onKeyboardLayoutChanged();
  16. // Setup Intl for comparers
  17. comparer.setFileNameComparer(new IdleValue(() => {
  18. const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
  19. return {
  20. collator: collator,
  21. collatorIsNumeric: collator.resolvedOptions().numeric
  22. };
  23. }));
  24. // Open workbench
  25. return openWorkbench(configuration);
  26. }


shell (vs/workbench/electron-browser/shell.ts)

open -> renderContents -> createWorkbench -> workbench.startup()

  1. export class WorkbenchShell extends Disposable {
  2. open(){
  3. // Listen on unhandled rejection events
  4. window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {
  5. // See https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent
  6. errors.onUnexpectedError(event.reason);
  7. // Prevent the printing of this event to the console
  8. event.preventDefault();
  9. });
  10. // Listen on unexpected errors
  11. errors.setUnexpectedErrorHandler((error: any) => {
  12. this.onUnexpectedError(error);
  13. });
  14. // Shell Class for CSS Scoping
  15. addClass(this.container, 'monaco-shell');
  16. // Create Contents
  17. this.renderContents();
  18. // Layout
  19. this.layout();
  20. // Listeners
  21. this.registerListeners();
  22. // Set lifecycle phase to `Ready`
  23. this.lifecycleService.phase = LifecyclePhase.Ready;
  24. }
  25. private renderContents(): void {
  26. // ARIA
  27. aria.setARIAContainer(document.body);
  28. // Instantiation service with services
  29. const [instantiationService, serviceCollection] = this.initServiceCollection(this.container);
  30. // Warm up font cache information before building up too many dom elements
  31. restoreFontInfo(this.storageService);
  32. readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getValue('editor'), browser.getZoomLevel()));
  33. this._register(this.storageService.onWillSaveState(() => {
  34. saveFontInfo(this.storageService); // Keep font info for next startup around
  35. }));
  36. // Workbench
  37. this.workbench = this.createWorkbench(instantiationService, serviceCollection, this.container);
  38. // Window
  39. this.workbench.getInstantiationService().createInstance(ElectronWindow);
  40. // Handle case where workbench is not starting up properly
  41. const timeoutHandle = setTimeout(() => {
  42. this.logService.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.');
  43. }, 10000);
  44. this.lifecycleService.when(LifecyclePhase.Restored).then(() => {
  45. clearTimeout(timeoutHandle);
  46. });
  47. }
  48. }


workbench (vs/workbench/electron-browser/workbench.ts)

这个起什么作用?

  • 初始化各种服务 dom容器,全局action,初始services,上下文按键,监听工作区变化和逻辑
  • 渲染工作区
  • 恢复之前打开的内容


  1. export class Workbench extends Disposable implements IPartService {
  2. startup(): Thenable<IWorkbenchStartedInfo> {
  3. this.workbenchStarted = true;
  4. // Create Workbench Container
  5. this.createWorkbench();
  6. // Install some global actions
  7. this.createGlobalActions();
  8. // Services
  9. this.initServices();
  10. // Context Keys
  11. this.handleContextKeys();
  12. // Register Listeners
  13. this.registerListeners();
  14. // Settings
  15. this.initSettings();
  16. // Create Workbench and Parts
  17. this.renderWorkbench();
  18. // Workbench Layout
  19. this.createWorkbenchLayout();
  20. // Driver
  21. if (this.environmentService.driverHandle) {
  22. registerWindowDriver(this.mainProcessClient, this.configuration.windowId, this.instantiationService).then(disposable => this._register(disposable));
  23. }
  24. // Restore Parts
  25. return this.restoreParts();
  26. }
  27. private renderWorkbench(): void {
  28. // Apply sidebar state as CSS class
  29. if (this.sideBarHidden) {
  30. DOM.addClass(this.workbench, 'nosidebar');
  31. }
  32. if (this.panelHidden) {
  33. DOM.addClass(this.workbench, 'nopanel');
  34. }
  35. if (this.statusBarHidden) {
  36. DOM.addClass(this.workbench, 'nostatusbar');
  37. }
  38. // Apply font aliasing
  39. this.setFontAliasing(this.fontAliasing);
  40. // Apply fullscreen state
  41. if (browser.isFullscreen()) {
  42. DOM.addClass(this.workbench, 'fullscreen');
  43. }
  44. // Create Parts
  45. this.createTitlebarPart();
  46. this.createActivityBarPart();
  47. this.createSidebarPart();
  48. this.createEditorPart();
  49. this.createPanelPart();
  50. this.createStatusbarPart();
  51. // Notification Handlers
  52. this.createNotificationsHandlers();
  53. // Menubar visibility changes
  54. if ((isWindows || isLinux) && this.useCustomTitleBarStyle()) {
  55. this.titlebarPart.onMenubarVisibilityChange()(e => this.onMenubarToggled(e));
  56. }
  57. // Add Workbench to DOM
  58. this.container.appendChild(this.workbench);
  59. }
  60. private createTitlebarPart(): void {
  61. const titlebarContainer = this.createPart(Identifiers.TITLEBAR_PART, ['part', 'titlebar'], 'contentinfo');
  62. this.titlebarPart.create(titlebarContainer);
  63. }
  64. }