Merge from vscode 8c426f9f3b6b18935cc6c2ec8aa6d45ccd88021e

This commit is contained in:
ADS Merger
2020-07-23 02:21:09 +00:00
parent efc8182954
commit ede827ee82
83 changed files with 1736 additions and 829 deletions

View File

@@ -34,5 +34,5 @@ export interface IContextMenuDelegate {
actionRunner?: IActionRunner;
autoSelectFirstItem?: boolean;
anchorAlignment?: AnchorAlignment;
anchorAsContainer?: boolean;
domForShadowRoot?: HTMLElement;
}

View File

@@ -5,7 +5,6 @@
.monaco-action-bar {
text-align: right;
overflow: hidden;
white-space: nowrap;
}

View File

@@ -28,7 +28,7 @@ function initialize() {
delayer.schedule();
}
function formatRule(c: Codicon) {
export function formatRule(c: Codicon) {
let def = c.definition;
while (def instanceof Codicon) {
def = def.definition;

View File

@@ -10,6 +10,12 @@ import { IDisposable, toDisposable, Disposable, DisposableStore } from 'vs/base/
import { Range } from 'vs/base/common/range';
import { BrowserFeatures } from 'vs/base/browser/canIUse';
export const enum ContextViewDOMPosition {
ABSOLUTE = 1,
FIXED,
FIXED_SHADOW
}
export interface IAnchor {
x: number;
y: number;
@@ -105,32 +111,62 @@ export class ContextView extends Disposable {
private container: HTMLElement | null = null;
private view: HTMLElement;
private useFixedPosition: boolean;
private useShadowDOM: boolean;
private delegate: IDelegate | null = null;
private toDisposeOnClean: IDisposable = Disposable.None;
private toDisposeOnSetContainer: IDisposable = Disposable.None;
private shadowRoot: ShadowRoot | null = null;
private shadowRootHostElement: HTMLElement | null = null;
constructor(container: HTMLElement, useFixedPosition: boolean) {
constructor(container: HTMLElement, domPosition: ContextViewDOMPosition) {
super();
this.view = DOM.$('.context-view');
this.useFixedPosition = false;
this.useShadowDOM = false;
DOM.hide(this.view);
this.setContainer(container, useFixedPosition);
this.setContainer(container, domPosition);
this._register(toDisposable(() => this.setContainer(null, false)));
this._register(toDisposable(() => this.setContainer(null, ContextViewDOMPosition.ABSOLUTE)));
}
setContainer(container: HTMLElement | null, useFixedPosition: boolean): void {
setContainer(container: HTMLElement | null, domPosition: ContextViewDOMPosition): void {
if (this.container) {
this.toDisposeOnSetContainer.dispose();
this.container.removeChild(this.view);
if (this.shadowRoot) {
this.shadowRoot.removeChild(this.view);
this.shadowRoot = null;
DOM.removeNode(this.shadowRootHostElement!);
this.shadowRootHostElement = null;
} else {
this.container.removeChild(this.view);
}
this.container = null;
}
if (container) {
this.container = container;
this.container.appendChild(this.view);
this.useFixedPosition = domPosition !== ContextViewDOMPosition.ABSOLUTE;
this.useShadowDOM = domPosition === ContextViewDOMPosition.FIXED_SHADOW;
if (this.useShadowDOM) {
this.shadowRootHostElement = DOM.$('.shadow-root-host');
this.container.appendChild(this.shadowRootHostElement);
this.shadowRoot = this.shadowRootHostElement.attachShadow({ mode: 'closed' });
this.shadowRoot.innerHTML = `
<style>
${SHADOW_ROOT_CSS}
</style>
`;
this.shadowRoot.appendChild(this.view);
this.shadowRoot.appendChild(DOM.$('slot'));
} else {
this.container.appendChild(this.view);
}
const toDisposeOnSetContainer = new DisposableStore();
@@ -148,8 +184,6 @@ export class ContextView extends Disposable {
this.toDisposeOnSetContainer = toDisposeOnSetContainer;
}
this.useFixedPosition = useFixedPosition;
}
show(delegate: IDelegate): void {
@@ -162,6 +196,7 @@ export class ContextView extends Disposable {
this.view.className = 'context-view';
this.view.style.top = '0px';
this.view.style.left = '0px';
this.view.style.zIndex = '2500';
this.view.style.position = this.useFixedPosition ? 'fixed' : 'absolute';
DOM.show(this.view);
@@ -301,3 +336,45 @@ export class ContextView extends Disposable {
super.dispose();
}
}
let SHADOW_ROOT_CSS = /* css */ `
:host {
all: initial; /* 1st rule so subsequent properties are reset. */
}
@font-face {
font-family: "codicon";
src: url("./codicon.ttf?5d4d76ab2ce5108968ad644d591a16a6") format("truetype");
}
.codicon[class*='codicon-'] {
font: normal normal normal 16px/1 codicon;
display: inline-block;
text-decoration: none;
text-rendering: auto;
text-align: center;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
:host-context(.mac) { font-family: -apple-system, BlinkMacSystemFont, sans-serif; }
:host-context(.mac:lang(zh-Hans)) { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; }
:host-context(.mac:lang(zh-Hant)) { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; }
:host-context(.mac:lang(ja)) { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; }
:host-context(.mac:lang(ko)) { font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif; }
:host-context(.windows) { font-family: "Segoe WPC", "Segoe UI", sans-serif; }
:host-context(.windows:lang(zh-Hans)) { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; }
:host-context(.windows:lang(zh-Hant)) { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; }
:host-context(.windows:lang(ja)) { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; }
:host-context(.windows:lang(ko)) { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; }
:host-context(.mac).linux) { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; }
:host-context(.mac).linux:lang(zh-Hans)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; }
:host-context(.mac).linux:lang(zh-Hant)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; }
:host-context(.mac).linux:lang(ja)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; }
:host-context(.mac).linux:lang(ko)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; }
`;

View File

@@ -270,7 +270,7 @@ export class DropdownMenu extends BaseDropdown {
onHide: () => this.onHide(),
actionRunner: this.menuOptions ? this.menuOptions.actionRunner : undefined,
anchorAlignment: this.menuOptions ? this.menuOptions.anchorAlignment : AnchorAlignment.LEFT,
anchorAsContainer: this.menuAsChild
domForShadowRoot: this.menuAsChild ? this.element : undefined
});
}
@@ -297,15 +297,17 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
private _onDidChangeVisibility = this._register(new Emitter<boolean>());
readonly onDidChangeVisibility = this._onDidChangeVisibility.event;
constructor(action: IAction, menuActions: ReadonlyArray<IAction>, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean);
constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean);
constructor(action: IAction, menuActionsOrProvider: ReadonlyArray<IAction> | IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean) {
constructor(action: IAction, menuActions: ReadonlyArray<IAction>, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner | undefined, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean);
constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner | undefined, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean);
constructor(action: IAction, menuActionsOrProvider: ReadonlyArray<IAction> | IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner | undefined, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean) {
super(null, action);
this.menuActionsOrProvider = menuActionsOrProvider;
this.contextMenuProvider = contextMenuProvider;
this.actionViewItemProvider = actionViewItemProvider;
this.actionRunner = actionRunner;
if (actionRunner) {
this.actionRunner = actionRunner;
}
this.keybindings = keybindings;
this.clazz = clazz;
this.anchorAlignmentProvider = anchorAlignmentProvider;

View File

@@ -1,225 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-menu .monaco-action-bar.vertical {
margin-left: 0;
overflow: visible;
}
.monaco-menu .monaco-action-bar.vertical .actions-container {
display: block;
}
.monaco-menu .monaco-action-bar.vertical .action-item {
padding: 0;
transform: none;
display: flex;
}
.monaco-menu .monaco-action-bar.vertical .action-item.active {
transform: none;
}
.monaco-menu .monaco-action-bar.vertical .action-menu-item {
flex: 1 1 auto;
display: flex;
height: 2em;
align-items: center;
position: relative;
}
.monaco-menu .monaco-action-bar.vertical .action-label {
flex: 1 1 auto;
text-decoration: none;
padding: 0 1em;
background: none;
font-size: 12px;
line-height: 1;
}
.monaco-menu .monaco-action-bar.vertical .keybinding,
.monaco-menu .monaco-action-bar.vertical .submenu-indicator {
display: inline-block;
flex: 2 1 auto;
padding: 0 1em;
text-align: right;
font-size: 12px;
line-height: 1;
}
.monaco-menu .monaco-action-bar.vertical .submenu-indicator {
height: 100%;
}
.monaco-menu .monaco-action-bar.vertical .submenu-indicator.codicon {
font-size: 16px !important;
display: flex;
align-items: center;
}
.monaco-menu .monaco-action-bar.vertical .submenu-indicator.codicon::before {
margin-left: auto;
margin-right: -20px;
}
.monaco-menu .monaco-action-bar.vertical .action-item.disabled .keybinding,
.monaco-menu .monaco-action-bar.vertical .action-item.disabled .submenu-indicator {
opacity: 0.4;
}
.monaco-menu .monaco-action-bar.vertical .action-label:not(.separator) {
display: inline-block;
box-sizing: border-box;
margin: 0;
}
.monaco-menu .monaco-action-bar.vertical .action-item {
position: static;
overflow: visible;
}
.monaco-menu .monaco-action-bar.vertical .action-item .monaco-submenu {
position: absolute;
}
.monaco-menu .monaco-action-bar.vertical .action-label.separator {
padding: 0.5em 0 0 0;
margin-bottom: 0.5em;
width: 100%;
height: 0px !important;
margin-left: .8em !important;
margin-right: .8em !important;
}
.monaco-menu .monaco-action-bar.vertical .action-label.separator.text {
padding: 0.7em 1em 0.1em 1em;
font-weight: bold;
opacity: 1;
}
.monaco-menu .monaco-action-bar.vertical .action-label:hover {
color: inherit;
}
.monaco-menu .monaco-action-bar.vertical .menu-item-check {
position: absolute;
visibility: hidden;
width: 1em;
height: 100%;
}
.monaco-menu .monaco-action-bar.vertical .action-menu-item.checked .menu-item-check {
visibility: visible;
display: flex;
align-items: center;
justify-content: center;
}
/* Context Menu */
.context-view.monaco-menu-container {
outline: 0;
border: none;
animation: fadeIn 0.083s linear;
}
.context-view.monaco-menu-container :focus,
.context-view.monaco-menu-container .monaco-action-bar.vertical:focus,
.context-view.monaco-menu-container .monaco-action-bar.vertical :focus {
outline: 0;
}
.monaco-menu .monaco-action-bar.vertical .action-item {
border: thin solid transparent; /* prevents jumping behaviour on hover or focus */
}
/* High Contrast Theming */
.hc-black .context-view.monaco-menu-container {
box-shadow: none;
}
.hc-black .monaco-menu .monaco-action-bar.vertical .action-item.focused {
background: none;
}
/* Menubar styles */
.menubar {
display: flex;
flex-shrink: 1;
box-sizing: border-box;
height: 30px;
overflow: hidden;
flex-wrap: wrap;
}
.fullscreen .menubar:not(.compact) {
margin: 0px;
padding: 0px 5px;
}
.menubar > .menubar-menu-button {
align-items: center;
box-sizing: border-box;
padding: 0px 8px;
cursor: default;
-webkit-app-region: no-drag;
zoom: 1;
white-space: nowrap;
outline: 0;
}
.menubar.compact {
flex-shrink: 0;
overflow: visible; /* to avoid the compact menu to be repositioned when clicking */
}
.menubar.compact > .menubar-menu-button {
width: 100%;
height: 100%;
padding: 0px;
}
.menubar .menubar-menu-items-holder {
position: absolute;
left: 0px;
opacity: 1;
z-index: 2000;
}
.menubar .menubar-menu-items-holder.monaco-menu-container {
outline: 0;
border: none;
}
.menubar .menubar-menu-items-holder.monaco-menu-container :focus {
outline: 0;
}
.menubar .toolbar-toggle-more {
width: 20px;
height: 100%;
}
.menubar.compact .toolbar-toggle-more {
position: relative;
left: 0px;
top: 0px;
cursor: pointer;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.menubar .toolbar-toggle-more {
padding: 0;
vertical-align: sub;
}
.menubar.compact .toolbar-toggle-more::before {
content: "\eb94" !important;
}

View File

@@ -3,13 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./menu';
import * as nls from 'vs/nls';
import * as strings from 'vs/base/common/strings';
import { IActionRunner, IAction, Action } from 'vs/base/common/actions';
import { ActionBar, IActionViewItemProvider, ActionsOrientation, Separator, ActionViewItem, IActionViewItemOptions, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { ResolvedKeybinding, KeyCode } from 'vs/base/common/keyCodes';
import { addClass, EventType, EventHelper, EventLike, removeTabIndexAndUpdateFocus, isAncestor, hasClass, addDisposableListener, removeClass, append, $, addClasses, removeClasses, clearNode } from 'vs/base/browser/dom';
import { addClass, EventType, EventHelper, EventLike, removeTabIndexAndUpdateFocus, isAncestor, hasClass, addDisposableListener, removeClass, append, $, addClasses, removeClasses, clearNode, createStyleSheet, isInShadowDOM } from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { RunOnceScheduler } from 'vs/base/common/async';
import { DisposableStore } from 'vs/base/common/lifecycle';
@@ -20,6 +19,7 @@ import { Event } from 'vs/base/common/event';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { isLinux, isMacintosh } from 'vs/base/common/platform';
import { Codicon, registerIcon, stripCodicons } from 'vs/base/common/codicons';
import { formatRule } from 'vs/base/browser/ui/codicons/codiconStyles';
export const MENU_MNEMONIC_REGEX = /\(&([^\s&])\)|(^|[^&])&([^\s&])/;
export const MENU_ESCAPED_MNEMONIC_REGEX = /(&amp;)?(&amp;)([^\s&])/g;
@@ -71,6 +71,8 @@ export class Menu extends ActionBar {
private readonly menuDisposables: DisposableStore;
private scrollableElement: DomScrollableElement;
private menuElement: HTMLElement;
static globalStyleSheet: HTMLStyleElement;
protected styleSheet: HTMLStyleElement | undefined;
constructor(container: HTMLElement, actions: ReadonlyArray<IAction>, options: IMenuOptions = {}) {
addClass(container, 'monaco-menu-container');
@@ -96,6 +98,8 @@ export class Menu extends ActionBar {
this.menuDisposables = this._register(new DisposableStore());
this.initializeStyleSheet(container);
addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => {
const event = new StandardKeyboardEvent(e);
@@ -215,6 +219,20 @@ export class Menu extends ActionBar {
});
}
private initializeStyleSheet(container: HTMLElement): void {
if (isInShadowDOM(container)) {
this.styleSheet = createStyleSheet(container);
this.styleSheet.innerHTML = MENU_WIDGET_CSS;
} else {
if (!Menu.globalStyleSheet) {
Menu.globalStyleSheet = createStyleSheet();
Menu.globalStyleSheet.innerHTML = MENU_WIDGET_CSS;
}
this.styleSheet = Menu.globalStyleSheet;
}
}
style(style: IMenuStyles): void {
const container = this.getContainer();
@@ -877,3 +895,298 @@ export function cleanMnemonic(label: string): string {
return label.replace(regex, mnemonicInText ? '$2$3' : '').trim();
}
let MENU_WIDGET_CSS: string = /* css */`
.monaco-menu {
font-size: 13px;
}
${formatRule(menuSelectionIcon)}
${formatRule(menuSubmenuIcon)}
.monaco-action-bar {
text-align: right;
overflow: hidden;
white-space: nowrap;
}
.monaco-action-bar .actions-container {
display: flex;
margin: 0 auto;
padding: 0;
width: 100%;
justify-content: flex-end;
}
.monaco-action-bar.vertical .actions-container {
display: inline-block;
}
.monaco-action-bar.reverse .actions-container {
flex-direction: row-reverse;
}
.monaco-action-bar .action-item {
cursor: pointer;
display: inline-block;
transition: transform 50ms ease;
position: relative; /* DO NOT REMOVE - this is the key to preventing the ghosting icon bug in Chrome 42 */
}
.monaco-action-bar .action-item.disabled {
cursor: default;
}
.monaco-action-bar.animated .action-item.active {
transform: scale(1.272019649, 1.272019649); /* 1.272019649 = √φ */
}
.monaco-action-bar .action-item .icon,
.monaco-action-bar .action-item .codicon {
display: inline-block;
}
.monaco-action-bar .action-item .codicon {
display: flex;
align-items: center;
}
.monaco-action-bar .action-label {
font-size: 11px;
margin-right: 4px;
}
.monaco-action-bar .action-item.disabled .action-label,
.monaco-action-bar .action-item.disabled .action-label:hover {
opacity: 0.4;
}
/* Vertical actions */
.monaco-action-bar.vertical {
text-align: left;
}
.monaco-action-bar.vertical .action-item {
display: block;
}
.monaco-action-bar.vertical .action-label.separator {
display: block;
border-bottom: 1px solid #bbb;
padding-top: 1px;
margin-left: .8em;
margin-right: .8em;
}
.monaco-action-bar.animated.vertical .action-item.active {
transform: translate(5px, 0);
}
.secondary-actions .monaco-action-bar .action-label {
margin-left: 6px;
}
/* Action Items */
.monaco-action-bar .action-item.select-container {
overflow: hidden; /* somehow the dropdown overflows its container, we prevent it here to not push */
flex: 1;
max-width: 170px;
min-width: 60px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
}
.monaco-menu .monaco-action-bar.vertical {
margin-left: 0;
overflow: visible;
}
.monaco-menu .monaco-action-bar.vertical .actions-container {
display: block;
}
.monaco-menu .monaco-action-bar.vertical .action-item {
padding: 0;
transform: none;
display: flex;
}
.monaco-menu .monaco-action-bar.vertical .action-item.active {
transform: none;
}
.monaco-menu .monaco-action-bar.vertical .action-menu-item {
flex: 1 1 auto;
display: flex;
height: 2em;
align-items: center;
position: relative;
}
.monaco-menu .monaco-action-bar.vertical .action-label {
flex: 1 1 auto;
text-decoration: none;
padding: 0 1em;
background: none;
font-size: 12px;
line-height: 1;
}
.monaco-menu .monaco-action-bar.vertical .keybinding,
.monaco-menu .monaco-action-bar.vertical .submenu-indicator {
display: inline-block;
flex: 2 1 auto;
padding: 0 1em;
text-align: right;
font-size: 12px;
line-height: 1;
}
.monaco-menu .monaco-action-bar.vertical .submenu-indicator {
height: 100%;
}
.monaco-menu .monaco-action-bar.vertical .submenu-indicator.codicon {
font-size: 16px !important;
display: flex;
align-items: center;
}
.monaco-menu .monaco-action-bar.vertical .submenu-indicator.codicon::before {
margin-left: auto;
margin-right: -20px;
}
.monaco-menu .monaco-action-bar.vertical .action-item.disabled .keybinding,
.monaco-menu .monaco-action-bar.vertical .action-item.disabled .submenu-indicator {
opacity: 0.4;
}
.monaco-menu .monaco-action-bar.vertical .action-label:not(.separator) {
display: inline-block;
box-sizing: border-box;
margin: 0;
}
.monaco-menu .monaco-action-bar.vertical .action-item {
position: static;
overflow: visible;
}
.monaco-menu .monaco-action-bar.vertical .action-item .monaco-submenu {
position: absolute;
}
.monaco-menu .monaco-action-bar.vertical .action-label.separator {
padding: 0.5em 0 0 0;
margin-bottom: 0.5em;
width: 100%;
height: 0px !important;
margin-left: .8em !important;
margin-right: .8em !important;
}
.monaco-menu .monaco-action-bar.vertical .action-label.separator.text {
padding: 0.7em 1em 0.1em 1em;
font-weight: bold;
opacity: 1;
}
.monaco-menu .monaco-action-bar.vertical .action-label:hover {
color: inherit;
}
.monaco-menu .monaco-action-bar.vertical .menu-item-check {
position: absolute;
visibility: hidden;
width: 1em;
height: 100%;
}
.monaco-menu .monaco-action-bar.vertical .action-menu-item.checked .menu-item-check {
visibility: visible;
display: flex;
align-items: center;
justify-content: center;
}
/* Context Menu */
.context-view.monaco-menu-container {
outline: 0;
border: none;
animation: fadeIn 0.083s linear;
}
.context-view.monaco-menu-container :focus,
.context-view.monaco-menu-container .monaco-action-bar.vertical:focus,
.context-view.monaco-menu-container .monaco-action-bar.vertical :focus {
outline: 0;
}
.monaco-menu .monaco-action-bar.vertical .action-item {
border: thin solid transparent; /* prevents jumping behaviour on hover or focus */
}
/* High Contrast Theming */
.hc-black .context-view.monaco-menu-container {
box-shadow: none;
}
.hc-black .monaco-menu .monaco-action-bar.vertical .action-item.focused {
background: none;
}
/* Vertical Action Bar Styles */
.monaco-menu .monaco-action-bar.vertical {
padding: .5em 0;
}
.monaco-menu .monaco-action-bar.vertical .action-menu-item {
height: 1.8em;
}
.monaco-menu .monaco-action-bar.vertical .action-label:not(.separator),
.monaco-menu .monaco-action-bar.vertical .keybinding {
font-size: inherit;
padding: 0 2em;
}
.monaco-menu .monaco-action-bar.vertical .menu-item-check {
font-size: inherit;
width: 2em;
}
.monaco-menu .monaco-action-bar.vertical .action-label.separator {
font-size: inherit;
padding: 0.2em 0 0 0;
margin-bottom: 0.2em;
}
linux .monaco-menu .monaco-action-bar.vertical .action-label.separator {
margin-left: 0;
margin-right: 0;
}
.monaco-menu .monaco-action-bar.vertical .submenu-indicator {
font-size: 60%;
padding: 0 1.8em;
}
:host-context(.linux) .monaco-menu .monaco-action-bar.vertical .submenu-indicator {
height: 100%;
mask-size: 10px 10px;
-webkit-mask-size: 10px 10px;
}
.monaco-menu .action-item {
cursor: default;
}
`;

View File

@@ -0,0 +1,83 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* Menubar styles */
.menubar {
display: flex;
flex-shrink: 1;
box-sizing: border-box;
height: 30px;
overflow: hidden;
flex-wrap: wrap;
}
.fullscreen .menubar:not(.compact) {
margin: 0px;
padding: 0px 5px;
}
.menubar > .menubar-menu-button {
align-items: center;
box-sizing: border-box;
padding: 0px 8px;
cursor: default;
-webkit-app-region: no-drag;
zoom: 1;
white-space: nowrap;
outline: 0;
}
.menubar.compact {
flex-shrink: 0;
overflow: visible; /* to avoid the compact menu to be repositioned when clicking */
}
.menubar.compact > .menubar-menu-button {
width: 100%;
height: 100%;
padding: 0px;
}
.menubar .menubar-menu-items-holder {
position: absolute;
left: 0px;
opacity: 1;
z-index: 2000;
}
.menubar .menubar-menu-items-holder.monaco-menu-container {
outline: 0;
border: none;
}
.menubar .menubar-menu-items-holder.monaco-menu-container :focus {
outline: 0;
}
.menubar .toolbar-toggle-more {
width: 20px;
height: 100%;
}
.menubar.compact .toolbar-toggle-more {
position: relative;
left: 0px;
top: 0px;
cursor: pointer;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.menubar .toolbar-toggle-more {
padding: 0;
vertical-align: sub;
}
.menubar.compact .toolbar-toggle-more::before {
content: "\eb94" !important;
}

View File

@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./menubar';
import * as browser from 'vs/base/browser/browser';
import * as DOM from 'vs/base/browser/dom';
import * as strings from 'vs/base/common/strings';

View File

@@ -3,8 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
import { VSBuffer } from 'vs/base/common/buffer';
import { regExpFlags } from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
export function stringify(obj: any): string {
return JSON.stringify(obj, replacer);
@@ -44,10 +45,23 @@ export function revive(obj: any, depth = 0): any {
case 2: return new RegExp(obj.source, obj.flags);
}
// walk object (or array)
for (let key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
obj[key] = revive(obj[key], depth + 1);
if (
obj instanceof VSBuffer
|| obj instanceof Uint8Array
) {
return obj;
}
if (Array.isArray(obj)) {
for (let i = 0; i < obj.length; ++i) {
obj[i] = revive(obj[i], depth + 1);
}
} else {
// walk object
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
obj[key] = revive(obj[key], depth + 1);
}
}
}
}

View File

@@ -16,6 +16,7 @@ export interface ISocket extends IDisposable {
onEnd(listener: () => void): IDisposable;
write(buffer: VSBuffer): void;
end(): void;
drain(): Promise<void>;
}
let emptyBuffer: VSBuffer | null = null;
@@ -277,6 +278,11 @@ class ProtocolWriter {
this._isDisposed = true;
}
public drain(): Promise<void> {
this.flush();
return this._socket.drain();
}
public flush(): void {
// flush
this._writeNow();
@@ -372,6 +378,10 @@ export class Protocol extends Disposable implements IMessagePassingProtocol {
this._register(this._socket.onClose(() => this._onClose.fire()));
}
drain(): Promise<void> {
return this._socketWriter.drain();
}
getSocket(): ISocket {
return this._socket;
}
@@ -619,6 +629,10 @@ export class PersistentProtocol implements IMessagePassingProtocol {
this._socketDisposables = dispose(this._socketDisposables);
}
drain(): Promise<void> {
return this._socketWriter.drain();
}
sendDisconnect(): void {
const msg = new ProtocolMessage(ProtocolMessageType.Disconnect, 0, 0, getEmptyBuffer());
this._socketWriter.write(msg);

View File

@@ -70,6 +70,10 @@ interface IHandler {
export interface IMessagePassingProtocol {
send(buffer: VSBuffer): void;
onMessage: Event<VSBuffer>;
/**
* Wait for the write buffer (if applicable) to become empty.
*/
drain?(): Promise<void>;
}
enum State {
@@ -482,10 +486,7 @@ export class ChannelClient implements IChannelClient, IDisposable {
return e(errors.canceled());
}
let uninitializedPromise: CancelablePromise<void> | null = createCancelablePromise(_ => this.whenInitialized());
uninitializedPromise.then(() => {
uninitializedPromise = null;
const doRequest = () => {
const handler: IHandler = response => {
switch (response.type) {
case ResponseType.PromiseSuccess:
@@ -510,7 +511,18 @@ export class ChannelClient implements IChannelClient, IDisposable {
this.handlers.set(id, handler);
this.sendRequest(request);
});
};
let uninitializedPromise: CancelablePromise<void> | null = null;
if (this.state === State.Idle) {
doRequest();
} else {
uninitializedPromise = createCancelablePromise(_ => this.whenInitialized());
uninitializedPromise.then(() => {
uninitializedPromise = null;
doRequest();
});
}
const cancel = () => {
if (uninitializedPromise) {

View File

@@ -12,6 +12,7 @@ import { generateUuid } from 'vs/base/common/uuid';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { VSBuffer } from 'vs/base/common/buffer';
import { ISocket, Protocol, Client, ChunkStream } from 'vs/base/parts/ipc/common/ipc.net';
import { onUnexpectedError } from 'vs/base/common/errors';
export class NodeSocket implements ISocket {
public readonly socket: Socket;
@@ -57,12 +58,47 @@ export class NodeSocket implements ISocket {
// > https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback
// > However, the false return value is only advisory and the writable stream will unconditionally
// > accept and buffer chunk even if it has not been allowed to drain.
this.socket.write(<Buffer>buffer.buffer);
try {
this.socket.write(<Buffer>buffer.buffer);
} catch (err) {
if (err.code === 'EPIPE') {
// An EPIPE exception at the wrong time can lead to a renderer process crash
// so ignore the error since the socket will fire the close event soon anyways:
// > https://nodejs.org/api/errors.html#errors_common_system_errors
// > EPIPE (Broken pipe): A write on a pipe, socket, or FIFO for which there is no
// > process to read the data. Commonly encountered at the net and http layers,
// > indicative that the remote side of the stream being written to has been closed.
return;
}
onUnexpectedError(err);
}
}
public end(): void {
this.socket.end();
}
public drain(): Promise<void> {
return new Promise<void>((resolve, reject) => {
if (this.socket.bufferSize === 0) {
resolve();
return;
}
const finished = () => {
this.socket.off('close', finished);
this.socket.off('end', finished);
this.socket.off('error', finished);
this.socket.off('timeout', finished);
this.socket.off('drain', finished);
resolve();
};
this.socket.on('close', finished);
this.socket.on('end', finished);
this.socket.on('error', finished);
this.socket.on('timeout', finished);
this.socket.on('drain', finished);
});
}
}
const enum Constants {
@@ -229,6 +265,10 @@ export class WebSocketNodeSocket extends Disposable implements ISocket {
}
}
}
public drain(): Promise<void> {
return this.socket.drain();
}
}
function unmask(buffer: VSBuffer, mask: number): void {