Repository navigation
Fix macOS 27 symbol launch crash - #6728
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds AppKit-backed SF Symbol rasterization through ChangesSF Symbol rendering migration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (2 errors, 1 warning)
✅ Passed checks (22 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR routes SF Symbol rendering off SwiftUI's
Confidence Score: 5/5Safe to merge — the change is a mechanical, well-tested migration of SF Symbol rendering to an AppKit-backed path with proper @mainactor isolation and bounded caching. The new CmuxSystemSymbolImage implementation is correct: the @MainActor-isolated cache avoids per-render allocations, size clamping is applied consistently, aspect-ratio fitting is verified by tests, and the magnified: vs systemName: label distinction cleanly separates magnification-aware from fixed-size call sites. No concurrency violations, no data races, no disk I/O on interactive paths, and no user-facing text changes. The open concern from prior review threads (the #if DEBUG resetRenderabilityCacheForTesting() seam extended to cover the two new caches) is the only residual issue and was already known before this PR. Sources/RenderableSystemSymbol.swift warrants a second look for the pre-existing #if DEBUG production seam, which this PR extended; all other files are straightforward call-site migrations. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["CmuxSystemSymbolImage.body"] --> B["resolvedRasterPointSize(pointSize, globalFontPercent, appliesGlobalFontMagnification)"]
B --> C{"appliesGlobalFontMagnification?"}
C -- "No" --> D["clampedRasterPointSize(pointSize) → rasterSize ≥ 1"]
C -- "Yes" --> E["clampedRasterPointSize then GlobalFontMagnification.scaledSize → rasterSize"]
D --> F["configuredAppKitImage(systemName, rasterSize, weight) @MainActor"]
E --> F
F --> G{"appKitImageCache hit?"}
G -- "Yes" --> H["Return cached NSImage"]
G -- "No" --> I{"renderabilityCache == false?"}
I -- "Yes" --> J["Return nil → Color.clear placeholder"]
I -- "No" --> K["NSImage(systemSymbolName:)"]
K -- "nil" --> L["cacheRenderability(false) → Return nil"]
K -- "image" --> M["withSymbolConfiguration(pointSize, weight)"]
M --> N["copy(), isTemplate = true, size = fittedSymbolSize(natural, max: rasterSize)"]
N --> O["Store in appKitImageCache (FIFO evict at 256)"]
O --> H
H --> P["Image(nsImage:).renderingMode(.template).frame(rasterSize × rasterSize)"]
J --> Q["Color.clear.frame(rasterSize × rasterSize).accessibilityHidden(true)"]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A["CmuxSystemSymbolImage.body"] --> B["resolvedRasterPointSize(pointSize, globalFontPercent, appliesGlobalFontMagnification)"]
B --> C{"appliesGlobalFontMagnification?"}
C -- "No" --> D["clampedRasterPointSize(pointSize) → rasterSize ≥ 1"]
C -- "Yes" --> E["clampedRasterPointSize then GlobalFontMagnification.scaledSize → rasterSize"]
D --> F["configuredAppKitImage(systemName, rasterSize, weight) @MainActor"]
E --> F
F --> G{"appKitImageCache hit?"}
G -- "Yes" --> H["Return cached NSImage"]
G -- "No" --> I{"renderabilityCache == false?"}
I -- "Yes" --> J["Return nil → Color.clear placeholder"]
I -- "No" --> K["NSImage(systemSymbolName:)"]
K -- "nil" --> L["cacheRenderability(false) → Return nil"]
K -- "image" --> M["withSymbolConfiguration(pointSize, weight)"]
M --> N["copy(), isTemplate = true, size = fittedSymbolSize(natural, max: rasterSize)"]
N --> O["Store in appKitImageCache (FIFO evict at 256)"]
O --> H
H --> P["Image(nsImage:).renderingMode(.template).frame(rasterSize × rasterSize)"]
J --> Q["Color.clear.frame(rasterSize × rasterSize).accessibilityHidden(true)"]
Reviews (5): Last reviewed commit: "Bound renderability symbol cache" | Re-trigger Greptile |
| var body: some View { | ||
| let rasterSize = RenderableSystemSymbol.clampedRasterPointSize(pointSize) | ||
| let systemFont: Font = weight.map { .system(size: rasterSize, weight: $0) } ?? .system(size: rasterSize) | ||
| return font(systemFont) | ||
| .frame(width: rasterSize, height: rasterSize, alignment: alignment) | ||
| if let image = RenderableSystemSymbol.configuredAppKitImage( | ||
| systemName: systemName, | ||
| pointSize: rasterSize, | ||
| weight: weight | ||
| ) { | ||
| Image(nsImage: image) | ||
| .renderingMode(.template) | ||
| .frame(width: rasterSize, height: rasterSize, alignment: alignment) | ||
| } else { | ||
| Color.clear | ||
| .frame(width: rasterSize, height: rasterSize, alignment: alignment) | ||
| .accessibilityHidden(true) | ||
| } | ||
| } |
There was a problem hiding this comment.
Per-render NSImage allocations on hot sidebar-row path
CmuxSystemSymbolImage.body calls configuredAppKitImage unconditionally on every render, allocating at least three NSImage objects per symbol (NSImage(systemSymbolName:), withSymbolConfiguration, copy()). TabItemView alone hosts up to 8 CmuxSystemSymbolImage instances (pin, audio, mic, camera, xmark, two branch icons, circle.fill), meaning ≥24 AppKit allocations per visible tab per render cycle. The previous cmuxSymbolRasterSize modifier was a zero-allocation font/frame attribute change — this replacement adds unbounded AppKit churn on every view invalidation for every visible row. Add a @MainActor static var imageCache: [CacheKey: NSImage] = [:] on RenderableSystemSymbol (keyed by (systemName, rasterSize, weight)) matching the pattern already used for renderabilityCache, so repeat renders of the same symbol at the same size reuse the existing NSImage instance.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Addressed in 72665b1 by adding a bounded @mainactor cache keyed by symbol name, clamped raster size, and AppKit font weight. Added a test that repeated configuredAppKitImage calls reuse the same NSImage instance.
— Claude Code
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Sources/RenderableSystemSymbol.swift`:
- Around line 95-98: The image sizing logic at line 98 forces NSImage to a
square size regardless of the symbol's natural aspect ratio, causing non-square
SF Symbols to be distorted. Instead of setting image.size to NSSize(width:
rasterSize, height: rasterSize), calculate the proportional dimensions by
determining the natural aspect ratio of the symbol after applying the
configuration and scaling it so the longer dimension equals rasterSize while
maintaining the correct aspect ratio. Additionally, update the test that
currently uses the symmetric questionmark.circle symbol to use a non-square
symbol like chevron.right or arrow.left to verify that non-square symbols render
without distortion.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 46173ec4-369f-4eaf-86d0-4c9da8584a5d
📒 Files selected for processing (2)
Sources/RenderableSystemSymbol.swiftcmuxTests/RenderableSystemSymbolTests.swift
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Sources/RightSidebarChromeStyle.swift (1)
28-32: 🎯 Functional Correctness | 🟡 MinorVerify
appliesGlobalFontMagnificationconsistency for header chrome icons.
HeaderChromeIconStyle.symboldoes not setappliesGlobalFontMagnification, defaulting tofalse. This differs fromModeBarButton(line 357) and all threeSidebarWorkspaceGroupHeaderViewicons (lines 128, 151, 188), which explicitly setappliesGlobalFontMagnification: true. Confirm that header chrome icons should remain fixed size when users adjust global font magnification settings, or add the parameter if they should scale consistently with other sidebar UI.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Sources/RightSidebarChromeStyle.swift` around lines 28 - 32, The CmuxSystemSymbolImage initialization in HeaderChromeIconStyle.symbol is missing the appliesGlobalFontMagnification parameter, which defaults to false and differs from the consistency pattern used in ModeBarButton and SidebarWorkspaceGroupHeaderView icons that explicitly set this to true. Add the appliesGlobalFontMagnification parameter to the CmuxSystemSymbolImage call and set it to true to ensure header chrome icons scale consistently with other sidebar UI elements when users adjust global font magnification settings.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@Sources/RightSidebarChromeStyle.swift`:
- Around line 28-32: The CmuxSystemSymbolImage initialization in
HeaderChromeIconStyle.symbol is missing the appliesGlobalFontMagnification
parameter, which defaults to false and differs from the consistency pattern used
in ModeBarButton and SidebarWorkspaceGroupHeaderView icons that explicitly set
this to true. Add the appliesGlobalFontMagnification parameter to the
CmuxSystemSymbolImage call and set it to true to ensure header chrome icons
scale consistently with other sidebar UI elements when users adjust global font
magnification settings.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 840e68a8-656f-4c52-8500-9bb338018322
📒 Files selected for processing (6)
Sources/ContentView.swiftSources/RenderableSystemSymbol.swiftSources/RightSidebarChromeStyle.swiftSources/SidebarWorkspaceGroupHeaderView.swiftSources/TextBoxInput.swiftcmuxTests/RenderableSystemSymbolTests.swift
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@cmuxTests/RenderableSystemSymbolTests.swift`:
- Around line 62-71: The test fittedSymbolSizeScalesLongerDimensionToRasterSize
only tests landscape orientation (width larger than height) and an invalid-size
fallback, but does not cover portrait orientation (height larger than width).
Add another `#expect` assertion to the
fittedSymbolSizeScalesLongerDimensionToRasterSize function that tests the
portrait case by calling RenderableSystemSymbol.fittedSymbolSize with
NSSize(width: 10, height: 20) and maximumDimension: 16, expecting it to return
NSSize(width: 8, height: 16), which verifies the function correctly scales the
longer dimension regardless of orientation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 10e89a79-b84a-4192-8b51-b97910b2f8fe
📒 Files selected for processing (2)
Sources/RenderableSystemSymbol.swiftcmuxTests/RenderableSystemSymbolTests.swift
| @Test func fittedSymbolSizeScalesLongerDimensionToRasterSize() { | ||
| #expect(RenderableSystemSymbol.fittedSymbolSize( | ||
| NSSize(width: 20, height: 10), | ||
| maximumDimension: 16 | ||
| ) == NSSize(width: 16, height: 8)) | ||
| #expect(RenderableSystemSymbol.fittedSymbolSize( | ||
| NSSize(width: 0, height: 10), | ||
| maximumDimension: 16 | ||
| ) == NSSize(width: 16, height: 16)) | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Add a portrait aspect-ratio case.
This covers landscape scaling and invalid-size fallback, but not the opposite orientation. A regression that always scales from width could still pass; add 10×20 → 8×16 to lock in portrait symbols too.
🧪 Proposed test addition
`@Test` func fittedSymbolSizeScalesLongerDimensionToRasterSize() {
`#expect`(RenderableSystemSymbol.fittedSymbolSize(
NSSize(width: 20, height: 10),
maximumDimension: 16
) == NSSize(width: 16, height: 8))
+ `#expect`(RenderableSystemSymbol.fittedSymbolSize(
+ NSSize(width: 10, height: 20),
+ maximumDimension: 16
+ ) == NSSize(width: 8, height: 16))
`#expect`(RenderableSystemSymbol.fittedSymbolSize(
NSSize(width: 0, height: 10),
maximumDimension: 16
) == NSSize(width: 16, height: 16))
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Test func fittedSymbolSizeScalesLongerDimensionToRasterSize() { | |
| #expect(RenderableSystemSymbol.fittedSymbolSize( | |
| NSSize(width: 20, height: 10), | |
| maximumDimension: 16 | |
| ) == NSSize(width: 16, height: 8)) | |
| #expect(RenderableSystemSymbol.fittedSymbolSize( | |
| NSSize(width: 0, height: 10), | |
| maximumDimension: 16 | |
| ) == NSSize(width: 16, height: 16)) | |
| } | |
| `@Test` func fittedSymbolSizeScalesLongerDimensionToRasterSize() { | |
| `#expect`(RenderableSystemSymbol.fittedSymbolSize( | |
| NSSize(width: 20, height: 10), | |
| maximumDimension: 16 | |
| ) == NSSize(width: 16, height: 8)) | |
| `#expect`(RenderableSystemSymbol.fittedSymbolSize( | |
| NSSize(width: 10, height: 20), | |
| maximumDimension: 16 | |
| ) == NSSize(width: 8, height: 16)) | |
| `#expect`(RenderableSystemSymbol.fittedSymbolSize( | |
| NSSize(width: 0, height: 10), | |
| maximumDimension: 16 | |
| ) == NSSize(width: 16, height: 16)) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@cmuxTests/RenderableSystemSymbolTests.swift` around lines 62 - 71, The test
fittedSymbolSizeScalesLongerDimensionToRasterSize only tests landscape
orientation (width larger than height) and an invalid-size fallback, but does
not cover portrait orientation (height larger than width). Add another `#expect`
assertion to the fittedSymbolSizeScalesLongerDimensionToRasterSize function that
tests the portrait case by calling RenderableSystemSymbol.fittedSymbolSize with
NSSize(width: 10, height: 20) and maximumDimension: 16, expecting it to return
NSSize(width: 8, height: 16), which verifies the function correctly scales the
longer dimension regardless of orientation.
| #if DEBUG | ||
| @MainActor | ||
| static func resetRenderabilityCacheForTesting() { | ||
| renderabilityCache.removeAll() | ||
| appKitImageCache.removeAll() | ||
| appKitImageCacheInsertionOrder.removeAll() | ||
| } | ||
| #endif |
There was a problem hiding this comment.
#if DEBUG test seam in production source worsened
resetRenderabilityCacheForTesting() already existed as a #if DEBUG-guarded function named with ForTesting, which matches the pattern the team's production-seam rule explicitly fails. This PR worsens the seam by extending it to also reset appKitImageCache and appKitImageCacheInsertionOrder — two new private caches whose only reset path in tests is now this compile-guarded function. The canonical fix is to widen appKitImageCache and appKitImageCacheInsertionOrder from private to internal, then let the test target reach them directly via @testable import, removing the need for the #if DEBUG function to cover the new state (or removing the function entirely).
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Sources/TextBoxInput.swift (1)
2879-2890: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAdd an explicit accessibility label for the icon-only dismiss button.
This button has
.help(...)but no.accessibilityLabel(...), which can make VoiceOver output ambiguous.Suggested patch
Button { dismissPendingComments() } label: { CmuxSystemSymbolImage(magnified: "xmark", pointSize: 9, weight: .bold) .frame(width: 16, height: 16) .background(Circle().fill(foreground.opacity(0.12))) } .buttonStyle(.plain) .help(String( localized: "textbox.diffComments.dismiss", defaultValue: "Dismiss comments without sending" )) + .accessibilityLabel(String( + localized: "textbox.diffComments.dismiss", + defaultValue: "Dismiss comments without sending" + ))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Sources/TextBoxInput.swift` around lines 2879 - 2890, The icon-only dismiss Button in TextBoxInput should have an explicit accessibility label in addition to the existing help text. Update the Button that calls dismissPendingComments() and uses CmuxSystemSymbolImage so it includes a clear .accessibilityLabel(...) describing the dismiss action, while keeping the current .help(...) for tooltip behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@Sources/TextBoxInput.swift`:
- Around line 2879-2890: The icon-only dismiss Button in TextBoxInput should
have an explicit accessibility label in addition to the existing help text.
Update the Button that calls dismissPendingComments() and uses
CmuxSystemSymbolImage so it includes a clear .accessibilityLabel(...) describing
the dismiss action, while keeping the current .help(...) for tooltip behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: a360f8c2-f526-483e-81bb-10f122159c9b
📒 Files selected for processing (6)
Sources/ContentView.swiftSources/Panels/BrowserPanelView.swiftSources/RenderableSystemSymbol.swiftSources/TextBoxInput.swiftSources/Update/UpdateTitlebarAccessory.swiftcmuxTests/RenderableSystemSymbolTests.swift
* Add failing guard for macOS 27 launch-path SF Symbols (#6745) Asserts the content views laid out during launch / session restore never use SwiftUI Image(systemName:) / Label(systemImage:), which crash on macOS 27 via CoreUI CUINamedVectorGlyph _rasterizeImageUsingScaleFactor during the first window layout. This commit adds only the test; it fails because NotificationsPage, WorkspaceContentView, TerminalPanelView, and RemoteTmuxPaneHeader still use the crash-prone APIs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix macOS 27 launch crash in restore-path content views (#6745) #6728 moved launch *chrome* (sidebar, titlebar, toolbars) off SwiftUI Image(systemName:) to dodge the macOS 27 CoreUI CUINamedVectorGlyph _rasterizeImageUsingScaleFactor crash, but missed the content-area views that are laid out on the first frame of a launched or session-restored window. The decisive one is NotificationsPage: it is mounted unconditionally in the main content ZStack (ContentView.terminalContent) and only toggled via .opacity, so its body — and its empty-state `bell.slash` glyph — is measured during the first NSWindow.makeKeyAndOrderFront: layout on every launch, even when the sidebar shows the tab list. That raw Image(systemName:) still crashes the app before any window appears on macOS 27 beta 2, exactly as reported. Route these views' SF Symbols through the AppKit-backed CmuxSystemSymbolImage instead: - NotificationsPage: bell.slash, bell.badge, xmark.circle.fill - WorkspaceContentView (EmptyPanelView): terminal.fill + the Terminal/Browser action-button labels (Label(systemImage:) rasterizes the same way) - TerminalPanelView (AgentHibernationPlaceholderView): pause.circle - RemoteTmuxPaneHeader: pane control glyphs The last three render the moment a saved layout containing an empty panel, a hibernated agent, or a remote tmux pane is restored — no user interaction required — so they are part of the same launch-crash surface. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Address review: behavioral symbol coverage + dedupe empty-pane button - Replace the source-scanning launch-path guard test (flagged in review as a brittle "fake regression test") with behavioral coverage: assert every launch/restore-path SF Symbol resolves through the non-crashing AppKit path (configuredAppKitImage) the fix routes them onto. The macOS 27 crash itself only reproduces on a macOS 27 runner, which is documented on the test. - Dedupe emptyPaneActionButton's two near-identical branches into one shared button with a conditional .keyboardShortcut, keeping behavior identical and bringing WorkspaceContentView.swift back under the Swift file-length budget. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Address review: label clear button; drop non-guarding symbol test - Add an explicit .accessibilityLabel to NotificationRow's icon-only clear button (reusing the existing notifications.row.clear string). Migrating to CmuxSystemSymbolImage drops the implicit VoiceOver name the SwiftUI system-symbol path supplied, so VoiceOver would otherwise announce an unlabeled button. Matches RemoteTmuxPaneHeader's existing pattern. - Remove the launch-path symbol test. Both the source-scan and the configuredAppKitImage variants were flagged in review as not real regression guards: the macOS 27 CoreUI crash only reproduces on macOS 27, so no test on CI's older macOS can distinguish the safe AppKit route from the crashing SwiftUI route. Per repo policy ("if the bug isn't cleanly testable, say so rather than faking a test"), the protection is the production migration plus manual macOS 27 validation, documented on the PR. The existing RenderableSystemSymbolTests already cover the AppKit rendering path itself. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: cmux <cmux@cmuxs-Mac-mini.local> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Testing
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by cubic
Fixes a macOS 27 launch crash by routing SF Symbol rendering through an AppKit-backed path with consistent template rasterization, aspect‑ratio‑preserving fitting, and caching, while preserving global font magnification where expected. Closes #6703.
CmuxSystemSymbolImageusingNSImage.SymbolConfiguration; clamps sizes, preserves aspect ratio, returns template images, caches AppKit symbols (256 max, FIFO), and bounds the renderability cache for unknown symbols (512 max, FIFO).appliesGlobalFontMagnification, applied across sidebar, tabs, browser toolbar, titlebar, right sidebar, text box, and headers.CmuxSystemSymbolImageacross chrome, removed the no‑op flat color helper, and kept call sites short viamagnified:and explicit magnification flags.Written for commit a3e7c20. Summary will update on new commits.
Summary by CodeRabbit
Refactor
systemName,pointSize, andweight, replacing ad-hoc font/raster sizing approaches.Tests