From 842ec6c00a12075b28d85c377acb65a5322f99ac Mon Sep 17 00:00:00 2001 From: supenom94 Date: Tue, 10 Mar 2026 09:36:23 +0900 Subject: [PATCH] fix: resolve font height compression when keyboard appears MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Metal renderer used view.bounds for viewport calculation in draw(), but bounds can lag behind the drawable size during animated resizes (e.g. keyboard appearance). This caused the vertex shader to map content using stale dimensions, compressing font height vertically. Cache viewport size from drawableSizeWillChange (derived from drawable) and add the missing setNeedsDisplay() call to trigger immediate redraw on resize — matching Apple's standard Metal on-demand rendering pattern. Co-Authored-By: Claude Opus 4.6 --- ios/Muxi/Terminal/TerminalRenderer.swift | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/ios/Muxi/Terminal/TerminalRenderer.swift b/ios/Muxi/Terminal/TerminalRenderer.swift index e0f08ff..765e58e 100644 --- a/ios/Muxi/Terminal/TerminalRenderer.swift +++ b/ios/Muxi/Terminal/TerminalRenderer.swift @@ -84,6 +84,12 @@ final class TerminalRenderer: NSObject, MTKViewDelegate { var buffer: TerminalBuffer? var needsRedraw: Bool = true + /// Cached viewport size in points, derived from the drawable size. + /// Updated in `drawableSizeWillChange` to guarantee it matches the + /// actual rendering target — unlike `view.bounds`, which can lag + /// behind the drawable during animated resizes (e.g. keyboard). + private var cachedViewportSize: SIMD2 = .zero + // MARK: - Scrollback /// When set, the renderer reads from this buffer instead of the live buffer. @@ -495,11 +501,18 @@ final class TerminalRenderer: NSObject, MTKViewDelegate { // MARK: - MTKViewDelegate func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { + let scale = view.contentScaleFactor + cachedViewportSize = SIMD2( + Float(size.width / scale), + Float(size.height / scale) + ) needsRedraw = true + view.setNeedsDisplay() } func draw(in view: MTKView) { guard let pipelineState, + cachedViewportSize.x > 0, cachedViewportSize.y > 0, let drawable = view.currentDrawable, let renderPassDesc = view.currentRenderPassDescriptor, let commandBuffer = commandQueue.makeCommandBuffer(), @@ -517,12 +530,7 @@ final class TerminalRenderer: NSObject, MTKViewDelegate { needsRedraw = false } - // Use bounds (points) not drawableSize (pixels) because vertex - // positions are computed in point coordinates (col * cellWidth). - var viewportSize = SIMD2( - Float(view.bounds.width), - Float(view.bounds.height) - ) + var viewportSize = cachedViewportSize encoder.setRenderPipelineState(pipelineState)