mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Merge pull request #2552 from ghostty-org/push-ryrokukruoxr
macos: setup colorspace in base terminal controller
This commit is contained in:
@ -496,11 +496,6 @@ class AppDelegate: NSObject,
|
||||
// AppKit mutex on the appearance.
|
||||
DispatchQueue.main.async { self.syncAppearance() }
|
||||
|
||||
// Update all of our windows
|
||||
terminalManager.windows.forEach { window in
|
||||
window.controller.configDidReload()
|
||||
}
|
||||
|
||||
// If we have configuration errors, we need to show them.
|
||||
let c = ConfigurationErrorsController.sharedInstance
|
||||
c.errors = state.config.errors
|
||||
|
@ -33,11 +33,6 @@ class QuickTerminalController: BaseTerminalController {
|
||||
selector: #selector(onToggleFullscreen),
|
||||
name: Ghostty.Notification.ghosttyToggleFullscreen,
|
||||
object: nil)
|
||||
center.addObserver(
|
||||
self,
|
||||
selector: #selector(ghosttyDidReloadConfig),
|
||||
name: Ghostty.Notification.ghosttyDidReloadConfig,
|
||||
object: nil)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@ -53,6 +48,8 @@ class QuickTerminalController: BaseTerminalController {
|
||||
// MARK: NSWindowController
|
||||
|
||||
override func windowDidLoad() {
|
||||
super.windowDidLoad()
|
||||
|
||||
guard let window = self.window else { return }
|
||||
|
||||
// The controller is the window delegate so we can detect events such as
|
||||
@ -63,9 +60,6 @@ class QuickTerminalController: BaseTerminalController {
|
||||
// make this restorable, but it isn't currently implemented.
|
||||
window.isRestorable = false
|
||||
|
||||
// Setup our configured appearance that we support.
|
||||
syncAppearance()
|
||||
|
||||
// Setup our initial size based on our configured position
|
||||
position.setLoaded(window)
|
||||
|
||||
@ -297,35 +291,6 @@ class QuickTerminalController: BaseTerminalController {
|
||||
})
|
||||
}
|
||||
|
||||
private func syncAppearance() {
|
||||
guard let window else { return }
|
||||
|
||||
// If our window is not visible, then delay this. This is possible specifically
|
||||
// during state restoration but probably in other scenarios as well. To delay,
|
||||
// we just loop directly on the dispatch queue. We have to delay because some
|
||||
// APIs such as window blur have no effect unless the window is visible.
|
||||
guard window.isVisible else {
|
||||
// Weak window so that if the window changes or is destroyed we aren't holding a ref
|
||||
DispatchQueue.main.async { [weak self] in self?.syncAppearance() }
|
||||
return
|
||||
}
|
||||
|
||||
// If we have window transparency then set it transparent. Otherwise set it opaque.
|
||||
if (ghostty.config.backgroundOpacity < 1) {
|
||||
window.isOpaque = false
|
||||
|
||||
// This is weird, but we don't use ".clear" because this creates a look that
|
||||
// matches Terminal.app much more closer. This lets users transition from
|
||||
// Terminal.app more easily.
|
||||
window.backgroundColor = .white.withAlphaComponent(0.001)
|
||||
|
||||
ghostty_set_window_background_blur(ghostty.app, Unmanaged.passUnretained(window).toOpaque())
|
||||
} else {
|
||||
window.isOpaque = true
|
||||
window.backgroundColor = .windowBackgroundColor
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: First Responder
|
||||
|
||||
@IBAction override func closeWindow(_ sender: Any) {
|
||||
@ -357,10 +322,6 @@ class QuickTerminalController: BaseTerminalController {
|
||||
// We ignore the requested mode and always use non-native for the quick terminal
|
||||
toggleFullscreen(mode: .nonNative)
|
||||
}
|
||||
|
||||
@objc private func ghosttyDidReloadConfig(notification: SwiftUI.Notification) {
|
||||
syncAppearance()
|
||||
}
|
||||
}
|
||||
|
||||
extension Notification.Name {
|
||||
|
@ -93,6 +93,11 @@ class BaseTerminalController: NSWindowController,
|
||||
selector: #selector(didChangeScreenParametersNotification),
|
||||
name: NSApplication.didChangeScreenParametersNotification,
|
||||
object: nil)
|
||||
center.addObserver(
|
||||
self,
|
||||
selector: #selector(ghosttyDidReloadConfigNotification),
|
||||
name: Ghostty.Notification.ghosttyDidReloadConfig,
|
||||
object: nil)
|
||||
|
||||
// Listen for local events that we need to know of outside of
|
||||
// single surface handlers.
|
||||
@ -123,7 +128,7 @@ class BaseTerminalController: NSWindowController,
|
||||
|
||||
/// Update all surfaces with the focus state. This ensures that libghostty has an accurate view about
|
||||
/// what surface is focused. This must be called whenever a surface OR window changes focus.
|
||||
func syncFocusToSurfaceTree() {
|
||||
private func syncFocusToSurfaceTree() {
|
||||
guard let tree = self.surfaceTree else { return }
|
||||
|
||||
for leaf in tree {
|
||||
@ -136,6 +141,48 @@ class BaseTerminalController: NSWindowController,
|
||||
}
|
||||
}
|
||||
|
||||
// Call this whenever we want to setup our appearance parameters based on
|
||||
// configuration changes.
|
||||
private func syncAppearance() {
|
||||
guard let window else { return }
|
||||
|
||||
// If our window is not visible, then delay this. This is possible specifically
|
||||
// during state restoration but probably in other scenarios as well. To delay,
|
||||
// we just loop directly on the dispatch queue. We have to delay because some
|
||||
// APIs such as window blur have no effect unless the window is visible.
|
||||
guard window.isVisible else {
|
||||
// Weak window so that if the window changes or is destroyed we aren't holding a ref
|
||||
DispatchQueue.main.async { [weak self] in self?.syncAppearance() }
|
||||
return
|
||||
}
|
||||
|
||||
// If we have window transparency then set it transparent. Otherwise set it opaque.
|
||||
if (ghostty.config.backgroundOpacity < 1) {
|
||||
window.isOpaque = false
|
||||
|
||||
// This is weird, but we don't use ".clear" because this creates a look that
|
||||
// matches Terminal.app much more closer. This lets users transition from
|
||||
// Terminal.app more easily.
|
||||
window.backgroundColor = .white.withAlphaComponent(0.001)
|
||||
|
||||
ghostty_set_window_background_blur(ghostty.app, Unmanaged.passUnretained(window).toOpaque())
|
||||
} else {
|
||||
window.isOpaque = true
|
||||
window.backgroundColor = .windowBackgroundColor
|
||||
}
|
||||
|
||||
// Terminals typically operate in sRGB color space and macOS defaults
|
||||
// to "native" which is typically P3. There is a lot more resources
|
||||
// covered in this GitHub issue: https://github.com/mitchellh/ghostty/pull/376
|
||||
// Ghostty defaults to sRGB but this can be overridden.
|
||||
switch (ghostty.config.windowColorspace) {
|
||||
case .displayP3:
|
||||
window.colorSpace = .displayP3
|
||||
case .srgb:
|
||||
window.colorSpace = .sRGB
|
||||
}
|
||||
}
|
||||
|
||||
// Call this whenever the frame changes
|
||||
private func windowFrameDidChange() {
|
||||
// We need to update our saved frame information in case of monitor
|
||||
@ -145,6 +192,14 @@ class BaseTerminalController: NSWindowController,
|
||||
savedFrame = .init(window: window.frame, screen: screen.visibleFrame)
|
||||
}
|
||||
|
||||
// MARK: Overridable Callbacks
|
||||
|
||||
/// Called whenever Ghostty reloads the configuration. Callers should call super.
|
||||
open func ghosttyDidReloadConfig() {
|
||||
// Whenever the config changes we setup our appearance.
|
||||
syncAppearance()
|
||||
}
|
||||
|
||||
// MARK: Notifications
|
||||
|
||||
@objc private func didChangeScreenParametersNotification(_ notification: Notification) {
|
||||
@ -191,6 +246,10 @@ class BaseTerminalController: NSWindowController,
|
||||
window.setFrame(newFrame, display: true)
|
||||
}
|
||||
|
||||
@objc private func ghosttyDidReloadConfigNotification(notification: SwiftUI.Notification) {
|
||||
ghosttyDidReloadConfig()
|
||||
}
|
||||
|
||||
// MARK: Local Events
|
||||
|
||||
private func localEventHandler(_ event: NSEvent) -> NSEvent? {
|
||||
@ -381,7 +440,16 @@ class BaseTerminalController: NSWindowController,
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - NSWindowDelegate
|
||||
// MARK: NSWindowController
|
||||
|
||||
override func windowDidLoad() {
|
||||
super.windowDidLoad()
|
||||
|
||||
// Setup our configured appearance that we support.
|
||||
syncAppearance()
|
||||
}
|
||||
|
||||
// MARK: NSWindowDelegate
|
||||
|
||||
// This is called when performClose is called on a window (NOT when close()
|
||||
// is called directly). performClose is called primarily when UI elements such
|
||||
|
@ -78,14 +78,16 @@ class TerminalController: BaseTerminalController {
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Methods
|
||||
override func ghosttyDidReloadConfig() {
|
||||
super.ghosttyDidReloadConfig()
|
||||
|
||||
func configDidReload() {
|
||||
guard let window = window as? TerminalWindow else { return }
|
||||
window.focusFollowsMouse = ghostty.config.focusFollowsMouse
|
||||
syncAppearance()
|
||||
}
|
||||
|
||||
//MARK: - Methods
|
||||
|
||||
/// Update the accessory view of each tab according to the keyboard
|
||||
/// shortcut that activates it (if any). This is called when the key window
|
||||
/// changes, when a window is closed, and when tabs are reordered
|
||||
@ -164,21 +166,6 @@ class TerminalController: BaseTerminalController {
|
||||
window.titlebarFont = nil
|
||||
}
|
||||
|
||||
// If we have window transparency then set it transparent. Otherwise set it opaque.
|
||||
if (ghostty.config.backgroundOpacity < 1) {
|
||||
window.isOpaque = false
|
||||
|
||||
// This is weird, but we don't use ".clear" because this creates a look that
|
||||
// matches Terminal.app much more closer. This lets users transition from
|
||||
// Terminal.app more easily.
|
||||
window.backgroundColor = .white.withAlphaComponent(0.001)
|
||||
|
||||
ghostty_set_window_background_blur(ghostty.app, Unmanaged.passUnretained(window).toOpaque())
|
||||
} else {
|
||||
window.isOpaque = true
|
||||
window.backgroundColor = .windowBackgroundColor
|
||||
}
|
||||
|
||||
window.hasShadow = ghostty.config.macosWindowShadow
|
||||
|
||||
guard window.hasStyledTabs else { return }
|
||||
@ -208,6 +195,8 @@ class TerminalController: BaseTerminalController {
|
||||
}
|
||||
|
||||
override func windowDidLoad() {
|
||||
super.windowDidLoad()
|
||||
|
||||
guard let window = window as? TerminalWindow else { return }
|
||||
|
||||
// Setting all three of these is required for restoration to work.
|
||||
@ -220,19 +209,6 @@ class TerminalController: BaseTerminalController {
|
||||
// If window decorations are disabled, remove our title
|
||||
if (!ghostty.config.windowDecorations) { window.styleMask.remove(.titled) }
|
||||
|
||||
// Terminals typically operate in sRGB color space and macOS defaults
|
||||
// to "native" which is typically P3. There is a lot more resources
|
||||
// covered in this GitHub issue: https://github.com/mitchellh/ghostty/pull/376
|
||||
// Ghostty defaults to sRGB but this can be overridden.
|
||||
switch (ghostty.config.windowColorspace) {
|
||||
case "display-p3":
|
||||
window.colorSpace = .displayP3
|
||||
case "srgb":
|
||||
fallthrough
|
||||
default:
|
||||
window.colorSpace = .sRGB
|
||||
}
|
||||
|
||||
// If we have only a single surface (no splits) and that surface requested
|
||||
// an initial size then we set it here now.
|
||||
if case let .leaf(leaf) = surfaceTree {
|
||||
|
@ -128,13 +128,14 @@ extension Ghostty {
|
||||
return v
|
||||
}
|
||||
|
||||
var windowColorspace: String {
|
||||
guard let config = self.config else { return "" }
|
||||
var windowColorspace: WindowColorspace {
|
||||
guard let config = self.config else { return .srgb }
|
||||
var v: UnsafePointer<Int8>? = nil
|
||||
let key = "window-colorspace"
|
||||
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return "" }
|
||||
guard let ptr = v else { return "" }
|
||||
return String(cString: ptr)
|
||||
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return .srgb }
|
||||
guard let ptr = v else { return .srgb }
|
||||
let str = String(cString: ptr)
|
||||
return WindowColorspace(rawValue: str) ?? .srgb
|
||||
}
|
||||
|
||||
var windowSaveState: String {
|
||||
@ -474,4 +475,9 @@ extension Ghostty.Config {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum WindowColorspace : String {
|
||||
case srgb
|
||||
case displayP3 = "display-p3"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user