Skip to content

Commit ad57e10

Browse files
committed
fix: dispatch UI updates to main thread for macOS 26 compatibility
Publishing changes from background threads is not allowed in macOS 26 (Tahoe). Ghostty action callbacks run on I/O threads but were modifying AppKit view properties and posting notifications without dispatching to the main thread. Fixes: - GHOSTTY_ACTION_SCROLLBAR: wrap in DispatchQueue.main.async - GHOSTTY_ACTION_CELL_SIZE: wrap in DispatchQueue.main.async - GHOSTTY_ACTION_COLOR_CHANGE: wrap background color updates in main async - GHOSTTY_ACTION_CONFIG_CHANGE: wrap background color clear in main async
1 parent 76c1e63 commit ad57e10

1 file changed

Lines changed: 33 additions & 28 deletions

File tree

Sources/GhosttyTerminalView.swift

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2249,24 +2249,28 @@ class GhosttyApp {
22492249
}
22502250
case GHOSTTY_ACTION_SCROLLBAR:
22512251
let scrollbar = GhosttyScrollbar(c: action.action.scrollbar)
2252-
surfaceView.scrollbar = scrollbar
2253-
NotificationCenter.default.post(
2254-
name: .ghosttyDidUpdateScrollbar,
2255-
object: surfaceView,
2256-
userInfo: [GhosttyNotificationKey.scrollbar: scrollbar]
2257-
)
2252+
DispatchQueue.main.async {
2253+
surfaceView.scrollbar = scrollbar
2254+
NotificationCenter.default.post(
2255+
name: .ghosttyDidUpdateScrollbar,
2256+
object: surfaceView,
2257+
userInfo: [GhosttyNotificationKey.scrollbar: scrollbar]
2258+
)
2259+
}
22582260
return true
22592261
case GHOSTTY_ACTION_CELL_SIZE:
22602262
let cellSize = CGSize(
22612263
width: CGFloat(action.action.cell_size.width),
22622264
height: CGFloat(action.action.cell_size.height)
22632265
)
2264-
surfaceView.cellSize = cellSize
2265-
NotificationCenter.default.post(
2266-
name: .ghosttyDidUpdateCellSize,
2267-
object: surfaceView,
2268-
userInfo: [GhosttyNotificationKey.cellSize: cellSize]
2269-
)
2266+
DispatchQueue.main.async {
2267+
surfaceView.cellSize = cellSize
2268+
NotificationCenter.default.post(
2269+
name: .ghosttyDidUpdateCellSize,
2270+
object: surfaceView,
2271+
userInfo: [GhosttyNotificationKey.cellSize: cellSize]
2272+
)
2273+
}
22702274
return true
22712275
case GHOSTTY_ACTION_START_SEARCH:
22722276
guard let terminalSurface = surfaceView.terminalSurface else { return true }
@@ -2363,36 +2367,37 @@ class GhosttyApp {
23632367
case GHOSTTY_ACTION_COLOR_CHANGE:
23642368
if action.action.color_change.kind == GHOSTTY_ACTION_COLOR_KIND_BACKGROUND {
23652369
let change = action.action.color_change
2366-
surfaceView.backgroundColor = NSColor(
2370+
let newColor = NSColor(
23672371
red: CGFloat(change.r) / 255,
23682372
green: CGFloat(change.g) / 255,
23692373
blue: CGFloat(change.b) / 255,
23702374
alpha: 1.0
23712375
)
23722376
if backgroundLogEnabled {
23732377
logBackground(
2374-
"surface override set tab=\(surfaceView.tabId?.uuidString ?? "nil") surface=\(surfaceView.terminalSurface?.id.uuidString ?? "nil") override=\(surfaceView.backgroundColor?.hexString() ?? "nil") default=\(defaultBackgroundColor.hexString()) source=action.color_change.surface"
2378+
"surface override set tab=\(surfaceView.tabId?.uuidString ?? "nil") surface=\(surfaceView.terminalSurface?.id.uuidString ?? "nil") override=\(newColor.hexString()) default=\(defaultBackgroundColor.hexString()) source=action.color_change.surface"
23752379
)
23762380
}
2377-
surfaceView.applySurfaceBackground()
2378-
if backgroundLogEnabled {
2379-
logBackground("OSC background change tab=\(surfaceView.tabId?.uuidString ?? "unknown") color=\(surfaceView.backgroundColor?.description ?? "nil")")
2380-
}
2381-
DispatchQueue.main.async {
2381+
DispatchQueue.main.async { [self] in
2382+
surfaceView.backgroundColor = newColor
2383+
surfaceView.applySurfaceBackground()
2384+
if backgroundLogEnabled {
2385+
logBackground("OSC background change tab=\(surfaceView.tabId?.uuidString ?? "unknown") color=\(surfaceView.backgroundColor?.description ?? "nil")")
2386+
}
23822387
surfaceView.applyWindowBackgroundIfActive()
23832388
}
23842389
}
23852390
return true
23862391
case GHOSTTY_ACTION_CONFIG_CHANGE:
2387-
if let staleOverride = surfaceView.backgroundColor {
2388-
surfaceView.backgroundColor = nil
2389-
if backgroundLogEnabled {
2390-
logBackground(
2391-
"surface override cleared tab=\(surfaceView.tabId?.uuidString ?? "nil") surface=\(surfaceView.terminalSurface?.id.uuidString ?? "nil") cleared=\(staleOverride.hexString()) source=action.config_change.surface"
2392-
)
2393-
}
2394-
surfaceView.applySurfaceBackground()
2395-
DispatchQueue.main.async {
2392+
DispatchQueue.main.async { [self] in
2393+
if let staleOverride = surfaceView.backgroundColor {
2394+
surfaceView.backgroundColor = nil
2395+
if backgroundLogEnabled {
2396+
logBackground(
2397+
"surface override cleared tab=\(surfaceView.tabId?.uuidString ?? "nil") surface=\(surfaceView.terminalSurface?.id.uuidString ?? "nil") cleared=\(staleOverride.hexString()) source=action.config_change.surface"
2398+
)
2399+
}
2400+
surfaceView.applySurfaceBackground()
23962401
surfaceView.applyWindowBackgroundIfActive()
23972402
}
23982403
}

0 commit comments

Comments
 (0)