diff --git a/docs/notes-3.7.txt b/docs/notes-3.7.txt index d5bdd598d7..29f9cdecb0 100644 --- a/docs/notes-3.7.txt +++ b/docs/notes-3.7.txt @@ -107,6 +107,11 @@ New Features in Terminal Sessions: Settings > Profiles > Text. Tabs, Windows, and UI: +- Closing a pinned tab now requires + confirmation, whether via the close + button, middle-click, ⌘W, or quitting + the app. The dialog identifies the tab + as pinned so the prompt is clear. - The control-sequence-controlled progress indicator is now shown in the tab bar. - An active pane border can be displayed to diff --git a/sources/AppShutdown/iTermPromptOnCloseReason.h b/sources/AppShutdown/iTermPromptOnCloseReason.h index 5646589a5b..38673cf71a 100644 --- a/sources/AppShutdown/iTermPromptOnCloseReason.h +++ b/sources/AppShutdown/iTermPromptOnCloseReason.h @@ -22,6 +22,7 @@ + (instancetype)closingMultipleSessionsPreferenceEnabled; + (instancetype)tmuxClientsAlwaysPromptBecauseJobsAreNotExposed; + (instancetype)sessionIsLocked; ++ (instancetype)tabIsPinned; - (void)addReason:(iTermPromptOnCloseReason *)reason; diff --git a/sources/AppShutdown/iTermPromptOnCloseReason.m b/sources/AppShutdown/iTermPromptOnCloseReason.m index 54b042029e..f731bf89b4 100644 --- a/sources/AppShutdown/iTermPromptOnCloseReason.m +++ b/sources/AppShutdown/iTermPromptOnCloseReason.m @@ -238,6 +238,10 @@ + (instancetype)sessionIsLocked { return [[[iTermPromptOnCloseMessageReason alloc] initWithMessage:@"This pane is locked." priority:75] autorelease]; } ++ (instancetype)tabIsPinned { + return [[[iTermPromptOnCloseMessageReason alloc] initWithMessage:@"A pinned tab is open." priority:70] autorelease]; +} + - (BOOL)hasReason { return YES; } diff --git a/sources/TerminalView/PseudoTerminal.m b/sources/TerminalView/PseudoTerminal.m index d311103262..ff29804fd2 100644 --- a/sources/TerminalView/PseudoTerminal.m +++ b/sources/TerminalView/PseudoTerminal.m @@ -1941,14 +1941,21 @@ - (BOOL)confirmCloseTab:(PTYTab *)aTab suppressConfirmation:(BOOL)suppressConfir const BOOL anyIsLocked = [[aTab sessions] anyWithBlock:^BOOL(PTYSession *anObject) { return anObject.locked; }]; + NSString *const pinnedPrefix = aTab.isPinned ? @"pinned " : @""; if (numClosing == 1) { + NSString *const identifier = anyIsLocked + ? [NSString stringWithFormat:@"This %@tab (with a locked session)", pinnedPrefix] + : [NSString stringWithFormat:@"This %@tab", pinnedPrefix]; okToClose = [self confirmCloseForSessions:[aTab sessions] - identifier:anyIsLocked ? @"This tab (with a locked session)" : @"This tab" + identifier:identifier genericName:[NSString stringWithFormat:@"tab #%d", [aTab tabNumber]]]; } else { + NSString *const identifier = anyIsLocked + ? [NSString stringWithFormat:@"This %@multi-pane tab (with locked sessions)", pinnedPrefix] + : [NSString stringWithFormat:@"This %@multi-pane tab", pinnedPrefix]; okToClose = [self confirmCloseForSessions:[aTab sessions] - identifier:anyIsLocked ? @"This multi-pane tab (with locked sessions)" : @"This multi-pane tab" + identifier:identifier genericName:[NSString stringWithFormat:@"tab #%d", [aTab tabNumber]]]; } @@ -4175,6 +4182,12 @@ - (iTermPromptOnCloseReason *)promptOnCloseReason { for (PTYSession *aSession in [self allSessions]) { [reason addReason:[aSession promptOnCloseReason]]; } + for (PTYTab *tab in self.tabs) { + if (tab.isPinned) { + [reason addReason:[iTermPromptOnCloseReason tabIsPinned]]; + break; + } + } return reason; }