@@ -7,7 +7,7 @@ import { addDisposableListener } from '../Dom';
77import { IBufferService , IMouseStateService , ICoreService , ILogService , IOptionsService } from '../../common/services/Services' ;
88import { CoreMouseAction , CoreMouseButton , CoreMouseEventType , ICoreMouseEvent , IDisposable } from '../../common/Types' ;
99import { C0 } from '../../common/data/EscapeSequences' ;
10- import { DisposableStore , MutableDisposable , toDisposable } from '../../common/Lifecycle' ;
10+ import { DisposableStore , MutableDisposable } from '../../common/Lifecycle' ;
1111import { ICoreBrowserService , IMouseCoordsService , IMouseService , IMouseServiceTarget , IRenderService , ISelectionService } from './Services' ;
1212import { Gesture , EventType as GestureEventType , IGestureEvent } from '../scrollable/touch' ;
1313
@@ -21,6 +21,8 @@ interface IMouseBindContext {
2121 readonly target : IMouseServiceTarget ;
2222 readonly focus : ( ) => void ;
2323 readonly requestedEvents : RequestedMouseEvents ;
24+ readonly mouseupListener : MutableDisposable < IDisposable > ;
25+ readonly mousedragListener : MutableDisposable < IDisposable > ;
2426}
2527
2628export class MouseService implements IMouseService {
@@ -61,7 +63,11 @@ export class MouseService implements IMouseService {
6163 mousedrag : null ,
6264 mousemove : null
6365 } ;
64- const ctx : IMouseBindContext = { target, focus, requestedEvents } ;
66+ const mouseupListener = new MutableDisposable < IDisposable > ( ) ;
67+ const mousedragListener = new MutableDisposable < IDisposable > ( ) ;
68+ register ( mouseupListener ) ;
69+ register ( mousedragListener ) ;
70+ const ctx : IMouseBindContext = { target, focus, requestedEvents, mouseupListener, mousedragListener } ;
6571 const eventListeners : Record < 'mouseup' | 'wheel' | 'mousedrag' | 'mousemove' , EventListener > = {
6672 mouseup : ( ev : Event ) => this . _handleMouseUp ( ctx , ev as MouseEvent ) ,
6773 wheel : ( ev : Event ) => this . _handleWheel ( ctx , ev as WheelEvent ) ,
@@ -85,16 +91,6 @@ export class MouseService implements IMouseService {
8591 // force initial onProtocolChange so we dont miss early mouse requests
8692 this . _mouseStateService . activeProtocol = this . _mouseStateService . activeProtocol ;
8793
88- // Ensure document-level listeners are removed on dispose
89- register ( toDisposable ( ( ) => {
90- if ( requestedEvents . mouseup ) {
91- document . removeEventListener ( 'mouseup' , requestedEvents . mouseup ) ;
92- }
93- if ( requestedEvents . mousedrag ) {
94- document . removeEventListener ( 'mousemove' , requestedEvents . mousedrag ) ;
95- }
96- } ) ) ;
97-
9894 /**
9995 * "Always on" event listeners.
10096 */
@@ -199,12 +195,8 @@ export class MouseService implements IMouseService {
199195 this . _sendEvent ( ctx , ev ) ;
200196 if ( ! ev . buttons ) {
201197 // if no other button is held remove global handlers
202- if ( ctx . requestedEvents . mouseup ) {
203- ctx . target . document . removeEventListener ( 'mouseup' , ctx . requestedEvents . mouseup ) ;
204- }
205- if ( ctx . requestedEvents . mousedrag ) {
206- ctx . target . document . removeEventListener ( 'mousemove' , ctx . requestedEvents . mousedrag ) ;
207- }
198+ ctx . mouseupListener . clear ( ) ;
199+ ctx . mousedragListener . clear ( ) ;
208200 }
209201 }
210202
@@ -246,11 +238,14 @@ export class MouseService implements IMouseService {
246238 // of the terminal element.
247239 // Note: Other emulators also do this for 'mousedown' while a button
248240 // is held, we currently limit 'mousedown' to the terminal only.
241+ // Use the element's current document in case it moved to another window after open.
242+ const { element, document : targetDocument } = ctx . target ;
243+ const listenerDocument = element . ownerDocument ?? targetDocument ;
249244 if ( ctx . requestedEvents . mouseup ) {
250- ctx . target . document . addEventListener ( 'mouseup' , ctx . requestedEvents . mouseup ) ;
245+ ctx . mouseupListener . value = addDisposableListener ( listenerDocument , 'mouseup' , ctx . requestedEvents . mouseup ) ;
251246 }
252247 if ( ctx . requestedEvents . mousedrag ) {
253- ctx . target . document . addEventListener ( 'mousemove' , ctx . requestedEvents . mousedrag ) ;
248+ ctx . mousedragListener . value = addDisposableListener ( listenerDocument , 'mousemove' , ctx . requestedEvents . mousedrag ) ;
254249 }
255250 }
256251
@@ -398,7 +393,7 @@ export class MouseService implements IMouseService {
398393 }
399394
400395 private _handleProtocolChange ( ctx : IMouseBindContext , eventListeners : Record < 'mouseup' | 'wheel' | 'mousedrag' | 'mousemove' , EventListener > , events : CoreMouseEventType ) : void {
401- const { element, document } = ctx . target ;
396+ const { element } = ctx . target ;
402397 const { requestedEvents } = ctx ;
403398 // apply global changes on events
404399 if ( events ) {
@@ -433,18 +428,14 @@ export class MouseService implements IMouseService {
433428 }
434429
435430 if ( ! ( events & CoreMouseEventType . UP ) ) {
436- if ( requestedEvents . mouseup ) {
437- document . removeEventListener ( 'mouseup' , requestedEvents . mouseup ) ;
438- }
431+ ctx . mouseupListener . clear ( ) ;
439432 requestedEvents . mouseup = null ;
440433 } else {
441434 requestedEvents . mouseup ??= eventListeners . mouseup ;
442435 }
443436
444437 if ( ! ( events & CoreMouseEventType . DRAG ) ) {
445- if ( requestedEvents . mousedrag ) {
446- document . removeEventListener ( 'mousemove' , requestedEvents . mousedrag ) ;
447- }
438+ ctx . mousedragListener . clear ( ) ;
448439 requestedEvents . mousedrag = null ;
449440 } else {
450441 requestedEvents . mousedrag ??= eventListeners . mousedrag ;
0 commit comments