Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
public import AppKit
public import Foundation
public import GhosttyKit
public import CmuxTerminalCore

// MARK: - Surface sizing and scale

extension TerminalSurface {
/// Assigns the host that authorizes view-driven renderer and PTY sizing.
/// - Parameter authority: The current portal, or nil when the surface is detached.
@MainActor
public func setSurfaceResizeAuthority(_ authority: (any TerminalSurfaceResizeAuthority)?) {
surfaceResizeAuthority = authority
}

/// Match upstream Ghostty AppKit sizing: framebuffer dimensions are derived
/// from backing-space points and truncated (never rounded up).
func pixelDimension(from value: CGFloat) -> UInt32 {
Expand All @@ -23,6 +15,7 @@ extension TerminalSurface {
}
return UInt32(floored)
}

@MainActor
func scaleFactors(for view: any TerminalSurfaceNativeViewing) -> (x: CGFloat, y: CGFloat, layer: CGFloat) {
let scale = max(
Expand All @@ -34,6 +27,7 @@ extension TerminalSurface {
)
return (scale, scale, scale)
}

func scaleApproximatelyEqual(_ lhs: CGFloat, _ rhs: CGFloat, epsilon: CGFloat = 0.0001) -> Bool {
abs(lhs - rhs) <= epsilon
}
Expand Down Expand Up @@ -171,8 +165,7 @@ extension TerminalSurface {
@MainActor
public func reapplyAssignedGrid() {
guard ioMode.usesManualIO, lastUncappedPixelWidth > 0, lastUncappedPixelHeight > 0,
lastXScale > 0, lastYScale > 0,
surfaceResizeAuthority?.isRendererResizeDeferred != true else { return }
lastXScale > 0, lastYScale > 0 else { return }
_ = updateSize(
width: CGFloat(lastUncappedPixelWidth) / lastXScale,
height: CGFloat(lastUncappedPixelHeight) / lastYScale,
Expand Down Expand Up @@ -212,7 +205,6 @@ extension TerminalSurface {
suppressAssignedGridPin: Bool = false,
caller: StaticString = #function
) -> Bool {
guard surfaceResizeAuthority?.isRendererResizeDeferred != true else { return false }
guard let surface = liveSurfaceForGhosttyAccess(reason: "updateSize") else { return false }
_ = layerScale

Expand Down Expand Up @@ -378,16 +370,19 @@ extension TerminalSurface {
}
}
}

if fittedSize.fontChanged && !sizeChanged {
ghostty_surface_refresh(surface)
}

// Deferred from above on a DPI increase: now that set_size grew the grid,
// applying the larger cell only shrinks it back to the final width.
if deferScaleUntilResized {
ghostty_surface_set_content_scale(surface, xScale, yScale)
lastXScale = xScale
lastYScale = yScale
}

// Remote tmux display surfaces: report every APPLIED resize —
// including same-grid re-applies, since a resize that lands on new
// pixels without changing cols×rows still refines the measured
Expand Down Expand Up @@ -425,9 +420,11 @@ extension TerminalSurface {
manualSizeReportPendingWindowAttach = true
}
}

// Let Ghostty continue rendering on its own wakeups for steady-state frames.
return true
}

/// The current monospace cell size in points, or nil if the runtime
/// surface is not ready. Used by remote tmux mirror sizing.
@MainActor
Expand All @@ -441,6 +438,7 @@ extension TerminalSurface {
height: Double(size.cell_height_px) / scale
)
}

/// Raw sizing sample for calibration diagnostics: `ghostty_surface_size`'s
/// device-pixel fields UNCONVERTED, plus the attached view's bounds in
/// points and its window's backing scale. Callers separate view layout,
Expand All @@ -462,6 +460,7 @@ extension TerminalSurface {
backingScale: attachedView?.window?.backingScaleFactor
)
}

/// Delivers the manual-size report that was skipped because the view was
/// outside any window when the size applied (see
/// ``manualSizeReportPendingWindowAttach``). Called from the attach path;
Expand All @@ -478,6 +477,7 @@ extension TerminalSurface {
manualSizeReportPendingWindowAttach = false
report(sample)
}

/// Which of ``renderedGridCells()``'s nil conditions currently hold —
/// lets sizing diagnostics name the mechanism (view detached from its
/// window vs surface not live vs no real grid) instead of a bare nil.
Expand All @@ -488,6 +488,7 @@ extension TerminalSurface {
surfaceLive: liveSurfaceForGhosttyAccess(reason: "renderedGridDiagnostics") != nil
)
}

/// The on-screen rendered grid, or nil while the runtime surface is not
/// live, is not in a window, or has no real grid yet.
@MainActor
Expand All @@ -500,4 +501,5 @@ extension TerminalSurface {
guard cols > 1, rows > 1 else { return nil }
return (cols, rows)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,6 @@ public final class TerminalSurface: Identifiable, ObservableObject {
/// the pinned grid and clips or letterboxes the difference — the same
/// answer tmux gives a client whose size disagrees with the window.
var assignedGrid: (columns: Int, rows: Int)?
@MainActor weak var surfaceResizeAuthority: (any TerminalSurfaceResizeAuthority)?
/// Temporary runtime font-size ownership while a mobile viewport is fitted.
var mobileViewportFontFitState: MobileViewportFontFitState?
// Debug metadata is read from debug/CLI paths off the main thread; the
Expand Down Expand Up @@ -839,6 +838,7 @@ extension TerminalSurface: TerminalSurfacing {}
/// exclusively owned by the request from creation until `close()` runs.
private struct TerminalSurfaceHeadlessWindowCloseRequest: @unchecked Sendable {
let window: NSWindow

@MainActor
func close() {
window.contentView = nil
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading