@@ -4,15 +4,15 @@ Date: Fri, 2 May 2025 10:13:06 +0200
44Subject: [PATCH] feat: support shadow dom
55
66---
7- src/vs/base/browser/dom.ts | 61 ++++++++++++++++---
8- src/vs/base/browser/domStylesheets.ts | 22 ++++- --
7+ src/vs/base/browser/dom.ts | 65 ++++++++++++++++---
8+ src/vs/base/browser/domStylesheets.ts | 22 +++++ --
99 src/vs/base/browser/keyboardEvent.ts | 12 +++-
1010 .../browser/ui/contextview/contextview.ts | 2 +-
1111 src/vs/base/browser/ui/dialog/dialog.ts | 6 +-
1212 src/vs/base/browser/ui/dnd/dnd.ts | 4 +-
1313 src/vs/base/browser/ui/findinput/findInput.ts | 3 +-
1414 .../base/browser/ui/findinput/replaceInput.ts | 3 +-
15- src/vs/base/browser/ui/inputbox/inputBox.ts | 7 ++ -
15+ src/vs/base/browser/ui/inputbox/inputBox.ts | 7 +-
1616 src/vs/base/browser/ui/sash/sash.css | 2 +-
1717 src/vs/base/browser/ui/sash/sash.ts | 2 +-
1818 src/vs/base/browser/ui/splitview/paneview.ts | 6 +-
@@ -32,10 +32,14 @@ Subject: [PATCH] feat: support shadow dom
3232 src/vs/platform/hover/browser/hoverWidget.ts | 2 +-
3333 .../platform/layout/browser/zIndexRegistry.ts | 2 +-
3434 .../platform/theme/browser/iconsStyleSheet.ts | 2 +-
35+ .../agentFeedbackEditorInputContribution.ts | 6 +-
3536 .../browser/actions/developerActions.ts | 4 +-
3637 src/vs/workbench/browser/layout.ts | 3 +
3738 .../browser/parts/editor/editorGroupView.ts | 4 +-
39+ .../browser/parts/editor/modalEditorPart.ts | 4 +-
3840 src/vs/workbench/browser/workbench.ts | 6 +-
41+ .../experiments/agentTitleBarStatusWidget.ts | 4 +-
42+ .../planReviewFeedbackEditorContribution.ts | 6 +-
3943 .../browser/widget/input/chatInputPart.ts | 2 +-
4044 .../files/browser/views/explorerViewer.ts | 4 +-
4145 .../notebook/browser/notebookEditorWidget.ts | 6 +-
@@ -46,19 +50,20 @@ Subject: [PATCH] feat: support shadow dom
4650 .../view/renderers/backLayerWebView.ts | 3 +-
4751 .../browser/preferences.contribution.ts | 3 +-
4852 .../preferences/browser/settingsEditor2.ts | 6 +-
49- .../terminal/browser/terminalService.ts | 7 +--
53+ .../terminal/browser/terminalService.ts | 7 +-
5054 .../terminal/browser/terminalTabbedView.ts | 2 +-
5155 .../contrib/terminal/browser/terminalView.ts | 2 +-
52- .../contrib/webview/browser/webviewElement.ts | 12 ++--
56+ .../contrib/webview/browser/webviewElement.ts | 14 ++--
5357 .../browser/gettingStarted.ts | 4 +-
58+ .../browser/onboardingVariationA.ts | 8 +--
5459 .../browser/walkThroughPart.ts | 6 +-
5560 .../browser/auxiliaryWindowService.ts | 6 +-
5661 .../suggest/browser/simpleSuggestWidget.ts | 4 +-
5762 .../themes/browser/workbenchThemeService.ts | 33 +++++++++-
58- 51 files changed, 235 insertions(+), 117 deletions(-)
63+ 56 files changed, 252 insertions(+), 134 deletions(-)
5964
6065diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
61- index e943bf0a557..6ebc4568a39 100644
66+ index e943bf0a557..7c7bce3ae00 100644
6267--- a/src/vs/base/browser/dom.ts
6368+++ b/src/vs/base/browser/dom.ts
6469@@ -257,6 +257,39 @@ export function addDisposableListener(node: EventTarget, type: string, handler:
@@ -140,7 +145,7 @@ index e943bf0a557..6ebc4568a39 100644
140145
141146 while (result?.shadowRoot) {
142147 result = result.shadowRoot.activeElement;
143- @@ -1022,6 +1054,14 @@ export function getActiveElement(): Element | null {
148+ @@ -1022,13 +1054,21 @@ export function getActiveElement(): Element | null {
144149 return result;
145150 }
146151
@@ -155,6 +160,23 @@ index e943bf0a557..6ebc4568a39 100644
155160 /**
156161 * Returns true if the focused window active element matches
157162 * the provided element. Falls back to the main window if no
163+ * window has focus.
164+ */
165+ export function isActiveElement(element: Element): boolean {
166+ - return getActiveElement() === element;
167+ + return getActiveElement(element.ownerDocument) === element;
168+ }
169+
170+ /**
171+ @@ -1036,7 +1076,7 @@ export function isActiveElement(element: Element): boolean {
172+ * `ancestor`. Falls back to the main window if no window has focus.
173+ */
174+ export function isAncestorOfActiveElement(ancestor: Element): boolean {
175+ - return isAncestor(getActiveElement(), ancestor);
176+ + return isAncestor(getActiveElement(ancestor.ownerDocument), ancestor);
177+ }
178+
179+ /**
158180@@ -1184,6 +1224,11 @@ export function isHTMLDivElement(e: unknown): e is HTMLDivElement {
159181 return e instanceof HTMLDivElement || e instanceof getWindow(e as Node).HTMLDivElement;
160182 }
@@ -838,6 +860,37 @@ index 7215f066d45..f55ed918b03 100644
838860
839861 return rules.join('\n');
840862 }
863+ diff --git a/src/vs/sessions/contrib/agentFeedback/browser/agentFeedbackEditorInputContribution.ts b/src/vs/sessions/contrib/agentFeedback/browser/agentFeedbackEditorInputContribution.ts
864+ index 0a2baa9cd08..b3a23939373 100644
865+ --- a/src/vs/sessions/contrib/agentFeedback/browser/agentFeedbackEditorInputContribution.ts
866+ +++ b/src/vs/sessions/contrib/agentFeedback/browser/agentFeedbackEditorInputContribution.ts
867+ @@ -11,7 +11,7 @@ import { EditorContributionInstantiation, registerEditorContribution } from '../
868+ import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
869+ import { EditorOption } from '../../../../editor/common/config/editorOptions.js';
870+ import { Selection, SelectionDirection } from '../../../../editor/common/core/selection.js';
871+ - import { addStandardDisposableListener, getWindow, ModifierKeyEmitter } from '../../../../base/browser/dom.js';
872+ + import { addStandardDisposableListener, getActiveElement, getWindow, isActiveElement, ModifierKeyEmitter } from '../../../../base/browser/dom.js';
873+ import { KeyCode } from '../../../../base/common/keyCodes.js';
874+ import { IAgentFeedbackService } from './agentFeedbackService.js';
875+ import { createAgentFeedbackContext } from './agentFeedbackEditorUtils.js';
876+ @@ -251,7 +251,7 @@ export class AgentFeedbackEditorInputContribution extends Disposable implements
877+ if (!this._visible) {
878+ return;
879+ }
880+ - if (this._isWidgetTarget(getWindow(this._editor.getDomNode()!).document.activeElement)) {
881+ + if (this._isWidgetTarget(getActiveElement(this._editor.getDomNode()!.ownerDocument))) {
882+ return;
883+ }
884+ this._autoHide();
885+ @@ -432,7 +432,7 @@ export class AgentFeedbackEditorInputContribution extends Disposable implements
886+ }
887+
888+ // If the input is not focused, focus it and let the keystroke go through
889+ - if (getWindow(widget.inputElement).document.activeElement !== widget.inputElement) {
890+ + if (!isActiveElement(widget.inputElement)) {
891+ widget.inputElement.focus();
892+ }
893+ }));
841894diff --git a/src/vs/workbench/browser/actions/developerActions.ts b/src/vs/workbench/browser/actions/developerActions.ts
842895index cdc59743913..14713c199ce 100644
843896--- a/src/vs/workbench/browser/actions/developerActions.ts
@@ -903,6 +956,28 @@ index 7b3e372a077..bef32d191c0 100644
903956 return true; // always restore focus if nothing is focused currently
904957 }
905958
959+ diff --git a/src/vs/workbench/browser/parts/editor/modalEditorPart.ts b/src/vs/workbench/browser/parts/editor/modalEditorPart.ts
960+ index 6301ce26e57..0d15376efa3 100644
961+ --- a/src/vs/workbench/browser/parts/editor/modalEditorPart.ts
962+ +++ b/src/vs/workbench/browser/parts/editor/modalEditorPart.ts
963+ @@ -4,7 +4,7 @@
964+ *--------------------------------------------------------------------------------------------*/
965+
966+ import './media/modalEditorPart.css';
967+ - import { $, addDisposableListener, append, Dimension, EventHelper, EventType, hide, IDimension, isHTMLElement, setVisibility, show } from '../../../../base/browser/dom.js';
968+ + import { $, addDisposableListener, append, Dimension, EventHelper, EventType, getActiveElement, hide, IDimension, isHTMLElement, setVisibility, show } from '../../../../base/browser/dom.js';
969+ import { GlobalPointerMoveMonitor } from '../../../../base/browser/globalPointerMoveMonitor.js';
970+ import { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
971+ import { ActionBar, prepareActions } from '../../../../base/browser/ui/actionbar/actionbar.js';
972+ @@ -923,7 +923,7 @@ class ModalEditorPartImpl extends EditorPart implements IModalEditorPart {
973+ }
974+
975+ override create(parent: HTMLElement, options?: object): void {
976+ - this.previousMainWindowActiveElement = mainWindow.document.activeElement;
977+ + this.previousMainWindowActiveElement = getActiveElement(mainWindow.document);
978+
979+ super.create(parent, options);
980+ }
906981diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts
907982index 7796aae8a15..1c304a11a9e 100644
908983--- a/src/vs/workbench/browser/workbench.ts
@@ -927,6 +1002,59 @@ index 7796aae8a15..1c304a11a9e 100644
9271002 }
9281003
9291004 private createPart(id: string, role: string, classes: string[]): HTMLElement {
1005+ diff --git a/src/vs/workbench/contrib/chat/browser/agentSessions/experiments/agentTitleBarStatusWidget.ts b/src/vs/workbench/contrib/chat/browser/agentSessions/experiments/agentTitleBarStatusWidget.ts
1006+ index 59d9960e78c..96d5fdc92a9 100644
1007+ --- a/src/vs/workbench/contrib/chat/browser/agentSessions/experiments/agentTitleBarStatusWidget.ts
1008+ +++ b/src/vs/workbench/contrib/chat/browser/agentSessions/experiments/agentTitleBarStatusWidget.ts
1009+ @@ -4,7 +4,7 @@
1010+ *--------------------------------------------------------------------------------------------*/
1011+
1012+ import './media/agenttitlebarstatuswidget.css';
1013+ - import { $, addDisposableListener, EventType, getWindow, isHTMLElement, reset } from '../../../../../../base/browser/dom.js';
1014+ + import { $, addDisposableListener, EventType, getActiveElement, isHTMLElement, reset } from '../../../../../../base/browser/dom.js';
1015+ import { renderIcon } from '../../../../../../base/browser/ui/iconLabel/iconLabels.js';
1016+ import { Disposable, DisposableStore } from '../../../../../../base/common/lifecycle.js';
1017+ import { Codicon } from '../../../../../../base/common/codicons.js';
1018+ @@ -295,7 +295,7 @@ export class AgentTitleBarStatusWidget extends BaseActionViewItem {
1019+ if (!this._container) {
1020+ return;
1021+ }
1022+ - const activeElement = getWindow(this._container).document.activeElement;
1023+ + const activeElement = getActiveElement(this._container.ownerDocument);
1024+ if (isHTMLElement(activeElement) && this._container.contains(activeElement)) {
1025+ activeElement.blur();
1026+ }
1027+ diff --git a/src/vs/workbench/contrib/chat/browser/planReviewFeedback/planReviewFeedbackEditorContribution.ts b/src/vs/workbench/contrib/chat/browser/planReviewFeedback/planReviewFeedbackEditorContribution.ts
1028+ index 7486d45ae40..b3867ac6a12 100644
1029+ --- a/src/vs/workbench/contrib/chat/browser/planReviewFeedback/planReviewFeedbackEditorContribution.ts
1030+ +++ b/src/vs/workbench/contrib/chat/browser/planReviewFeedback/planReviewFeedbackEditorContribution.ts
1031+ @@ -14,7 +14,7 @@ import { Range } from '../../../../../editor/common/core/range.js';
1032+ import { OverviewRulerLane } from '../../../../../editor/common/model.js';
1033+ import { themeColorFromId } from '../../../../../platform/theme/common/themeService.js';
1034+ import { overviewRulerInfo } from '../../../../../editor/common/core/editorColorRegistry.js';
1035+ - import { addStandardDisposableListener, getWindow } from '../../../../../base/browser/dom.js';
1036+ + import { addStandardDisposableListener, getActiveElement, getWindow, isActiveElement } from '../../../../../base/browser/dom.js';
1037+ import { KeyCode } from '../../../../../base/common/keyCodes.js';
1038+ import { localize } from '../../../../../nls.js';
1039+ import { ActionBar } from '../../../../../base/browser/ui/actionbar/actionbar.js';
1040+ @@ -303,7 +303,7 @@ export class PlanReviewFeedbackEditorContribution extends Disposable implements
1041+ if (!this._visible) {
1042+ return;
1043+ }
1044+ - if (this._isWidgetTarget(getWindow(this._editor.getDomNode()!).document.activeElement)) {
1045+ + if (this._isWidgetTarget(getActiveElement(this._editor.getDomNode()!.ownerDocument))) {
1046+ return;
1047+ }
1048+ this._hide();
1049+ @@ -452,7 +452,7 @@ export class PlanReviewFeedbackEditorContribution extends Disposable implements
1050+ return;
1051+ }
1052+
1053+ - if (getWindow(widget.inputElement).document.activeElement !== widget.inputElement) {
1054+ + if (!isActiveElement(widget.inputElement)) {
1055+ widget.inputElement.focus();
1056+ }
1057+ }));
9301058diff --git a/src/vs/workbench/contrib/chat/browser/widget/input/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/widget/input/chatInputPart.ts
9311059index 2c67995e535..f11bf0d7a09 100644
9321060--- a/src/vs/workbench/contrib/chat/browser/widget/input/chatInputPart.ts
@@ -1236,15 +1364,15 @@ index 9a745727415..32b87509ab3 100644
12361364 const listener = this._register(Event.once(this._terminalService.onDidChangeConnectionState)(() => {
12371365 // Only focus the terminal if the activeElement has not changed since focus() was called
12381366diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts
1239- index 9f6018c77f5..e065c4bcc81 100644
1367+ index 9f6018c77f5..25085c88cde 100644
12401368--- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts
12411369+++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts
12421370@@ -4,7 +4,7 @@
12431371 *--------------------------------------------------------------------------------------------*/
12441372
12451373 import { isFirefox } from '../../../../base/browser/browser.js';
12461374- import { addDisposableListener, EventType, getWindow, getWindowById } from '../../../../base/browser/dom.js';
1247- + import { addDisposableListener, EventType, getActiveElement, getWindow, getWindowById } from '../../../../base/browser/dom.js';
1375+ + import { addDisposableListener, EventType, getActiveElement, getWindow, getWindowById, isActiveElement } from '../../../../base/browser/dom.js';
12481376 import { parentOriginHash } from '../../../../base/browser/iframe.js';
12491377 import { IMouseWheelEvent } from '../../../../base/browser/mouseEvent.js';
12501378 import { CodeWindow } from '../../../../base/browser/window.js';
@@ -1253,19 +1381,28 @@ index 9f6018c77f5..e065c4bcc81 100644
12531381 }
12541382
12551383- if (this.window.document.activeElement && this.window.document.activeElement !== this.element) {
1256- + const activeElement = getActiveElement(this.window.document)
1384+ + const activeElement = getActiveElement(this.window.document);
12571385+ if (activeElement && activeElement !== this.element) {
12581386 // looks like https://github.com/microsoft/vscode/issues/132641
12591387 // where the focus is actually not in the `<iframe>`
12601388 return false;
1389+ @@ -712,7 +713,7 @@ export class WebviewElement extends Disposable implements IWebviewElement, Webvi
1390+ }
1391+
1392+ private isActiveElement(): boolean {
1393+ - return !!this.element && this.window?.document.activeElement === this.element;
1394+ + return !!this.element && isActiveElement(this.element);
1395+ }
1396+
1397+ private handleKeyEvent(type: 'keydown' | 'keyup', event: KeyEvent) {
12611398@@ -956,8 +957,11 @@ export class WebviewElement extends Disposable implements IWebviewElement, Webvi
12621399 return;
12631400 }
12641401
12651402- if (this.window?.document.activeElement && this.window.document.activeElement !== this.element && this.window.document.activeElement?.tagName !== 'BODY') {
12661403- return;
12671404+ if (this.window) {
1268- + const activeElement = getActiveElement(this.window?.document)
1405+ + const activeElement = getActiveElement(this.window?.document);
12691406+ if (activeElement && activeElement !== this.element && activeElement?.tagName !== 'BODY') {
12701407+ return;
12711408+ }
@@ -1294,6 +1431,41 @@ index 0cb22b9cf17..64f8a2c27d7 100644
12941431
12951432 let parent = this.container.parentElement;
12961433 while (parent && parent !== active) {
1434+ diff --git a/src/vs/workbench/contrib/welcomeOnboarding/browser/onboardingVariationA.ts b/src/vs/workbench/contrib/welcomeOnboarding/browser/onboardingVariationA.ts
1435+ index ad276fc2c49..84d56dfff12 100644
1436+ --- a/src/vs/workbench/contrib/welcomeOnboarding/browser/onboardingVariationA.ts
1437+ +++ b/src/vs/workbench/contrib/welcomeOnboarding/browser/onboardingVariationA.ts
1438+ @@ -5,7 +5,7 @@
1439+
1440+ import { Disposable, DisposableStore } from '../../../../base/common/lifecycle.js';
1441+ import { Emitter, Event } from '../../../../base/common/event.js';
1442+ - import { $, append, addDisposableListener, EventType, clearNode, getActiveWindow } from '../../../../base/browser/dom.js';
1443+ + import { $, append, addDisposableListener, EventType, clearNode, getActiveWindow, getActiveElement, isActiveElement } from '../../../../base/browser/dom.js';
1444+ import { isCancellationError } from '../../../../base/common/errors.js';
1445+ import { StopWatch } from '../../../../base/common/stopwatch.js';
1446+ import { URI } from '../../../../base/common/uri.js';
1447+ @@ -172,7 +172,7 @@ export class OnboardingVariationA extends Disposable implements IOnboardingServi
1448+ }
1449+
1450+ this._isShowing = true;
1451+ - this.previouslyFocusedElement = getActiveWindow().document.activeElement as HTMLElement | undefined;
1452+ + this.previouslyFocusedElement = getActiveElement() as HTMLElement | undefined;
1453+
1454+ const container = this.layoutService.activeContainer;
1455+
1456+ @@ -1268,10 +1268,10 @@ export class OnboardingVariationA extends Disposable implements IOnboardingServi
1457+ const first = allFocusable[0];
1458+ const last = allFocusable[allFocusable.length - 1];
1459+
1460+ - if (shiftKey && getActiveWindow().document.activeElement === first) {
1461+ + if (shiftKey && isActiveElement(first)) {
1462+ e.preventDefault();
1463+ last.focus();
1464+ - } else if (!shiftKey && getActiveWindow().document.activeElement === last) {
1465+ + } else if (!shiftKey && isActiveElement(last)) {
1466+ e.preventDefault();
1467+ first.focus();
1468+ }
12971469diff --git a/src/vs/workbench/contrib/welcomeWalkthrough/browser/walkThroughPart.ts b/src/vs/workbench/contrib/welcomeWalkthrough/browser/walkThroughPart.ts
12981470index c6fb17f8525..8691b2f7a37 100644
12991471--- a/src/vs/workbench/contrib/welcomeWalkthrough/browser/walkThroughPart.ts
0 commit comments