66import { ICoreBrowserService , IRenderService , IThemeService } from 'browser/services/Services' ;
77import { ViewportConstants } from 'browser/shared/Constants' ;
88import { Disposable , toDisposable } from 'common/Lifecycle' ;
9- import { IBufferService , IMouseStateService , IOptionsService } from 'common/services/Services' ;
9+ import { IBufferService , ICoreService , IMouseStateService , IOptionsService } from 'common/services/Services' ;
1010import { CoreMouseEventType } from 'common/Types' ;
1111import { scheduleAtNextAnimationFrame } from 'browser/Dom' ;
1212import { SmoothScrollableElement } from 'browser/scrollable/scrollableElement' ;
@@ -27,12 +27,14 @@ export class Viewport extends Disposable {
2727 private _isSyncing : boolean = false ;
2828 private _isHandlingScroll : boolean = false ;
2929 private _suppressOnScrollHandler : boolean = false ;
30+ private _needsSyncOnRender : boolean = false ;
3031
3132 constructor (
3233 element : HTMLElement ,
3334 screenElement : HTMLElement ,
3435 @IBufferService private readonly _bufferService : IBufferService ,
3536 @ICoreBrowserService coreBrowserService : ICoreBrowserService ,
37+ @ICoreService private readonly _coreService : ICoreService ,
3638 @IMouseStateService mouseStateService : IMouseStateService ,
3739 @IThemeService themeService : IThemeService ,
3840 @IOptionsService private readonly _optionsService : IOptionsService ,
@@ -104,6 +106,16 @@ export class Viewport extends Disposable {
104106 } ) ) ;
105107 this . _register ( this . _bufferService . onScroll ( ( ) => this . _sync ( ) ) ) ;
106108
109+ // Flush deferred viewport sync after a render completes (e.g. after ESU ends
110+ // synchronized output mode). This ensures DOM scroll position updates atomically
111+ // with the canvas render.
112+ this . _register ( this . _renderService . onRender ( ( ) => {
113+ if ( this . _needsSyncOnRender ) {
114+ this . _needsSyncOnRender = false ;
115+ this . _sync ( ) ;
116+ }
117+ } ) ) ;
118+
107119 this . _register ( this . _scrollableElement . onScroll ( e => this . _handleScroll ( e ) ) ) ;
108120
109121 }
@@ -161,6 +173,12 @@ export class Viewport extends Disposable {
161173 if ( ! this . _renderService || this . _isSyncing ) {
162174 return ;
163175 }
176+ // Defer DOM scroll updates during synchronized output to prevent visible
177+ // scroll position flickering while the canvas content is frozen.
178+ if ( this . _coreService . decPrivateModes . synchronizedOutput ) {
179+ this . _needsSyncOnRender = true ;
180+ return ;
181+ }
164182 this . _isSyncing = true ;
165183
166184 // Ignore any onScroll event that happens as a result of dimensions changing as this should
0 commit comments