Files
ghostty/macos/Sources/Ghostty/Ghostty.Action.swift
Mitchell Hashimoto 058d6808c1 macos: custom progress bar to workaround macOS 26 ProgressView bugs
Fixes #8731

The progress view in macOS 26 is broken in ways we can't work around
directly. Instead, we must create our own custom progress bar. Luckily,
our usage of the progress view is very simple.

Amp threads:
https://ampcode.com/threads/T-88b550b7-5e0d-4ab9-97d9-36fb63d18f21
https://ampcode.com/threads/T-721d6085-21d5-497d-b6ac-9f203aae0b94
2025-09-18 10:22:54 -07:00

112 lines
2.9 KiB
Swift

import SwiftUI
import GhosttyKit
extension Ghostty {
struct Action {}
}
extension Ghostty.Action {
struct ColorChange {
let kind: Kind
let color: Color
enum Kind {
case foreground
case background
case cursor
case palette(index: UInt8)
}
init(c: ghostty_action_color_change_s) {
switch (c.kind) {
case GHOSTTY_ACTION_COLOR_KIND_FOREGROUND:
self.kind = .foreground
case GHOSTTY_ACTION_COLOR_KIND_BACKGROUND:
self.kind = .background
case GHOSTTY_ACTION_COLOR_KIND_CURSOR:
self.kind = .cursor
default:
self.kind = .palette(index: UInt8(c.kind.rawValue))
}
self.color = Color(red: Double(c.r) / 255, green: Double(c.g) / 255, blue: Double(c.b) / 255)
}
}
struct MoveTab {
let amount: Int
init(c: ghostty_action_move_tab_s) {
self.amount = c.amount
}
}
struct OpenURL {
enum Kind {
case unknown
case text
init(_ c: ghostty_action_open_url_kind_e) {
switch c {
case GHOSTTY_ACTION_OPEN_URL_KIND_TEXT:
self = .text
default:
self = .unknown
}
}
}
let kind: Kind
let url: String
init(c: ghostty_action_open_url_s) {
self.kind = Kind(c.kind)
if let urlCString = c.url {
let data = Data(bytes: urlCString, count: Int(c.len))
self.url = String(data: data, encoding: .utf8) ?? ""
} else {
self.url = ""
}
}
}
struct ProgressReport {
enum State {
case remove
case set
case error
case indeterminate
case pause
init(_ c: ghostty_action_progress_report_state_e) {
switch c {
case GHOSTTY_PROGRESS_STATE_REMOVE:
self = .remove
case GHOSTTY_PROGRESS_STATE_SET:
self = .set
case GHOSTTY_PROGRESS_STATE_ERROR:
self = .error
case GHOSTTY_PROGRESS_STATE_INDETERMINATE:
self = .indeterminate
case GHOSTTY_PROGRESS_STATE_PAUSE:
self = .pause
default:
self = .remove
}
}
}
let state: State
let progress: UInt8?
}
}
// Putting the initializer in an extension preserves the automatic one.
extension Ghostty.Action.ProgressReport {
init(c: ghostty_action_progress_report_s) {
self.state = State(c.state)
self.progress = c.progress >= 0 ? UInt8(c.progress) : nil
}
}