mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Fix notification handling from publishing while View is updating (#3177)
I was originally looking into this issue: https://github.com/ghostty-org/ghostty/issues/3109 When running the logic and triggering a config reload, Xcode warns us about updating publishable properties from within the notification callback functions: <img width="924" alt="Screenshot 2024-12-26 at 5 46 19 PM" src="https://github.com/user-attachments/assets/38000a09-ffad-4dda-9e2d-a37e5283ff89" /> I believe this is because `SurfaceView` is being used as both a bridged NSView (inside `Surface`) and also an `ObservableObject`, so it's possible for the notification callback to happen while a SwiftUI render loop is occurring. The notification delivery happens on whatever thread posted the message. The better solution long-term is likely to separate the `ObservableObject` logic into its own class to avoid mixing with the View logic. The solution here is to simply move the publishable mutation out of the current loop via `DispatchQueue.main.async`. I confirmed the warning goes away with this, and I didn't notice any odd behavior while reloading config changes.
This commit is contained in:
@ -361,17 +361,23 @@ extension Ghostty {
|
|||||||
@objc private func onUpdateRendererHealth(notification: SwiftUI.Notification) {
|
@objc private func onUpdateRendererHealth(notification: SwiftUI.Notification) {
|
||||||
guard let healthAny = notification.userInfo?["health"] else { return }
|
guard let healthAny = notification.userInfo?["health"] else { return }
|
||||||
guard let health = healthAny as? ghostty_action_renderer_health_e else { return }
|
guard let health = healthAny as? ghostty_action_renderer_health_e else { return }
|
||||||
healthy = health == GHOSTTY_RENDERER_HEALTH_OK
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.healthy = health == GHOSTTY_RENDERER_HEALTH_OK
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func ghosttyDidContinueKeySequence(notification: SwiftUI.Notification) {
|
@objc private func ghosttyDidContinueKeySequence(notification: SwiftUI.Notification) {
|
||||||
guard let keyAny = notification.userInfo?[Ghostty.Notification.KeySequenceKey] else { return }
|
guard let keyAny = notification.userInfo?[Ghostty.Notification.KeySequenceKey] else { return }
|
||||||
guard let key = keyAny as? Ghostty.KeyEquivalent else { return }
|
guard let key = keyAny as? Ghostty.KeyEquivalent else { return }
|
||||||
keySequence.append(key)
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.keySequence.append(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func ghosttyDidEndKeySequence(notification: SwiftUI.Notification) {
|
@objc private func ghosttyDidEndKeySequence(notification: SwiftUI.Notification) {
|
||||||
keySequence = []
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.keySequence = []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func ghosttyConfigDidChange(_ notification: SwiftUI.Notification) {
|
@objc private func ghosttyConfigDidChange(_ notification: SwiftUI.Notification) {
|
||||||
@ -381,7 +387,9 @@ extension Ghostty {
|
|||||||
] as? Ghostty.Config else { return }
|
] as? Ghostty.Config else { return }
|
||||||
|
|
||||||
// Update our derived config
|
// Update our derived config
|
||||||
self.derivedConfig = DerivedConfig(config)
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.derivedConfig = DerivedConfig(config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func ghosttyColorDidChange(_ notification: SwiftUI.Notification) {
|
@objc private func ghosttyColorDidChange(_ notification: SwiftUI.Notification) {
|
||||||
@ -391,7 +399,9 @@ extension Ghostty {
|
|||||||
|
|
||||||
switch (change.kind) {
|
switch (change.kind) {
|
||||||
case .background:
|
case .background:
|
||||||
self.backgroundColor = change.color
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.backgroundColor = change.color
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// We don't do anything for the other colors yet.
|
// We don't do anything for the other colors yet.
|
||||||
@ -413,7 +423,9 @@ extension Ghostty {
|
|||||||
// We also just trigger a backing property change. Just in case the screen has
|
// We also just trigger a backing property change. Just in case the screen has
|
||||||
// a different scaling factor, this ensures that we update our content scale.
|
// a different scaling factor, this ensures that we update our content scale.
|
||||||
// Issue: https://github.com/ghostty-org/ghostty/issues/2731
|
// Issue: https://github.com/ghostty-org/ghostty/issues/2731
|
||||||
viewDidChangeBackingProperties()
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.viewDidChangeBackingProperties()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - NSView
|
// MARK: - NSView
|
||||||
|
Reference in New Issue
Block a user