@@ -553,6 +553,12 @@ export class DockviewComponent
553553 readonly onDidRemovePopoutGroup : Event < PopoutGroup > =
554554 this . _onDidRemovePopoutGroup . event ;
555555
556+ private readonly _onDidChangePopouts = new Emitter < void > ( ) ;
557+ /** Fires whenever a popout window opens or closes — i.e. the set of popout
558+ * documents changed. Used by accessibility services that mirror per-window
559+ * state (e.g. a live region in each popout). */
560+ readonly onDidChangePopouts : Event < void > = this . _onDidChangePopouts . event ;
561+
556562 private readonly _onDidOpenPopoutWindowFail = new Emitter < void > ( ) ;
557563 readonly onDidOpenPopoutWindowFail : Event < void > =
558564 this . _onDidOpenPopoutWindowFail . event ;
@@ -828,6 +834,26 @@ export class DockviewComponent
828834 return this . _shellManager ?. element ?? this . element ;
829835 }
830836
837+ /**
838+ * Does this dock own `node`, in any of its windows? True when the node is
839+ * inside the main shell, or inside one of this component's popout documents.
840+ * A popout window hosts only this component's content, so whole-document
841+ * membership is sufficient there; the main document may hold sibling docks,
842+ * so it must be a containment check. A same-document popout (the jsdom mock)
843+ * is already covered by the main check and contributes nothing.
844+ */
845+ ownsElement ( node : Node ) : boolean {
846+ if ( this . rootElement . contains ( node ) ) {
847+ return true ;
848+ }
849+ const mainDoc = this . rootElement . ownerDocument ;
850+ const doc = node . ownerDocument ;
851+ if ( ! doc || doc === mainDoc ) {
852+ return false ;
853+ }
854+ return this . getPopoutWindows ( ) . some ( ( win ) => win . document === doc ) ;
855+ }
856+
831857 /**
832858 * The next / previous group in gridview (spatial) order, wrapping round.
833859 * The keyboard accessibility module's focus navigation is built on this
@@ -1094,6 +1120,15 @@ export class DockviewComponent
10941120 this . _onDidPopoutGroupPositionChange ,
10951121 this . _onDidAddPopoutGroup ,
10961122 this . _onDidRemovePopoutGroup ,
1123+ this . _onDidChangePopouts ,
1124+ // Coalesce popout add/remove into a single "the popout set changed"
1125+ // signal for per-window accessibility state.
1126+ this . _onDidAddPopoutGroup . event ( ( ) =>
1127+ this . _onDidChangePopouts . fire ( )
1128+ ) ,
1129+ this . _onDidRemovePopoutGroup . event ( ( ) =>
1130+ this . _onDidChangePopouts . fire ( )
1131+ ) ,
10971132 this . _onDidOpenPopoutWindowFail ,
10981133 this . _onDidCreateTabGroup ,
10991134 this . _onDidDestroyTabGroup ,
@@ -1299,6 +1334,12 @@ export class DockviewComponent
12991334 ) ;
13001335 }
13011336
1337+ /** The live popout `Window` handles — one per open popout group. The
1338+ * narrow surface accessibility services need to mirror per-window state. */
1339+ getPopoutWindows ( ) : Window [ ] {
1340+ return this . getPopouts ( ) . map ( ( popout ) => popout . window ) ;
1341+ }
1342+
13021343 private _doAddPopoutGroup (
13031344 itemToPopout : DockviewPanel | DockviewGroupPanel ,
13041345 options ?: DockviewPopoutGroupOptionsInternal
0 commit comments