Skip to content

Commit 76089e0

Browse files
Use a --isolated flag instead of the setting
The setting is silently ignored by a dt that does not know it, which would leak one launch's environment into another. An unknown flag fails the launch instead, the caller decides per launch, and nothing has to be read from settings.json before the broker election.
1 parent f3c0527 commit 76089e0

16 files changed

Lines changed: 68 additions & 153 deletions

File tree

‎README.md‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,13 @@ settings file. On Windows, `WT_PARENT_WINDOW_HANDLE` embeds the window as a
8888
child of that HWND. `alwaysShowTabs: false` hides the tab row when only one
8989
tab is open.
9090

91-
`"compatibility.isolatedMode": true` (from Windows Terminal 1.22 and earlier)
92-
makes each launch its own process: it neither forwards to a running instance
93-
nor becomes the broker for later launches, so every window keeps its own
94-
environment, `WT_PARENT_WINDOW_HANDLE`, and settings directory. `-w` targeting
95-
of other windows is unavailable, and persisted layouts are neither restored
96-
nor saved.
91+
`dt --isolated` (or `Devolutions.Terminal.exe --isolated`) runs the launch in
92+
its own process: it neither forwards to a running instance nor becomes the
93+
broker for later launches, so every window keeps its own environment,
94+
`WT_PARENT_WINDOW_HANDLE`, and settings directory. `-w` targeting of other
95+
windows is unavailable, and persisted layouts are neither restored nor saved.
96+
It is the per-launch equivalent of Windows Terminal's
97+
`compatibility.isolatedMode` setting, which Windows Terminal 1.23 removed.
9798

9899
Set `"experimental.terminalEngine": "ghostty"` to use the pinned
99100
`libghostty-vt` engine globally. A profile can override it with `"builtin"` or

‎src/Devolutions.Terminal.App/Models/TerminalLayoutStateStore.cs‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@ preference is not null &&
1111
preference.Equals("persistedLayoutAndContent", StringComparison.OrdinalIgnoreCase));
1212

1313
// Matches Windows Terminal: an isolated process never restores or saves the shared window layouts.
14-
public static bool ShouldUsePersistedLayout(AppSettings settings)
15-
{
16-
ArgumentNullException.ThrowIfNull(settings);
17-
return !settings.IsolatedMode && IsPersistedLayoutPreference(settings.FirstWindowPreference);
18-
}
14+
public static bool ShouldUsePersistedLayout(string? firstWindowPreference, bool isolated) =>
15+
!isolated && IsPersistedLayoutPreference(firstWindowPreference);
1916

2017
public static WindowLayoutState? ReadWindowState(ApplicationStateStore store, int windowId)
2118
{

‎src/Devolutions.Terminal.App/Views/MainWindow.axaml.cs‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public partial class MainWindow :
7777
private readonly Func<GlobalSummonArgs, ValueTask<WindowActionResult>>? _summonRequested;
7878
private readonly Action<AppSettings>? _settingsChanged;
7979
private readonly ISystemMenuService _systemMenuService;
80+
private readonly bool _isolated;
8081
private readonly TaskCompletionSource<TerminalWindowActivationResult> _initialActivationCompletion =
8182
new(TaskCreationOptions.RunContinuationsAsynchronously);
8283
private readonly DispatcherTimer _notificationTimer;
@@ -102,10 +103,12 @@ public MainWindow(
102103
Action<string>? workspaceRequested = null,
103104
Func<GlobalSummonArgs, ValueTask<WindowActionResult>>? summonRequested = null,
104105
Action<AppSettings>? settingsChanged = null,
105-
ISystemMenuService? systemMenuService = null)
106+
ISystemMenuService? systemMenuService = null,
107+
bool isolated = false)
106108
{
107109
WindowId = windowId;
108110
WindowName = windowName;
111+
_isolated = isolated;
109112
_initialActivation = initialActivation;
110113
_newWindowRequested = newWindowRequested;
111114
_tabTearOffRequested = tabTearOffRequested;
@@ -3647,7 +3650,7 @@ private void PersistWorkspace(TerminalWindowLayoutDescriptor layout)
36473650
};
36483651

36493652
private bool UsesPersistedLayout =>
3650-
TerminalLayoutStateStore.ShouldUsePersistedLayout(_settings);
3653+
TerminalLayoutStateStore.ShouldUsePersistedLayout(_settings.FirstWindowPreference, _isolated);
36513654

36523655
private void TryPersistCurrentLayout(TerminalWindowLayoutDescriptor layout)
36533656
{

‎src/Devolutions.Terminal.Cli/CliContracts.cs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ public sealed record CliInvocation(
2424
CliLaunchMode LaunchMode,
2525
int? SavedLayout,
2626
IReadOnlyList<ActionAndArgs> Actions,
27-
CliSaveRequest? SaveRequest = null);
27+
CliSaveRequest? SaveRequest = null,
28+
bool Isolated = false);
2829

2930
public sealed record CliParseResult(
3031
int ExitCode,

‎src/Devolutions.Terminal.Cli/CliParser.cs‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ private static CliParseResult ParseCore(
118118
int? rows = null;
119119
int? savedLayout = null;
120120
var launchMode = CliLaunchMode.Default;
121+
var isolated = false;
121122
CliSaveRequest? save = null;
122123

123124
for (var segmentIndex = 0; segmentIndex < segments.Count; segmentIndex++)
@@ -135,7 +136,8 @@ private static CliParseResult ParseCore(
135136
ref columns,
136137
ref rows,
137138
ref savedLayout,
138-
ref launchMode);
139+
ref launchMode,
140+
ref isolated);
139141
}
140142

141143
var command = index < segment.Count && Commands.Contains(segment[index])
@@ -215,7 +217,8 @@ save is null &&
215217
launchMode,
216218
savedLayout,
217219
actions,
218-
save);
220+
save,
221+
isolated);
219222
return new(0, string.Empty, false, invocation);
220223
}
221224

@@ -228,7 +231,8 @@ private static void ParseRootOptions(
228231
ref int? columns,
229232
ref int? rows,
230233
ref int? savedLayout,
231-
ref CliLaunchMode launchMode)
234+
ref CliLaunchMode launchMode,
235+
ref bool isolated)
232236
{
233237
while (index < args.Count)
234238
{
@@ -269,6 +273,10 @@ private static void ParseRootOptions(
269273
launchMode |= CliLaunchMode.Focus;
270274
index++;
271275
break;
276+
case "--isolated":
277+
isolated = true;
278+
index++;
279+
break;
272280
default:
273281
if (option.StartsWith('-') &&
274282
option.Length > 2 &&
@@ -696,6 +704,7 @@ internal static class CommandLineSchema
696704
-M, --maximized Launch maximized
697705
-F, --fullscreen Launch fullscreen
698706
-f, --focus Hide the title bar
707+
--isolated Own process: never join or serve other launches
699708
700709
Commands:
701710
new-tab, nt split-pane, sp focus-tab, ft move-focus, mf
@@ -708,6 +717,7 @@ public static RootCommand Create()
708717
root.Options.Add(new Option<string>("--window") { Description = "Target window." });
709718
root.Options.Add(new Option<string>("--pos") { Description = "Window position." });
710719
root.Options.Add(new Option<string>("--size") { Description = "Terminal size." });
720+
root.Options.Add(new Option<bool>("--isolated") { Description = "Run in its own process." });
711721
foreach (var (name, alias) in new[]
712722
{
713723
("new-tab", "nt"),

‎src/Devolutions.Terminal.Cli/Program.cs‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Diagnostics;
22
using Devolutions.Terminal.Broker;
3-
using Devolutions.Terminal.Settings;
43

54
namespace Devolutions.Terminal.Cli;
65

@@ -18,8 +17,8 @@ public static async Task<int> Main(string[] args)
1817
}
1918

2019
var invocation = parsed.Invocation!;
21-
var response = SettingsService.IsIsolatedModeEnabled()
22-
? BrokerResponse.Unavailable("Isolated mode does not use the broker.")
20+
var response = invocation.Isolated
21+
? BrokerResponse.Unavailable("Isolated launches do not use the broker.")
2322
: await new BrokerClient().SendAsync(
2423
invocation.TargetWindow,
2524
CliInvocationSerializer.Serialize(invocation)).ConfigureAwait(false);

‎src/Devolutions.Terminal.Settings/Models.cs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ public sealed class AppSettings
131131
public bool AlwaysShowNotificationIcon { get; set; }
132132
public List<string> DisabledProfileSources { get; set; } = [];
133133
public bool AllowHeadless { get; set; }
134-
public bool IsolatedMode { get; set; }
135134
public bool EnableColorSelection { get; set; }
136135

137136
// Per-window settings.

‎src/Devolutions.Terminal.Settings/SettingsLoader.cs‎

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ public static class SettingsLoader
1919
{
2020
private const string OriginKey = "$terminalOrigin";
2121
private const string SourceKey = "$terminalSource";
22-
private const string IsolatedModeKey = "compatibility.isolatedMode";
2322

2423
private static readonly JsonDocumentOptions DocumentOptions = new()
2524
{
@@ -34,27 +33,6 @@ public static string ReadEmbeddedDefaults()
3433
public static string ReadEmbeddedUserDefaults()
3534
=> ReadEmbeddedResource("Devolutions.Terminal.Settings.userDefaults.json");
3635

37-
/// <summary>
38-
/// Reads only <c>compatibility.isolatedMode</c> from a user settings document, so startup can
39-
/// decide whether to use the broker before loading the full settings.
40-
/// </summary>
41-
public static bool ReadIsolatedMode(string? userJson)
42-
{
43-
if (string.IsNullOrWhiteSpace(userJson))
44-
{
45-
return false;
46-
}
47-
48-
try
49-
{
50-
return Bool(JsonNode.Parse(userJson, documentOptions: DocumentOptions) as JsonObject, IsolatedModeKey);
51-
}
52-
catch (JsonException)
53-
{
54-
return false;
55-
}
56-
}
57-
5836
private static string ReadEmbeddedResource(string name)
5937
{
6038
using var stream = typeof(SettingsLoader).Assembly.GetManifestResourceStream(name);
@@ -342,7 +320,6 @@ private static AppSettings Resolve(
342320
AlwaysShowNotificationIcon = Bool(root, "alwaysShowNotificationIcon"),
343321
DisabledProfileSources = StringList(root["disabledProfileSources"]),
344322
AllowHeadless = Bool(root, "compatibility.allowHeadless"),
345-
IsolatedMode = Bool(root, IsolatedModeKey),
346323
EnableColorSelection = Bool(root, "experimental.enableColorSelection"),
347324
DefaultProfile = String(root, "defaultProfile"),
348325
InitialCols = Int(root, "initialCols", 80, minimum: 1),
@@ -1158,7 +1135,6 @@ private static bool GuidsEqual(string? left, string? right) =>
11581135
["alwaysShowNotificationIcon"] = settings.AlwaysShowNotificationIcon,
11591136
["disabledProfileSources"] = StringArray(settings.DisabledProfileSources),
11601137
["compatibility.allowHeadless"] = settings.AllowHeadless,
1161-
[IsolatedModeKey] = settings.IsolatedMode,
11621138
["experimental.enableColorSelection"] = settings.EnableColorSelection,
11631139
["defaultProfile"] = settings.DefaultProfile,
11641140
["initialCols"] = settings.InitialCols,

‎src/Devolutions.Terminal.Settings/SettingsService.cs‎

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -149,22 +149,6 @@ public static void Save(AppSettings settings)
149149
public static AppSettings CreateDefault() =>
150150
SettingsLoader.Load(SettingsLoader.ReadEmbeddedDefaults());
151151

152-
public static bool IsIsolatedModeEnabled() => IsIsolatedModeEnabled(SettingsPath);
153-
154-
public static bool IsIsolatedModeEnabled(string settingsPath)
155-
{
156-
ArgumentException.ThrowIfNullOrWhiteSpace(settingsPath);
157-
try
158-
{
159-
return File.Exists(settingsPath) &&
160-
SettingsLoader.ReadIsolatedMode(File.ReadAllText(settingsPath, Encoding.UTF8));
161-
}
162-
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
163-
{
164-
return false;
165-
}
166-
}
167-
168152
public static ApplicationStateStore LoadApplicationState() =>
169153
new(Path.GetDirectoryName(Path.GetFullPath(StatePath))!);
170154

‎src/Devolutions.Terminal/App.axaml.cs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ public override void OnFrameworkInitializationCompleted()
3030
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
3131
{
3232
_desktop = desktop;
33-
_router = new TerminalWindowRouter(desktop, ConfigureWindow);
33+
_router = new TerminalWindowRouter(
34+
desktop,
35+
ConfigureWindow,
36+
isolated: InitialInvocation?.Isolated ?? false);
3437
BrokerHandler?.SetHandler(_router);
3538
if (OperatingSystem.IsMacOS())
3639
{

0 commit comments

Comments
 (0)