Start workspace command process before workspace is opened

This commit is contained in:
Lawrence Chen 2026-02-21 05:06:29 -08:00
parent 9653113920
commit 645c7f76ea
3 changed files with 36 additions and 5 deletions

View file

@ -1135,6 +1135,7 @@ final class TerminalSurface: Identifiable, ObservableObject {
private var pendingTextQueue: [Data] = []
private var pendingTextBytes: Int = 0
private let maxPendingTextBytes = 1_048_576
private var backgroundSurfaceStartQueued = false
@Published var searchState: SearchState? = nil {
didSet {
if let searchState {
@ -1616,6 +1617,35 @@ final class TerminalSurface: Identifiable, ObservableObject {
writeTextData(data, to: surface)
}
func requestBackgroundSurfaceStartIfNeeded() {
if !Thread.isMainThread {
DispatchQueue.main.async { [weak self] in
self?.requestBackgroundSurfaceStartIfNeeded()
}
return
}
guard surface == nil, attachedView != nil else { return }
guard !backgroundSurfaceStartQueued else { return }
backgroundSurfaceStartQueued = true
DispatchQueue.main.async { [weak self] in
guard let self else { return }
self.backgroundSurfaceStartQueued = false
guard self.surface == nil, let view = self.attachedView else { return }
#if DEBUG
let startedAt = ProcessInfo.processInfo.systemUptime
#endif
self.createSurface(for: view)
#if DEBUG
let elapsedMs = (ProcessInfo.processInfo.systemUptime - startedAt) * 1000.0
dlog(
"surface.background_start surface=\(self.id.uuidString.prefix(8)) inWindow=\(view.window != nil ? 1 : 0) ready=\(self.surface != nil ? 1 : 0) ms=\(String(format: "%.2f", elapsedMs))"
)
#endif
}
}
private func writeTextData(_ data: Data, to surface: ghostty_surface_t) {
data.withUnsafeBytes { rawBuffer in
guard let baseAddress = rawBuffer.baseAddress?.assumingMemoryBound(to: CChar.self) else { return }

View file

@ -3165,6 +3165,7 @@ class TerminalController {
} else {
// Avoid blocking the main actor waiting for view/surface attachment.
terminalPanel.sendText(text)
terminalPanel.surface.requestBackgroundSurfaceStartIfNeeded()
queued = true
}
#if DEBUG
@ -9981,6 +9982,7 @@ class TerminalController {
sendSocketText(unescaped, surface: surface)
} else {
terminalPanel.sendText(unescaped)
terminalPanel.surface.requestBackgroundSurfaceStartIfNeeded()
}
success = true
}
@ -10009,6 +10011,7 @@ class TerminalController {
sendSocketText(unescaped, surface: surface)
} else {
terminalPanel.sendText(unescaped)
terminalPanel.surface.requestBackgroundSurfaceStartIfNeeded()
}
success = true
}

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Regression: `new-workspace --command` must not block/fail before surface attach."""
"""Regression: `new-workspace --command` should execute without selecting the workspace."""
from __future__ import annotations
@ -89,9 +89,6 @@ def main() -> int:
# Creation with --command should not steal focus.
_must(c.current_workspace() == baseline_ws_id, "new-workspace --command should preserve selected workspace")
# Selecting the created workspace should attach/create the surface and flush queued input.
c.select_workspace(created_ws_id)
observed = ""
deadline = time.time() + 12.0
while time.time() < deadline:
@ -106,6 +103,7 @@ def main() -> int:
_must(marker.exists(), f"Command marker file was not created: {marker}")
_must(observed == token, f"Queued command did not execute as expected: expected={token!r} observed={observed!r}")
_must(c.current_workspace() == baseline_ws_id, "Command execution should not switch selected workspace")
finally:
if created_ws_id:
try:
@ -118,7 +116,7 @@ def main() -> int:
except OSError:
pass
print("PASS: new-workspace --command queues input until surface attach and returns without blocking")
print("PASS: new-workspace --command executes without opening the created workspace")
return 0