diff --git a/src/10-Core/Wtq/Configuration/AutoStartMode.cs b/src/10-Core/Wtq/Configuration/AutoStartMode.cs
new file mode 100644
index 00000000..4c55fa06
--- /dev/null
+++ b/src/10-Core/Wtq/Configuration/AutoStartMode.cs
@@ -0,0 +1,25 @@
+namespace Wtq.Configuration;
+
+///
+/// How WTQ should start an app.
+///
+public enum AutoStartMode
+{
+ ///
+ /// Used to detect serialization issues.
+ ///
+ [DisplayFlags(IsVisible = false)] // Don't show this in the GUI, it's purely for internal use.
+ None = 0,
+
+ ///
+ /// Start app as soon as WTQ starts.
+ ///
+ [Display(Name = "On WTQ start")]
+ OnWtqStart,
+
+ ///
+ /// Start app on hotkey press, and it's not running yet.
+ ///
+ [Display(Name = "On hotkey press")]
+ OnHotkeyPress,
+}
\ No newline at end of file
diff --git a/src/10-Core/Wtq/Configuration/WtqAppOptions.Extensions.cs b/src/10-Core/Wtq/Configuration/WtqAppOptions.Extensions.cs
index d76d32c2..dcc1305a 100644
--- a/src/10-Core/Wtq/Configuration/WtqAppOptions.Extensions.cs
+++ b/src/10-Core/Wtq/Configuration/WtqAppOptions.Extensions.cs
@@ -52,6 +52,14 @@ public static AttachMode GetAttachMode(this WtqAppOptions app)
return OptionUtils.Cascade(o => o.AttachMode, app, app.Global);
}
+ ///
+ public static AutoStartMode GetAutoStartMode(this WtqAppOptions app)
+ {
+ Guard.Against.Null(app);
+
+ return OptionUtils.Cascade(o => o.AutoStartMode, app, app.Global);
+ }
+
///
public static HideOnFocusLost GetHideOnFocusLost(this WtqAppOptions app)
{
diff --git a/src/10-Core/Wtq/Configuration/WtqSharedOptions.cs b/src/10-Core/Wtq/Configuration/WtqSharedOptions.cs
index d448b316..64cc2c14 100644
--- a/src/10-Core/Wtq/Configuration/WtqSharedOptions.cs
+++ b/src/10-Core/Wtq/Configuration/WtqSharedOptions.cs
@@ -21,6 +21,14 @@ public abstract class WtqSharedOptions : IValidatableObject
[JsonPropertyOrder(2005)]
public AttachMode? AttachMode { get; set; }
+ ///
+ /// Automatically start app on WTQ start.
+ ///
+ [DefaultValue(Wc.AutoStartMode.OnWtqStart)]
+ [Display(GroupName = Gn.Process, Name = "Auto start mode")]
+ [JsonPropertyOrder(2006)]
+ public AutoStartMode? AutoStartMode { get; set; }
+
#endregion
#region 3000 - Behavior
diff --git a/src/10-Core/Wtq/Services/WtqAppRepo.cs b/src/10-Core/Wtq/Services/WtqAppRepo.cs
index d8a37859..4c2a1a40 100644
--- a/src/10-Core/Wtq/Services/WtqAppRepo.cs
+++ b/src/10-Core/Wtq/Services/WtqAppRepo.cs
@@ -32,9 +32,7 @@ public WtqAppRepo(
_ = Task.Run(async () =>
{
- // TODO: Make setting for "allowStartNew"? As in, allow starting apps on WTQ first start?
- // "StartApps": "OnWtqStart | OnHotkeyPress"
- await UpdateAppsAsync(allowStartNew: true).NoCtx();
+ await UpdateAppsAsync(allowStartNew: null).NoCtx();
});
// When WTQ stops, reset all tracked apps.
@@ -120,7 +118,7 @@ private WtqApp GetOrCreate(WtqAppOptions opts)
///
/// Updates the list of tracked apps (), to match the list of available option objects ().
///
- private async Task UpdateAppsAsync(bool allowStartNew)
+ private async Task UpdateAppsAsync(bool? allowStartNew)
{
// Make sure this method always runs non-concurrently.
using var l = await _updateLock.WaitAsync(new CancellationTokenSource(TimeSpan.FromSeconds(15)).Token);
@@ -134,7 +132,7 @@ private async Task UpdateAppsAsync(bool allowStartNew)
var app = GetOrCreate(opt);
// Update the app's local state, which may include starting a new process.
- await app.UpdateLocalAppStateAsync(allowStartNew).NoCtx();
+ await app.UpdateLocalAppStateAsync(allowStartNew ?? opt.GetAutoStartMode() == AutoStartMode.OnWtqStart).NoCtx();
}
// Remove app handles for dropped options.
diff --git a/src/10-Core/Wtq/Services/WtqWindowResolver.cs b/src/10-Core/Wtq/Services/WtqWindowResolver.cs
index 0ab9fe1c..bf3b0d7c 100644
--- a/src/10-Core/Wtq/Services/WtqWindowResolver.cs
+++ b/src/10-Core/Wtq/Services/WtqWindowResolver.cs
@@ -33,7 +33,7 @@ public sealed class WtqWindowResolver(
private async Task FindOrStartAsync(WtqAppOptions opts, bool allowStartNew)
{
- _log.LogInformation("Using find-or-start process attach mode for app with options {Options}, looking for process (allow start new: {AllowStartNew})", opts, allowStartNew);
+ _log.LogDebug("Using find-or-start process attach mode for app with options {Options}, looking for process (allow start new: {AllowStartNew})", opts, allowStartNew);
// Look for an existing window first.
var window1 = await _windowService.FindWindowAsync(opts, CancellationToken.None).NoCtx();