@@ -21,6 +21,7 @@ import { localize } from 'vs/nls';
2121import { Severity } from 'vs/platform/notification/common/notification' ;
2222import { ScrollbarVisibility } from 'vs/base/common/scrollable' ;
2323import { ILifecycleService , LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle' ;
24+ import { IWindowService } from 'vs/platform/windows/common/windows' ;
2425
2526interface INotificationToast {
2627 item : INotificationViewItem ;
@@ -52,6 +53,7 @@ export class NotificationsToasts extends Themable {
5253
5354 private notificationsToastsContainer : HTMLElement ;
5455 private workbenchDimensions : Dimension ;
56+ private windowHasFocus : boolean ;
5557 private isNotificationsCenterVisible : boolean ;
5658 private mapNotificationToToast : Map < INotificationViewItem , INotificationToast > ;
5759 private notificationsToastsVisibleContextKey : IContextKey < boolean > ;
@@ -64,13 +66,16 @@ export class NotificationsToasts extends Themable {
6466 @IThemeService themeService : IThemeService ,
6567 @IEditorGroupsService private editorGroupService : IEditorGroupsService ,
6668 @IContextKeyService contextKeyService : IContextKeyService ,
67- @ILifecycleService private lifecycleService : ILifecycleService
69+ @ILifecycleService private lifecycleService : ILifecycleService ,
70+ @IWindowService private windowService : IWindowService
6871 ) {
6972 super ( themeService ) ;
7073
7174 this . mapNotificationToToast = new Map < INotificationViewItem , INotificationToast > ( ) ;
7275 this . notificationsToastsVisibleContextKey = NotificationsToastsVisibleContext . bindTo ( contextKeyService ) ;
7376
77+ this . windowService . isFocused ( ) . then ( isFocused => this . windowHasFocus = isFocused ) ;
78+
7479 this . registerListeners ( ) ;
7580 }
7681
@@ -85,6 +90,9 @@ export class NotificationsToasts extends Themable {
8590 // Update toasts on notification changes
8691 this . _register ( this . model . onDidNotificationChange ( e => this . onDidNotificationChange ( e ) ) ) ;
8792 } ) ;
93+
94+ // Track window focus
95+ this . windowService . onDidChangeFocus ( hasFocus => this . windowHasFocus = hasFocus ) ;
8896 }
8997
9098 private onDidNotificationChange ( e : INotificationChangeEvent ) : void {
@@ -177,31 +185,8 @@ export class NotificationsToasts extends Themable {
177185 this . removeToast ( item ) ;
178186 } ) ;
179187
180- // Automatically hide collapsed notifications
181- if ( ! item . expanded ) {
182-
183- // Track mouse over item
184- let isMouseOverToast = false ;
185- itemDisposeables . push ( addDisposableListener ( notificationToastContainer , EventType . MOUSE_OVER , ( ) => isMouseOverToast = true ) ) ;
186- itemDisposeables . push ( addDisposableListener ( notificationToastContainer , EventType . MOUSE_OUT , ( ) => isMouseOverToast = false ) ) ;
187-
188- // Install Timers
189- let timeoutHandle : any ;
190- const hideAfterTimeout = ( ) => {
191- timeoutHandle = setTimeout ( ( ) => {
192- const showsProgress = item . hasProgress ( ) && ! item . progress . state . done ;
193- if ( ! notificationList . hasFocus ( ) && ! item . expanded && ! isMouseOverToast && ! showsProgress ) {
194- this . removeToast ( item ) ;
195- } else {
196- hideAfterTimeout ( ) ; // push out disposal if item has focus or is expanded
197- }
198- } , NotificationsToasts . PURGE_TIMEOUT [ item . severity ] ) ;
199- } ;
200-
201- hideAfterTimeout ( ) ;
202-
203- itemDisposeables . push ( toDisposable ( ( ) => clearTimeout ( timeoutHandle ) ) ) ;
204- }
188+ // Automatically purge non-sticky notifications
189+ this . purgeNotification ( item , notificationToastContainer , notificationList , itemDisposeables ) ;
205190
206191 // Theming
207192 this . updateStyles ( ) ;
@@ -217,6 +202,35 @@ export class NotificationsToasts extends Themable {
217202 } ) ) ;
218203 }
219204
205+ private purgeNotification ( item : INotificationViewItem , notificationToastContainer : HTMLElement , notificationList : NotificationsList , disposables : IDisposable [ ] ) : void {
206+
207+ // Track mouse over item
208+ let isMouseOverToast = false ;
209+ disposables . push ( addDisposableListener ( notificationToastContainer , EventType . MOUSE_OVER , ( ) => isMouseOverToast = true ) ) ;
210+ disposables . push ( addDisposableListener ( notificationToastContainer , EventType . MOUSE_OUT , ( ) => isMouseOverToast = false ) ) ;
211+
212+ // Install Timers
213+ let timeoutHandle : any ;
214+ const hideAfterTimeout = ( ) => {
215+ timeoutHandle = setTimeout ( ( ) => {
216+ if (
217+ item . sticky || // never hide sticky notifications
218+ notificationList . hasFocus ( ) || // never hide notifications with focus
219+ isMouseOverToast || // never hide notifications under mouse
220+ ! this . windowHasFocus // never hide when window has no focus
221+ ) {
222+ hideAfterTimeout ( ) ;
223+ } else {
224+ this . removeToast ( item ) ;
225+ }
226+ } , NotificationsToasts . PURGE_TIMEOUT [ item . severity ] ) ;
227+ } ;
228+
229+ hideAfterTimeout ( ) ;
230+
231+ disposables . push ( toDisposable ( ( ) => clearTimeout ( timeoutHandle ) ) ) ;
232+ }
233+
220234 private removeToast ( item : INotificationViewItem ) : void {
221235 const notificationToast = this . mapNotificationToToast . get ( item ) ;
222236 let focusGroup = false ;
0 commit comments