22 September 2024
Hide macOS window controls using SwiftUI
For certain macOS applications, you might want to hide the macOS window controls, commonly called ‘traffic light buttons’. These are the close, minimize and maximize buttons that appear on the top-left of most macOS applications.
To solve this problem, we will do the following:
- Track when the application has opened and become the key window.
- Identify the window that will have it’s windows controls hidden.
- Hide the window controls
To track when the application has opened and become the key window, we can make use of SwiftUI’s View.onReceive()
function. It allow us to
add an action to perform when this view detects data emitted by a given publisher. A publisher is any object that implements the Publisher
protocol which imparts that object the power to transmit a sequence of values over time to some subscriber.
We can use the NotificationCenter.default.publisher
to emit a notification when a Window has become the key window and run some action.
@main
struct hide_window_controlsApp: App {
var body: some Scene {
WindowGroup("SwiftUI") {
ContentView().onReceive(NotificationCenter.default.publisher(for: NSWindow.didBecomeKeyNotification)) { _ in
}
}
}
}
The next step involves identifying which window within our app will have it’s window controls removed.
We can use NSApplication.shared.windows
to return a list of windows associated with our application and filter based on a given identifier. In our case, we filter
based on the title we provide our apps WindowGroup
or Window
and return the given window. If a window with that title does not exist for our app, we return an error instead.
func getWindowByTitle(title: String) -> NSWindow? {
guard let window = NSApplication.shared.windows.first(where: { $0.title == title }) else {
fatalError("Window with title '\(title)' not found.")
}
return window
}
Now that we can identify the target window by it’s title, we can remove the window controls.
For this, macOS allows us to modify an NSWindow
window controls using the NSWindow.standardWindowButton
API like such: window.standardWindowButton(NSWindow.ButtonType.closeButton)?.isHidden = true
.
To hide all the window controls for a specific window, we implement the following function:
func hideWindowControls(for window: NSWindow) {
window.standardWindowButton(NSWindow.ButtonType.closeButton)?.isHidden = true
window.standardWindowButton(NSWindow.ButtonType.miniaturizeButton)?.isHidden = true
window.standardWindowButton(NSWindow.ButtonType.zoomButton)?.isHidden = true
}
Now,we pass our action into our .onReceive
function to find the window by it’s title and hide the window controls for said window:
if let window = getWindowByTitle(title: "SwiftUI") {
hideWindowControls(for: window)
}
This will lead us to this complete solution:
import SwiftUI
func hideWindowControls(for window: NSWindow) {
window.standardWindowButton(NSWindow.ButtonType.closeButton)?.isHidden = true
window.standardWindowButton(NSWindow.ButtonType.miniaturizeButton)?.isHidden = true
window.standardWindowButton(NSWindow.ButtonType.zoomButton)?.isHidden = true
}
func getWindowByTitle(title: String) -> NSWindow? {
guard let window = NSApplication.shared.windows.first(where: { $0.title == title }) else {
fatalError("Window with title '\(title)' not found.")
}
return window
}
@main
struct hide_window_controlsApp: App {
var body: some Scene {
WindowGroup("SwiftUI") {
ContentView().onReceive(NotificationCenter.default.publisher(for: NSWindow.didBecomeKeyNotification)) { _ in
if let window = getWindowByTitle(title: "SwiftUI") {
hideWindowControls(for: window)
}
}
}
}
}
For updates about the blog and software development tips, follow me on X @0xFFA4.