Merge from vscode cfbd1999769f4f08dce29629fb92fdc0fac53829

This commit is contained in:
ADS Merger
2020-08-06 07:08:52 +00:00
parent 9c67832880
commit 540046ba00
362 changed files with 7588 additions and 6584 deletions

View File

@@ -749,6 +749,16 @@ export function getShadowRoot(domNode: Node): ShadowRoot | null {
return isShadowRoot(domNode) ? domNode : null;
}
export function getActiveElement(): Element | null {
let result = document.activeElement;
while (result?.shadowRoot) {
result = result.shadowRoot.activeElement;
}
return result;
}
export function createStyleSheet(container: HTMLElement = document.getElementsByTagName('head')[0]): HTMLStyleElement {
let style = document.createElement('style');
style.type = 'text/css';

View File

@@ -137,17 +137,9 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
this._register(DOM.addDisposableListener(element, DOM.EventType.CLICK, e => {
DOM.EventHelper.stop(e, true);
// See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Interact_with_the_clipboard
// > Writing to the clipboard
// > You can use the "cut" and "copy" commands without any special
// permission if you are using them in a short-lived event handler
// for a user action (for example, a click handler).
// => to get the Copy and Paste context menu actions working on Firefox,
// there should be no timeout here
if (this.options && this.options.isMenu) {
this.onClick(e);
} else {
// menus do not use the click event
if (!(this.options && this.options.isMenu)) {
platform.setImmediate(() => this.onClick(e));
}
}));

View File

@@ -173,7 +173,7 @@ export class ActionBar extends Disposable implements IActionRunner {
this.focusTracker = this._register(DOM.trackFocus(this.domNode));
this._register(this.focusTracker.onDidBlur(() => {
if (document.activeElement === this.domNode || !DOM.isAncestor(document.activeElement, this.domNode)) {
if (DOM.getActiveElement() === this.domNode || !DOM.isAncestor(DOM.getActiveElement(), this.domNode)) {
this._onDidBlur.fire();
this.focusedItem = undefined;
}
@@ -214,7 +214,7 @@ export class ActionBar extends Disposable implements IActionRunner {
private updateFocusedItem(): void {
for (let i = 0; i < this.actionsList.children.length; i++) {
const elem = this.actionsList.children[i];
if (DOM.isAncestor(document.activeElement, elem)) {
if (DOM.isAncestor(DOM.getActiveElement(), elem)) {
this.focusedItem = i;
break;
}

View File

@@ -156,7 +156,7 @@ export class ContextView extends Disposable {
if (this.useShadowDOM) {
this.shadowRootHostElement = DOM.$('.shadow-root-host');
this.container.appendChild(this.shadowRootHostElement);
this.shadowRoot = this.shadowRootHostElement.attachShadow({ mode: 'closed' });
this.shadowRoot = this.shadowRootHostElement.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
${SHADOW_ROOT_CSS}
@@ -215,6 +215,10 @@ export class ContextView extends Disposable {
}
}
getViewElement(): HTMLElement {
return this.view;
}
layout(): void {
if (!this.isVisible()) {
return;
@@ -372,9 +376,9 @@ let SHADOW_ROOT_CSS = /* css */ `
: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; }
:host-context(.linux) { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; }
:host-context(.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(.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(.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(.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

@@ -8,7 +8,7 @@ import * as strings from 'vs/base/common/strings';
import { IActionRunner, IAction, SubmenuAction, Separator, IActionViewItemProvider } from 'vs/base/common/actions';
import { ActionBar, ActionsOrientation } 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, createStyleSheet, isInShadowDOM } from 'vs/base/browser/dom';
import { addClass, EventType, EventHelper, EventLike, removeTabIndexAndUpdateFocus, isAncestor, hasClass, addDisposableListener, removeClass, append, $, addClasses, removeClasses, clearNode, createStyleSheet, isInShadowDOM, getActiveElement, Dimension, IDomNodePagePosition } 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';
@@ -16,11 +16,13 @@ import { Color } from 'vs/base/common/color';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';
import { Event } from 'vs/base/common/event';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { AnchorAlignment, layout, LayoutAnchorPosition } 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 { BaseActionViewItem, ActionViewItem, IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { formatRule } from 'vs/base/browser/ui/codicons/codiconStyles';
import { isFirefox } from 'vs/base/browser/browser';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
export const MENU_MNEMONIC_REGEX = /\(&([^\s&])\)|(^|[^&])&([^\s&])/;
export const MENU_ESCAPED_MNEMONIC_REGEX = /(&amp;)?(&amp;)([^\s&])/g;
@@ -203,7 +205,7 @@ export class Menu extends ActionBar {
e.preventDefault();
}));
menuElement.style.maxHeight = `${Math.max(10, window.innerHeight - container.getBoundingClientRect().top - 30)}px`;
menuElement.style.maxHeight = `${Math.max(10, window.innerHeight - container.getBoundingClientRect().top - 35)}px`;
actions = actions.filter(a => {
if (options.submenuIds?.has(a.id)) {
@@ -423,7 +425,37 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
// with BaseActionViewItem #101537
// add back if issues arise and link new issue
EventHelper.stop(e, true);
this.onClick(e);
// See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Interact_with_the_clipboard
// > Writing to the clipboard
// > You can use the "cut" and "copy" commands without any special
// permission if you are using them in a short-lived event handler
// for a user action (for example, a click handler).
// => to get the Copy and Paste context menu actions working on Firefox,
// there should be no timeout here
if (isFirefox) {
const mouseEvent = new StandardMouseEvent(e);
// Allowing right click to trigger the event causes the issue described below,
// but since the solution below does not work in FF, we must disable right click
if (mouseEvent.rightButton) {
return;
}
this.onClick(e);
}
// In all other cases, set timout to allow context menu cancellation to trigger
// otherwise the action will destroy the menu and a second context menu
// will still trigger for right click.
setTimeout(() => {
this.onClick(e);
}, 0);
}));
this._register(addDisposableListener(this.element, EventType.CONTEXT_MENU, e => {
EventHelper.stop(e, true);
}));
}, 100);
@@ -679,7 +711,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
}, 250);
this.hideScheduler = new RunOnceScheduler(() => {
if (this.element && (!isAncestor(document.activeElement, this.element) && this.parentData.submenu === this.mysubmenu)) {
if (this.element && (!isAncestor(getActiveElement(), this.element) && this.parentData.submenu === this.mysubmenu)) {
this.parentData.parent.focus(false);
this.cleanupExistingSubmenu(true);
}
@@ -713,7 +745,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
this._register(addDisposableListener(this.element, EventType.KEY_DOWN, e => {
let event = new StandardKeyboardEvent(e);
if (document.activeElement === this.item) {
if (getActiveElement() === this.item) {
if (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Enter)) {
EventHelper.stop(e, true);
}
@@ -733,7 +765,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
}));
this._register(addDisposableListener(this.element, EventType.FOCUS_OUT, e => {
if (this.element && !isAncestor(document.activeElement, this.element)) {
if (this.element && !isAncestor(getActiveElement(), this.element)) {
this.hideScheduler.schedule();
}
}));
@@ -769,6 +801,33 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
}
}
private calculateSubmenuMenuLayout(windowDimensions: Dimension, submenu: Dimension, entry: IDomNodePagePosition, expandDirection: Direction): { top: number, left: number } {
const ret = { top: 0, left: 0 };
// Start with horizontal
ret.left = layout(windowDimensions.width, submenu.width, { position: expandDirection === Direction.Right ? LayoutAnchorPosition.Before : LayoutAnchorPosition.After, offset: entry.left, size: entry.width });
// We don't have enough room to layout the menu fully, so we are overlapping the menu
if (ret.left >= entry.left && ret.left < entry.left + entry.width) {
if (entry.left + 10 + submenu.width <= windowDimensions.width) {
ret.left = entry.left + 10;
}
entry.top += 10;
entry.height = 0;
}
// Now that we have a horizontal position, try layout vertically
ret.top = layout(windowDimensions.height, submenu.height, { position: LayoutAnchorPosition.Before, offset: entry.top, size: 0 });
// We didn't have enough room below, but we did above, so we shift down to align the menu
if (ret.top + submenu.height === entry.top && ret.top + entry.height + submenu.height <= windowDimensions.height) {
ret.top += entry.height;
}
return ret;
}
private createSubmenu(selectFirstItem = true): void {
if (!this.element) {
return;
@@ -776,36 +835,40 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
if (!this.parentData.submenu) {
this.updateAriaExpanded('true');
this.submenuContainer = append(this.element, $('div.monaco-submenu'));
this.submenuContainer = document.createElement('div.monaco-submenu');
addClasses(this.submenuContainer, 'menubar-menu-items-holder', 'context-view');
// Set the top value of the menu container before construction
// This allows the menu constructor to calculate the proper max height
const computedStyles = getComputedStyle(this.parentData.parent.domNode);
const paddingTop = parseFloat(computedStyles.paddingTop || '0') || 0;
this.submenuContainer.style.top = `${this.element.offsetTop - this.parentData.parent.scrollOffset - paddingTop}px`;
// this.submenuContainer.style.top = `${this.element.offsetTop - this.parentData.parent.scrollOffset - paddingTop}px`;
this.submenuContainer.style.zIndex = '1';
this.submenuContainer.style.position = 'fixed';
this.submenuContainer.style.top = '0';
this.submenuContainer.style.left = '0';
this.parentData.submenu = new Menu(this.submenuContainer, this.submenuActions, this.submenuOptions);
if (this.menuStyle) {
this.parentData.submenu.style(this.menuStyle);
}
const boundingRect = this.element.getBoundingClientRect();
const childBoundingRect = this.submenuContainer.getBoundingClientRect();
this.element.appendChild(this.submenuContainer);
if (this.expandDirection === Direction.Right) {
if (window.innerWidth <= boundingRect.right + childBoundingRect.width) {
this.submenuContainer.style.left = '10px';
this.submenuContainer.style.top = `${this.element.offsetTop - this.parentData.parent.scrollOffset + boundingRect.height}px`;
} else {
this.submenuContainer.style.left = `${this.element.offsetWidth}px`;
this.submenuContainer.style.top = `${this.element.offsetTop - this.parentData.parent.scrollOffset - paddingTop}px`;
}
} else if (this.expandDirection === Direction.Left) {
this.submenuContainer.style.right = `${this.element.offsetWidth}px`;
this.submenuContainer.style.left = 'auto';
this.submenuContainer.style.top = `${this.element.offsetTop - this.parentData.parent.scrollOffset - paddingTop}px`;
}
// layout submenu
const entryBox = this.element.getBoundingClientRect();
const entryBoxUpdated = {
top: entryBox.top - paddingTop,
left: entryBox.left,
height: entryBox.height + 2 * paddingTop,
width: entryBox.width
};
const viewBox = this.submenuContainer.getBoundingClientRect();
const { top, left } = this.calculateSubmenuMenuLayout({ height: window.innerHeight, width: window.innerWidth }, viewBox, entryBoxUpdated, this.expandDirection);
this.submenuContainer.style.left = `${left}px`;
this.submenuContainer.style.top = `${top}px`;
this.submenuDisposables.add(addDisposableListener(this.submenuContainer, EventType.KEY_UP, e => {
let event = new StandardKeyboardEvent(e);
@@ -911,13 +974,13 @@ let MENU_WIDGET_CSS: string = /* css */`
${formatRule(menuSelectionIcon)}
${formatRule(menuSubmenuIcon)}
.monaco-action-bar {
.monaco-menu .monaco-action-bar {
text-align: right;
overflow: hidden;
white-space: nowrap;
}
.monaco-action-bar .actions-container {
.monaco-menu .monaco-action-bar .actions-container {
display: flex;
margin: 0 auto;
padding: 0;
@@ -925,60 +988,60 @@ ${formatRule(menuSubmenuIcon)}
justify-content: flex-end;
}
.monaco-action-bar.vertical .actions-container {
.monaco-menu .monaco-action-bar.vertical .actions-container {
display: inline-block;
}
.monaco-action-bar.reverse .actions-container {
.monaco-menu .monaco-action-bar.reverse .actions-container {
flex-direction: row-reverse;
}
.monaco-action-bar .action-item {
.monaco-menu .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 {
.monaco-menu .monaco-action-bar .action-item.disabled {
cursor: default;
}
.monaco-action-bar.animated .action-item.active {
.monaco-menu .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 {
.monaco-menu .monaco-action-bar .action-item .icon,
.monaco-menu .monaco-action-bar .action-item .codicon {
display: inline-block;
}
.monaco-action-bar .action-item .codicon {
.monaco-menu .monaco-action-bar .action-item .codicon {
display: flex;
align-items: center;
}
.monaco-action-bar .action-label {
.monaco-menu .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 {
.monaco-menu .monaco-action-bar .action-item.disabled .action-label,
.monaco-menu .monaco-action-bar .action-item.disabled .action-label:hover {
opacity: 0.4;
}
/* Vertical actions */
.monaco-action-bar.vertical {
.monaco-menu .monaco-action-bar.vertical {
text-align: left;
}
.monaco-action-bar.vertical .action-item {
.monaco-menu .monaco-action-bar.vertical .action-item {
display: block;
}
.monaco-action-bar.vertical .action-label.separator {
.monaco-menu .monaco-action-bar.vertical .action-label.separator {
display: block;
border-bottom: 1px solid #bbb;
padding-top: 1px;
@@ -986,16 +1049,12 @@ ${formatRule(menuSubmenuIcon)}
margin-right: .8em;
}
.monaco-action-bar.animated.vertical .action-item.active {
transform: translate(5px, 0);
}
.secondary-actions .monaco-action-bar .action-label {
.monaco-menu .secondary-actions .monaco-action-bar .action-label {
margin-left: 6px;
}
/* Action Items */
.monaco-action-bar .action-item.select-container {
.monaco-menu .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;
@@ -1140,11 +1199,11 @@ ${formatRule(menuSubmenuIcon)}
/* High Contrast Theming */
.hc-black .context-view.monaco-menu-container {
:host-context(.hc-black) .context-view.monaco-menu-container {
box-shadow: none;
}
.hc-black .monaco-menu .monaco-action-bar.vertical .action-item.focused {
:host-context(.hc-black) .monaco-menu .monaco-action-bar.vertical .action-item.focused {
background: none;
}
@@ -1175,7 +1234,7 @@ ${formatRule(menuSubmenuIcon)}
margin-bottom: 0.2em;
}
linux .monaco-menu .monaco-action-bar.vertical .action-label.separator {
:host-context(.linux) .monaco-menu .monaco-action-bar.vertical .action-label.separator {
margin-left: 0;
margin-right: 0;
}
@@ -1195,4 +1254,110 @@ linux .monaco-menu .monaco-action-bar.vertical .action-label.separator {
cursor: default;
}
/* Arrows */
.monaco-scrollable-element > .scrollbar > .scra {
cursor: pointer;
font-size: 11px !important;
}
.monaco-scrollable-element > .visible {
opacity: 1;
/* Background rule added for IE9 - to allow clicks on dom node */
background:rgba(0,0,0,0);
transition: opacity 100ms linear;
}
.monaco-scrollable-element > .invisible {
opacity: 0;
pointer-events: none;
}
.monaco-scrollable-element > .invisible.fade {
transition: opacity 800ms linear;
}
/* Scrollable Content Inset Shadow */
.monaco-scrollable-element > .shadow {
position: absolute;
display: none;
}
.monaco-scrollable-element > .shadow.top {
display: block;
top: 0;
left: 3px;
height: 3px;
width: 100%;
box-shadow: #DDD 0 6px 6px -6px inset;
}
.monaco-scrollable-element > .shadow.left {
display: block;
top: 3px;
left: 0;
height: 100%;
width: 3px;
box-shadow: #DDD 6px 0 6px -6px inset;
}
.monaco-scrollable-element > .shadow.top-left-corner {
display: block;
top: 0;
left: 0;
height: 3px;
width: 3px;
}
.monaco-scrollable-element > .shadow.top.left {
box-shadow: #DDD 6px 6px 6px -6px inset;
}
/* ---------- Default Style ---------- */
:host-context(.vs) .monaco-scrollable-element > .scrollbar > .slider {
background: rgba(100, 100, 100, .4);
}
:host-context(.vs-dark) .monaco-scrollable-element > .scrollbar > .slider {
background: rgba(121, 121, 121, .4);
}
:host-context(.hc-black) .monaco-scrollable-element > .scrollbar > .slider {
background: rgba(111, 195, 223, .6);
}
.monaco-scrollable-element > .scrollbar > .slider:hover {
background: rgba(100, 100, 100, .7);
}
:host-context(.hc-black) .monaco-scrollable-element > .scrollbar > .slider:hover {
background: rgba(111, 195, 223, .8);
}
.monaco-scrollable-element > .scrollbar > .slider.active {
background: rgba(0, 0, 0, .6);
}
:host-context(.vs-dark) .monaco-scrollable-element > .scrollbar > .slider.active {
background: rgba(191, 191, 191, .4);
}
:host-context(.hc-black) .monaco-scrollable-element > .scrollbar > .slider.active {
background: rgba(111, 195, 223, 1);
}
:host-context(.vs-dark) .monaco-scrollable-element .shadow.top {
box-shadow: none;
}
:host-context(.vs-dark) .monaco-scrollable-element .shadow.left {
box-shadow: #000 6px 0 6px -6px inset;
}
:host-context(.vs-dark) .monaco-scrollable-element .shadow.top.left {
box-shadow: #000 6px 6px 6px -6px inset;
}
:host-context(.hc-black) .monaco-scrollable-element .shadow.top {
box-shadow: none;
}
:host-context(.hc-black) .monaco-scrollable-element .shadow.left {
box-shadow: none;
}
:host-context(.hc-black) .monaco-scrollable-element .shadow.top.left {
box-shadow: none;
}
`;

View File

@@ -217,7 +217,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
// Intercept keyboard handling
this._register(dom.addDisposableListener(this.selectElement, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {
// React on KEY_UP since the actionBar also reacts on KEY_UP so that appropriate events get canceled
this._register(dom.addDisposableListener(this.selectElement, dom.EventType.KEY_UP, (e: KeyboardEvent) => {
const event = new StandardKeyboardEvent(e);
let showDropDown = false;
@@ -234,7 +235,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
if (showDropDown) {
this.showSelectDropDown();
dom.EventHelper.stop(e);
dom.EventHelper.stop(e, true);
}
}));
}