mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-22 01:29:04 +01:00
Allow for multiple editor parts (#193425)
* demo * wip * polish * allow to toggle * compile * enable devtools * cleanup * cleanup * cleanup * cleanup * cleanup * Avoid using global document, global window * Fix exception caused by reading the size of the newly created window before it is available * cleanup * make it more useful * apply zoom * first cut editor parts * cleanup * scaffold some services * preserve view state * simple label distinction * introduce accessor * support dnd * fix open editors view * share window options * cleanup * 💄 * 💄 * 💄 * 💄 * cleanup on unload * add todo * stylescleanup * avoid instanceof checks * share more styles * revert changes partially * fix custom menus * more alignment to main window * codicon does not seem to be needed anymore * no need for isHTMLElement * fix icon error on macOS * prevent `document.createElement` * close child window when main window closes * better active groups tracking * cleanup * pass along editor parts viewer * eslint rule for instanceof checks * add dom tests * cleanup * cleanup * cleanup * cleanup * cleanup * cleanup * cleanup * cleanup --------- Co-authored-by: Alex Dima <alexdima@microsoft.com>
This commit is contained in:
@@ -12,7 +12,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import * as event from 'vs/base/common/event';
|
||||
import * as dompurify from 'vs/base/browser/dompurify/dompurify';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore, IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { FileAccess, RemoteAuthorities, Schemas } from 'vs/base/common/network';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -729,6 +729,25 @@ export function getActiveDocument(): Document {
|
||||
return documents.find(doc => doc.hasFocus()) ?? document;
|
||||
}
|
||||
|
||||
export function getActiveWindow(): Window & typeof globalThis {
|
||||
const document = getActiveDocument();
|
||||
return document.defaultView?.window ?? window;
|
||||
}
|
||||
|
||||
function getWindow(e: unknown): Window & typeof globalThis {
|
||||
const candidateNode = e as Node | undefined;
|
||||
if (candidateNode?.ownerDocument?.defaultView) {
|
||||
return candidateNode.ownerDocument.defaultView.window;
|
||||
}
|
||||
|
||||
const candidateEvent = e as UIEvent | undefined;
|
||||
if (candidateEvent?.view) {
|
||||
return candidateEvent.view.window;
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
export function createStyleSheet(container: HTMLElement = document.getElementsByTagName('head')[0], beforeAppend?: (style: HTMLStyleElement) => void): HTMLStyleElement {
|
||||
const style = document.createElement('style');
|
||||
style.type = 'text/css';
|
||||
@@ -791,11 +810,24 @@ export function removeCSSRulesContainingSelector(ruleName: string, style: HTMLSt
|
||||
}
|
||||
}
|
||||
|
||||
export function isHTMLElement(o: any): o is HTMLElement {
|
||||
if (typeof HTMLElement === 'object') {
|
||||
return o instanceof HTMLElement;
|
||||
}
|
||||
return o && typeof o === 'object' && o.nodeType === 1 && typeof o.nodeName === 'string';
|
||||
export function isMouseEvent(e: unknown): e is MouseEvent {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return e instanceof MouseEvent || e instanceof getWindow(e).MouseEvent;
|
||||
}
|
||||
|
||||
export function isKeyboardEvent(e: unknown): e is KeyboardEvent {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return e instanceof KeyboardEvent || e instanceof getWindow(e).KeyboardEvent;
|
||||
}
|
||||
|
||||
export function isPointerEvent(e: unknown): e is PointerEvent {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return e instanceof PointerEvent || e instanceof getWindow(e).PointerEvent;
|
||||
}
|
||||
|
||||
export function isDragEvent(e: unknown): e is DragEvent {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return e instanceof DragEvent || e instanceof getWindow(e).DragEvent;
|
||||
}
|
||||
|
||||
export const EventType = {
|
||||
@@ -915,7 +947,7 @@ class FocusTracker extends Disposable implements IFocusTracker {
|
||||
private _refreshStateHandler: () => void;
|
||||
|
||||
private static hasFocusWithin(element: HTMLElement | Window): boolean {
|
||||
if (isHTMLElement(element)) {
|
||||
if (element instanceof HTMLElement) {
|
||||
const shadowRoot = getShadowRoot(element);
|
||||
const activeElement = (shadowRoot ? shadowRoot.activeElement : element.ownerDocument.activeElement);
|
||||
return isAncestor(activeElement, element);
|
||||
@@ -1942,3 +1974,58 @@ export function h(tag: string, ...args: [] | [attributes: { $: string } & Partia
|
||||
function camelCaseToHyphenCase(str: string) {
|
||||
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||
}
|
||||
|
||||
interface IObserver extends IDisposable {
|
||||
readonly onDidChangeAttribute: event.Event<string>;
|
||||
}
|
||||
|
||||
function observeAttributes(element: Element, filter?: string[]): IObserver {
|
||||
const onDidChangeAttribute = new event.Emitter<string>();
|
||||
|
||||
const observer = new MutationObserver(mutations => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type === 'attributes' && mutation.attributeName) {
|
||||
onDidChangeAttribute.fire(mutation.attributeName);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(element, {
|
||||
attributes: true,
|
||||
attributeFilter: filter
|
||||
});
|
||||
|
||||
return {
|
||||
onDidChangeAttribute: onDidChangeAttribute.event,
|
||||
dispose: () => {
|
||||
observer.disconnect();
|
||||
onDidChangeAttribute.dispose();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function copyAttributes(from: Element, to: Element): void {
|
||||
for (const { name, value } of from.attributes) {
|
||||
to.setAttribute(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
function copyAttribute(from: Element, to: Element, name: string): void {
|
||||
const value = from.getAttribute(name);
|
||||
if (value) {
|
||||
to.setAttribute(name, value);
|
||||
} else {
|
||||
to.removeAttribute(name);
|
||||
}
|
||||
}
|
||||
|
||||
export function trackAttributes(from: Element, to: Element, filter?: string[]): IDisposable {
|
||||
copyAttributes(from, to);
|
||||
|
||||
const observer = observeAttributes(from, filter);
|
||||
|
||||
return combinedDisposable(
|
||||
observer,
|
||||
observer.onDidChangeAttribute(name => copyAttribute(from, to, name))
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user