From b3ba25d35a0669d41afdbc282a4ff93114e42144 Mon Sep 17 00:00:00 2001 From: Gavinkaa Date: Fri, 29 May 2026 17:33:05 +0200 Subject: [PATCH 1/2] adding hide-title-bar-menu-toggle --- Sources/tart/Commands/Run.swift | 68 +++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/Sources/tart/Commands/Run.swift b/Sources/tart/Commands/Run.swift index 2e89590c..21009c9c 100644 --- a/Sources/tart/Commands/Run.swift +++ b/Sources/tart/Commands/Run.swift @@ -758,11 +758,23 @@ struct Run: AsyncParsableCommand { } } -struct MainApp: App { - static var suspendable: Bool = false - static var capturesSystemKeys: Bool = false +// Live title-bar toggle for the running VM window(s). Launch state is set via +// `.windowStyle` instead — AppKit at launch races SwiftUI's window creation. +func applyTitleBarStyle(hidden: Bool) { + for window in NSApplication.shared.windows { + window.titleVisibility = hidden ? .hidden : .visible + window.titlebarAppearsTransparent = hidden + if hidden { + window.styleMask.insert(.fullSizeContentView) + } else { + window.styleMask.remove(.fullSizeContentView) + } + } +} - @NSApplicationDelegateAdaptor private var appDelegate: AppDelegate +struct VMScene: Scene { + // Local preference (UserDefaults), not VMConfig — so it never travels with the image. + @AppStorage("hideTitleBar") private var hideTitleBar = false var body: some Scene { WindowGroup(vm!.name) { @@ -786,6 +798,12 @@ struct MainApp: App { idealHeight: CGFloat(vm!.config.display.height), maxHeight: .infinity ) + // Vary the parameter, not an if/else: a structural conditional rebuilds VMView, + // firing its .onDisappear (which SIGINTs the process). + .ignoresSafeArea(edges: hideTitleBar ? .all : []) + .onChange(of: hideTitleBar) { newValue in + applyTitleBarStyle(hidden: newValue) + } }.commands { // Remove some standard menu options CommandGroup(replacing: .help, addition: {}) @@ -813,11 +831,53 @@ struct MainApp: App { } } } + Divider() + Toggle("Hide Title Bar", isOn: Binding( + get: { hideTitleBar }, + set: { newValue in + hideTitleBar = newValue + // Force a flush: tart exits via SIGINT/exit(0), pre-empting the lazy write. + UserDefaults.standard.synchronize() + } + )) + .keyboardShortcut("t", modifiers: [.command, .control]) } } } } +struct HideTitleBarApp: App { + @NSApplicationDelegateAdaptor private var appDelegate: AppDelegate + + var body: some Scene { + VMScene() + .windowStyle(.hiddenTitleBar) + } +} + +struct ShowTitleBarApp: App { + @NSApplicationDelegateAdaptor private var appDelegate: AppDelegate + + var body: some Scene { + VMScene() + } +} + +// Picks the window style at launch from the remembered preference — declaratively, to +// avoid racing SwiftUI's window creation during boot. +enum MainApp { + static var suspendable: Bool = false + static var capturesSystemKeys: Bool = false + + static func main() { + if UserDefaults.standard.bool(forKey: "hideTitleBar") { + HideTitleBarApp.main() + } else { + ShowTitleBarApp.main() + } + } +} + class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { func applicationDidFinishLaunching(_ : Notification) { let nsApp = NSApplication.shared From d896a3ddf5397de443aae35db4779a0b1e66dff5 Mon Sep 17 00:00:00 2001 From: Gavinkaa Date: Fri, 29 May 2026 17:57:57 +0200 Subject: [PATCH 2/2] fixing lint --- Sources/tart/Commands/Run.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/tart/Commands/Run.swift b/Sources/tart/Commands/Run.swift index 21009c9c..9bce0a5c 100644 --- a/Sources/tart/Commands/Run.swift +++ b/Sources/tart/Commands/Run.swift @@ -840,7 +840,7 @@ struct VMScene: Scene { UserDefaults.standard.synchronize() } )) - .keyboardShortcut("t", modifiers: [.command, .control]) + .keyboardShortcut("t", modifiers: [.command, .control]) } } }