-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
GhosttyTerminalView decomposition: terminal surface model (stack D) #6024
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 57 commits
Commits
Show all changes
63 commits
Select commit
Hold shift + click to select a range
00da345
CmuxControlSocket stage 3c-1: ControlCommandCoordinator + window domain
azooz2003-bit 2383068
stage 3c: multi-protocol seam umbrella + shared param/ref helper port
azooz2003-bit b02c28d
stage 3c: extract App Focus + Feed + Notification domains
azooz2003-bit 9bdae00
stage 3c: extract Mobile Host + Workspace Groups + Pane domains
azooz2003-bit 4b8118f
stage 3c: fix int/double param helpers to match legacy NSNumber coercion
azooz2003-bit 1905b38
stage 3c: integrate Workspace + Surface domains (full lifts)
azooz2003-bit 8f7ac89
stage 3c: organize coordinator files into per-domain subfolders
azooz2003-bit 487baaf
stage 3c: dedupe workspace.create onto the shared v2WorkspaceCreate body
azooz2003-bit 6f2cba5
stage 3c: fix 8 divergences found by Workspace+Surface adversarial re…
azooz2003-bit fe419f0
Budget: entries for the two coordinator files grown by the divergence…
azooz2003-bit a94589d
Merge remote-tracking branch 'origin/main' into feat-ctl-coordinator-…
azooz2003-bit 1e19188
CmuxTerminalCore: extract terminal core leaf (interop, key translatio…
azooz2003-bit edbdf67
CI: gate CmuxTerminalCore package tests (66 tests, 15 suites)
azooz2003-bit 6b96072
Fix the two warnings that tripped the CI Swift warning budget
azooz2003-bit f731c27
Fix duplicate parameter name warning (sessionID sessionID) in workspa…
azooz2003-bit 7d234dc
stage 3c: package side of System/Project/Debug/Sidebar/Browser domain…
azooz2003-bit 494988f
CI: tolerate the cosmetic GhosttyKit binaryTarget diagnostic in the C…
azooz2003-bit 39d111b
stage 3c: cut over System/Project/Debug/Sidebar/Browser domains to th…
azooz2003-bit ecd5148
stage 3c: dedupe file.open onto the shared v2FileOpen body
azooz2003-bit 3178b68
stage 3c: fix browser.focus_mode.set/zoom.set error precedence; finis…
azooz2003-bit 42f9332
Budget tsv: strip accidental leading whitespace
azooz2003-bit d47e003
Merge pull request #5909 from manaflow-ai/feat-ctl-3c-final-domains
azooz2003-bit 29d8342
stage 3c: address review threads (handles observation, window.close t…
azooz2003-bit aadae54
CmuxTerminalCore: clipboard, render-demand, and surface-registry seams
azooz2003-bit 0713b6d
CmuxTerminalServices: TerminalPasteboardService lifts GhosttyPasteboa…
azooz2003-bit 0b6812d
CmuxTerminalEngine: surface registry, render-demand gating, Metal layer
azooz2003-bit 0e5d265
App: rewire to CmuxTerminalEngine/CmuxTerminalServices, delete lifted…
azooz2003-bit ad70889
GhosttyMetalLayer: one critical section per vended drawable
azooz2003-bit 2be538e
Merge origin/main: adopt PR 5778's socket-worker browser JS lane; rev…
azooz2003-bit 5ebac5c
Engine tests: deterministic route-retire wait (fixes CI hang)
azooz2003-bit 362ace9
Merge origin/feat-ctl-coordinator-3c-1 into feat-terminal-core
azooz2003-bit 35eb145
Merge origin/feat-terminal-core into feat-terminal-engine
azooz2003-bit f54b421
CmuxTerminalCore: no namespace types; lint-enforce the rule repo-wide
azooz2003-bit 57fd951
Merge remote-tracking branch 'origin/feat-terminal-core' into feat-te…
azooz2003-bit 6996fc6
Merge origin/main into feat-terminal-core
azooz2003-bit 8bbb21b
Merge origin/feat-terminal-core into feat-terminal-engine
azooz2003-bit ea8d799
Lift TerminalSurface model into CmuxTerminal package (stack D, tranch…
azooz2003-bit 38b18b7
Hoist import CmuxTerminal into app-side tests naming the moved surfac…
azooz2003-bit f4c3689
Lift window-background policy + compositor blur into CmuxWorkspaceWin…
azooz2003-bit be6b65f
Lift Ghostty config-path namespace cluster into CmuxTerminalCore (sta…
azooz2003-bit c65e50d
Lift GhosttyBackgroundBlur config value into CmuxTerminalCore (stack …
azooz2003-bit 0ce1595
Lift NSColor(hex:)/luminance/darken into CmuxTerminalCore (stack D, t…
azooz2003-bit 5981d4a
Break GhosttyConfig <-> GhosttyApp config recursion by inverting owne…
azooz2003-bit 3486bfe
Remove pbxproj references to the lifted CmuxApplicationSupportDirecto…
azooz2003-bit 966c913
Relocate config-path namespace cluster to CmuxFoundation; the CLI sha…
azooz2003-bit 3a89a1b
Wire CmuxTerminalCore into cmuxTests + fix test imports for lifted co…
azooz2003-bit 8b5086c
Fix pre-existing Swift 6 isolation break in CmuxWorkspaceWindow blur …
azooz2003-bit b4b37ad
Consolidate config color/blur value types into CmuxFoundation; unwire…
azooz2003-bit 959bd30
Remove stale WindowTransparencyDecisionTests referencing lifted free …
azooz2003-bit 8c3de19
Lift SystemAppearance into CmuxTerminalCore as TerminalSystemAppearan…
azooz2003-bit fbd0e21
Lift ColorSchemePreference into CmuxTerminalCore as TerminalColorSche…
azooz2003-bit a160955
Move terminal color-scheme resolution into CmuxTerminalCore; GhosttyC…
azooz2003-bit 2d3e968
Invert the DEBUG startup-preview reach out of GhosttyConfig (stack D,…
azooz2003-bit 8e40b09
Lift NSColor.hexString() into CmuxFoundation (stack D, tranche A sub-6a)
azooz2003-bit 943dc10
Move GhosttyConfig into CmuxTerminalCore (stack D, tranche A sub-6b)
azooz2003-bit 8ca488b
Retarget the self-contained GhosttyConfig font-size suites into CmuxT…
azooz2003-bit 3f8e336
Merge origin/main into feat-terminal-surface (re-sync onto merged 592…
azooz2003-bit cf80953
Fix post-re-sync CI: cmuxTests TerminalSurface import + 4 Swift-6 iso…
azooz2003-bit 713016c
Ratchet GhosttyTerminalView file-length budget for the isolation-warn…
azooz2003-bit b67c530
Restore ghostty_surface_quicklook_font test stub in Engine/Services p…
azooz2003-bit 00aca95
Merge origin/main again (5792 device-presence, 6057 Metal drawable, 6…
azooz2003-bit 3b77c21
Add CmuxTerminal import to GhosttyDrawableSizeRetryTests (new 6057 te…
azooz2003-bit 69abbe3
Merge origin/main again (5991 Workspace god-model split: CmuxWorkspac…
azooz2003-bit File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import Foundation | ||
| import CmuxFoundation | ||
|
|
||
| extension CMUXCLI { | ||
| func runConfigCommand( | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import Foundation | ||
| import CmuxFoundation | ||
|
|
||
| extension CMUXCLI { | ||
| func availableThemeNames() -> [String] { | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import Foundation | ||
| import CmuxFoundation | ||
| import Darwin | ||
|
|
||
| extension CMUXCLI { | ||
|
|
||
80 changes: 80 additions & 0 deletions
80
Packages/CmuxFoundation/Sources/CmuxFoundation/Color/NSColor+Hex.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| public import AppKit | ||
|
|
||
| extension NSColor { | ||
| /// Creates a color from a 6-digit hex string (with or without a leading | ||
| /// `#`), or `nil` when the string is not a valid 6-digit hex color. | ||
| public convenience init?(hex: String) { | ||
| var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines) | ||
| hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "") | ||
|
|
||
| var rgb: UInt64 = 0 | ||
| guard Scanner(string: hexSanitized).scanHexInt64(&rgb) else { | ||
| return nil | ||
| } | ||
|
|
||
| let r, g, b: CGFloat | ||
| if hexSanitized.count == 6 { | ||
| r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0 | ||
| g = CGFloat((rgb & 0x00FF00) >> 8) / 255.0 | ||
| b = CGFloat(rgb & 0x0000FF) / 255.0 | ||
| } else { | ||
| return nil | ||
| } | ||
|
|
||
| self.init(red: r, green: g, blue: b, alpha: 1.0) | ||
| } | ||
|
|
||
| /// Whether the color reads as light (relative luminance above 0.5). | ||
| public var isLightColor: Bool { | ||
| luminance > 0.5 | ||
| } | ||
|
|
||
| /// The perceptual relative luminance of the color in sRGB, or `0` when the | ||
| /// color cannot be converted to sRGB. | ||
| public var luminance: Double { | ||
| var r: CGFloat = 0 | ||
| var g: CGFloat = 0 | ||
| var b: CGFloat = 0 | ||
| var a: CGFloat = 0 | ||
|
|
||
| guard let rgb = usingColorSpace(.sRGB) else { return 0 } | ||
| rgb.getRed(&r, green: &g, blue: &b, alpha: &a) | ||
| return (0.299 * r) + (0.587 * g) + (0.114 * b) | ||
| } | ||
|
|
||
| /// Returns a darkened copy of the color, reducing brightness by `amount` | ||
| /// (0...1) in HSB space. | ||
| public func darken(by amount: CGFloat) -> NSColor { | ||
| var h: CGFloat = 0 | ||
| var s: CGFloat = 0 | ||
| var b: CGFloat = 0 | ||
| var a: CGFloat = 0 | ||
| getHue(&h, saturation: &s, brightness: &b, alpha: &a) | ||
| return NSColor( | ||
| hue: h, | ||
| saturation: s, | ||
| brightness: min(b * (1 - amount), 1), | ||
| alpha: a | ||
| ) | ||
| } | ||
|
|
||
| /// The color as a `#`-prefixed, uppercased sRGB hex string. Returns a 6-digit | ||
| /// `#RRGGBB` string, or an 8-digit `#RRGGBBAA` string when `includeAlpha` is | ||
| /// `true`. The inverse of ``init(hex:)``. | ||
| public func hexString(includeAlpha: Bool = false) -> String { | ||
| let color = usingColorSpace(.sRGB) ?? self | ||
| var red: CGFloat = 0 | ||
| var green: CGFloat = 0 | ||
| var blue: CGFloat = 0 | ||
| var alpha: CGFloat = 0 | ||
| color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) | ||
| let redByte = min(255, max(0, Int(red * 255))) | ||
| let greenByte = min(255, max(0, Int(green * 255))) | ||
| let blueByte = min(255, max(0, Int(blue * 255))) | ||
| if includeAlpha { | ||
| let alphaByte = min(255, max(0, Int(alpha * 255))) | ||
| return String(format: "#%02X%02X%02X%02X", redByte, greenByte, blueByte, alphaByte) | ||
| } | ||
| return String(format: "#%02X%02X%02X", redByte, greenByte, blueByte) | ||
| } | ||
| } | ||
49 changes: 49 additions & 0 deletions
49
...CmuxFoundation/Sources/CmuxFoundation/ConfigPaths/CmuxApplicationSupportDirectories.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| public import Foundation | ||
|
|
||
| /// Resolves the Application Support base directories cmux scans for Ghostty | ||
| /// configuration, honoring `CFFIXED_USER_HOME` for test/sandbox overrides. | ||
| /// | ||
| /// TRANSITIONAL: faithful lift of the app-target config-path namespace cluster | ||
| /// the engine and ``GhosttyConfig`` recurse through. These stateless directory | ||
| /// transforms have no natural receiver type; modernization into instantiated, | ||
| /// dependency-injected resolvers is deferred to the engine lift (Tranche C). | ||
| // lint:allow namespace-type — see TRANSITIONAL note above. | ||
| public enum CmuxApplicationSupportDirectories { | ||
| /// Returns the de-duplicated, standardized Application Support directories to | ||
| /// search, ordered from the most specific (`FileManager`-resolved) to the | ||
| /// `~/Library/Application Support` fallback. | ||
| public static func userDirectories( | ||
| environment: [String: String], | ||
| fileManager: FileManager = .default | ||
| ) -> [URL] { | ||
| var urls: [URL] = [] | ||
| var seen: Set<String> = [] | ||
|
|
||
| func append(_ url: URL?) { | ||
| guard let url else { return } | ||
| let standardized = url.standardizedFileURL | ||
| if seen.insert(standardized.path).inserted { | ||
| urls.append(standardized) | ||
| } | ||
| } | ||
|
|
||
| append(fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first) | ||
|
|
||
| if let fixedHome = environment["CFFIXED_USER_HOME"]?.trimmingCharacters(in: .whitespacesAndNewlines), | ||
| !fixedHome.isEmpty { | ||
| append( | ||
| URL(fileURLWithPath: fixedHome, isDirectory: true) | ||
| .appendingPathComponent("Library/Application Support", isDirectory: true) | ||
| ) | ||
| } | ||
|
|
||
| append( | ||
| URL( | ||
| fileURLWithPath: NSString(string: "~/Library/Application Support").expandingTildeInPath, | ||
| isDirectory: true | ||
| ) | ||
| ) | ||
|
|
||
| return urls | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
In Swift Foundation, does Scanner.scanHexInt64(_:) succeed when only a prefix is valid hex (for example "12GG34")? Is checking scanner.isAtEnd required for strict full-string validation?💡 Result:
In Swift Foundation, Scanner.scanHexInt64(:) does succeed when only a prefix is valid [1][2]. The method scans for a valid hexadecimal representation starting at the current position, and if found, it returns true and advances the scanner's position past the end of the scanned hexadecimal digits [1]. It does not require that the entire remainder of the string be consumed or that the scanner be at the end of the string [1]. For example, if you call scanHexInt64(:) on the string "12GG34", the scanner will successfully identify "12" as a valid hexadecimal number, store the value 0x12 (18) in the provided pointer, and move the scanner's current position to the character 'G'. Because it successfully scanned a valid prefix, it returns true [1]. Therefore, checking scanner.isAtEnd is required if you want to ensure the entire string is a valid hexadecimal number [1][3]. Without this check, the scanner will report success as long as it finds a valid numeric start, leaving the remaining invalid characters unparsed [1]. To perform strict full-string validation, you must ensure that after the scan completes, scanner.isAtEnd is true [1][4].
Citations:
🏁 Script executed:
Repository: manaflow-ai/cmux
Length of output: 133
🏁 Script executed:
cat -n "./Packages/CmuxFoundation/Sources/CmuxFoundation/Color/NSColor+Hex.swift"Repository: manaflow-ai/cmux
Length of output: 3537
Reject malformed hex input before conversion.
The hex parser accepts invalid input for two reasons:
Line 8:
replacingOccurrences(of: "#", with: "")removes all#characters globally, not just a leading prefix. Input like"1#23456"normalizes to"123456"and is accepted.Lines 10–13:
Scanner.scanHexInt64(_:)succeeds on a valid hex prefix and does not consume the entire string. Input like"12ABXX"(6 chars) passes the length check, but Scanner consumes only"12AB", leaving"XX"unparsed. The resulting color is incorrect.Replace with strict validation and parsing:
🔧 Suggested fix
🤖 Prompt for AI Agents