提交 3338ff4e 编写于 作者: M Matt Bierner

Fixes navigation commands for webviews

Fixes #100536

These commands currently do not work because:

- The use the `hasFocus` check in layout.ts
- This looks at the active element and checks if the active element has a parent in the editor dom
- However webviews are outside of the normal dom flow (since they cannot be reparented without being destroyred)

To fix this, this PR adds allows dom node to point to their explicit parent using `setParentFlowTo`. Instead of a normal ancestor check, we then check ancestors while observing the flow to parents of node

The webview element is then update to have a parent flow to that points at its editor node
上级 6e2aa0bf
......@@ -661,6 +661,43 @@ export function isAncestor(testChild: Node | null, testAncestor: Node | null): b
return false;
}
const parentFlowToDataKey = 'parentFlowToElementId';
/**
* Set an explicit parent to use for nodes that are not part of the
* regular dom structure.
*/
export function setParentFlowTo(fromChildElement: HTMLElement, toParentElement: Element): void {
fromChildElement.dataset[parentFlowToDataKey] = toParentElement.id;
}
/**
* Check if `testAncestor` is an ancessor of `testChild`, observing the explicit
* parents set by `setParentFlowTo`.
*/
export function isAncestorUsingFlowTo(testChild: Node, testAncestor: Node): boolean {
let node: Node | null = testChild;
while (node) {
if (node === testAncestor) {
return true;
}
if (node instanceof HTMLElement) {
const flowToParentId = node.dataset[parentFlowToDataKey];
if (typeof flowToParentId === 'string') {
const flowToParentElement = document.getElementById(flowToParentId);
if (flowToParentElement) {
node = flowToParentElement;
continue;
}
}
}
node = node.parentNode;
}
return false;
}
export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement | null {
while (node && node.nodeType === node.ELEMENT_NODE) {
if (node.classList.contains(clazz)) {
......
......@@ -5,7 +5,7 @@
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event';
import { EventType, addDisposableListener, isAncestor, getClientArea, Dimension, position, size, IDimension } from 'vs/base/browser/dom';
import { EventType, addDisposableListener, getClientArea, Dimension, position, size, IDimension, isAncestorUsingFlowTo } from 'vs/base/browser/dom';
import { onDidChangeFullscreen, isFullscreen } from 'vs/base/browser/browser';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { Registry } from 'vs/platform/registry/common/platform';
......@@ -999,7 +999,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
const container = this.getContainer(part);
return !!container && isAncestor(activeElement, container);
return !!container && isAncestorUsingFlowTo(activeElement, container);
}
focusPart(part: Parts): void {
......
......@@ -8,18 +8,19 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { isWeb } from 'vs/base/common/platform';
import { generateUuid } from 'vs/base/common/uuid';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { IEditorDropService } from 'vs/workbench/services/editor/browser/editorDropService';
import { EditorInput, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import { WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
import { IEditorDropService } from 'vs/workbench/services/editor/browser/editorDropService';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
export class WebviewEditor extends EditorPane {
......@@ -54,6 +55,7 @@ export class WebviewEditor extends EditorPane {
protected createEditor(parent: HTMLElement): void {
const element = document.createElement('div');
this._element = element;
this._element.id = `webview-editor-element-${generateUuid()}`;
parent.appendChild(element);
}
......@@ -143,6 +145,7 @@ export class WebviewEditor extends EditorPane {
if (this._element) {
this._element.setAttribute('aria-flowto', input.webview.container.id);
DOM.setParentFlowTo(input.webview.container, this._element);
}
this._webviewVisibleDisposables.clear();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册