Control window behaviors of SwiftUI Scenes without doing weird tricks
SwiftUI-WindowManagement
The WindowManagement package allows you to control window behaviors of SwiftUI Scenes without doing weird tricks. Views can also access the NSWindow through the Environment.
Notice
This package uses and modifies some internals of SwiftUI. As SwiftUI changes frequently, implementations might break.
Note: DocumentGroup is not supported (yet)
Compatibility
- macOS 12.0 (Untested, but should work)
- macOS 13.0+
Available Scene modifiers
register
This modifier enables the modification of the underlying NSWindow
for this scene.
It should always be called before any of the other modifiers.
The identifier must be the same as the one set in the Scene initializer.
For the Settings
Scene, use registerSettingsWindow
.
func register(_ identifier: String)
func registerSettingsWindow()
movableByBackground
Indicates whether the window can be moved by clicking and dragging its background.
func movableByBackground(_ value: Bool)
movable
Indicates whether the view can be moved.
func movable(_ value: Bool)
styleMask
Apply a certain stylemask to the window.
Note that NSWindow.StyleMask.titled
is always included, otherwise SwiftUI will crash.
func styleMask(_ styleMask: NSWindow.StyleMask)
windowButton
Indicated whether a window button should be enabled or not.
If disabled, the button will be greyed out but still visible.
The keyboard shortcut of the button won’t be active.
Use windowButton(_:hidden:)
to hide a window button.
func windowButton(_ button: NSWindow.ButtonType, enabled: Bool)
Indicated whether a window button should be hidden or not.
A hidden button can still be triggered with it’s keyboard shortcut, e.g. Cmd+w for closing a window.
Use windowButton(_:hidden:)
to disable a window button.
func windowButton(_ button: NSWindow.ButtonType, hidden: Bool)
collectionBehavior
Apply a certain collectionBehavior to the window.
func collectionBehavior(_ behavior: NSWindow.CollectionBehavior)
tabbingMode
Set the tabbingMode for the window. If set to preferred, new windows will be opened as tabs.
func tabbingMode(_ mode: NSWindow.TabbingMode)
backgroundColor
Sets the background color of the window.
func backgroundColor(_ color: NSColor)
titlebarAppearsTransparent
Makes the titlebar transparent.
func titlebarAppearsTransparent(_ value: Bool)
disableRestoreOnLaunch
This will stop windows from relaunching if they were open in the last active app state.
Note: While this should work fine, I can’t guarantee it.
func disableRestoreOnLaunch()
Available View modifiers
Inject the current window into the environment.
func injectWindow(_ identifier: String)
Inject the settings window into the environment.
func injectSettingsWindow()
Get the NSWindow from a View.
@Environment(\.window) var window
Example
The following code shows the implementation of the window shown above.
import SwiftUI
import WindowManagement
@main
struct MyApp: App {
var body: some Scene {
WindowGroup(id: "MyWindow") {
ContentView()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.regularMaterial)
.injectWindow("MyWindow")
}
.register("MyWindow")
.titlebarAppearsTransparent(true)
.windowToolbarStyle(.unifiedCompact(showsTitle: false))
.movableByBackground(true)
.backgroundColor(.systemGray.withAlphaComponent(0.001)) // Don't use .clear, causes glitches.
.styleMask([.closable, .fullSizeContentView, .resizable])
.windowButton(.miniaturizeButton, hidden: true)
.windowButton(.zoomButton, hidden: true)
}
}
struct ContentView: View {
@Environment(\.window) var window
var body: some View {
Text("This windows identifier is \(window.identifier?.rawValue ?? "")")
Button("Hide this window") {
window.orderOut(nil)
}
}
}