Repository navigation
Merge upstream Ghostty 1.4.0 and audit Windows parity - #18
Merged
Merged
Conversation
Also clamp keyboard split resizes to the split size, which fixed an assertion failure when resize_split moved past the edge of a split. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Zig 0.17 port replaced the absolute path to the executable in the desktop file, D-Bus services and systemd user service with a bare `ghostty`, since the install prefix is no longer known while the build is configured. systemd resolves a bare ExecStart= name against a fixed search path rather than PATH: /usr/bin and /usr/local/bin on most systems, and only systemd's own directory on NixOS. So the service failed to start for any install outside those directories, including every Nix one. -Dinstalled-exe-path gives the absolute path to write into those files. Without it they still name the executable alone, which is right for packages installing to /usr. The Nix package passes its output path, and the Flatpak manifests pass /app/bin/ghostty, which is what they produced before the port.
Run `systemd-analyze verify` on the systemd user service, and check that every Exec= and TryExec= in the D-Bus service and desktop file is an absolute path to an executable, so a build that stops passing -Dinstalled-exe-path fails instead of shipping a service systemd can't start. The verifier starts a user manager, which needs a writable runtime directory that the sandbox doesn't have, so it gets one under $TMPDIR.
While a chunked Kitty graphics load was in progress, every transmit or animation frame command was treated as its next chunk, regardless of its transmission medium. A file (`t=f`), temporary file (`t=t`), or shared memory (`t=s`) command arriving mid-load had its encoded path appended to the partial image as pixel data. This diverged from Kitty. The spec only defines chunking for direct data, and continuation chunks must carry only the `m` and `q` keys, so a command with another medium can never be a continuation. Kitty abandons the in-progress load and handles the command as a new transmission, for both image and animation frame loads. A client that interrupts a load this way now gets the image or frame it asked for instead of a corrupted or failed one. `execute` now destroys the in-progress load before dispatching any non-direct transmit or frame command, so the command is handled as a fresh transmission, including its own `q` setting.
ECMA-48 says a control string that is cancelled or aborted is thrown away. xterm only dispatches a control string on ST, and Kitty only ends an APC on ST or BEL, so neither runs the command. https://ecma-international.org/publications-and-standards/standards/ecma-48/
…hostty-org#14811) While a chunked Kitty graphics load was in progress, every transmit or animation frame command was treated as its next chunk, regardless of its transmission medium. A file (`t=f`), temporary file (`t=t`), or shared memory (`t=s`) command arriving mid-load had its encoded path appended to the partial image as pixel data. This diverged from Kitty. The spec only defines chunking for direct data, and continuation chunks must carry only the `m` and `q` keys, so a command with another medium can never be a continuation. Kitty abandons the in-progress load and handles the command as a new transmission, for both image and animation frame loads. A client that interrupts a load this way now gets the image or frame it asked for instead of a corrupted or failed one. `execute` now destroys the in-progress load before dispatching any non-direct transmit or frame command, so the command is handled as a fresh transmission, including its own `q` setting.
ECMA-48 says a control string that is cancelled or aborted is thrown away. xterm only dispatches a control string on ST, and Kitty only ends an APC on ST or BEL, so neither runs the command. https://ecma-international.org/publications-and-standards/standards/ecma-48/
A stream continuation that ended after an 8-bit C1 introducer had aborted an APC could not be exported. For example, `ESC _ data 0x9B` ends the APC and starts a CSI, but the tracker only treats ESC as the start of a new sequence, so it kept the aborted APC. Replaying that would end the APC a second time, and validation rejected it. Export now starts at the last C1 introducer that moved the parser into a new sequence and writes it in its 7-bit ESC form.
…-org#14806) The Zig 0.17 port replaced the absolute path to the executable in the desktop file, D-Bus services and systemd user service with a bare `ghostty`, since the install prefix is no longer known while the build is configured. systemd resolves a bare ExecStart= name against a fixed search path rather than PATH: /usr/bin and /usr/local/bin on most systems, and only systemd's own directory on NixOS. So the service failed to start for any install outside those directories, including every Nix one. -Dinstalled-exe-path gives the absolute path to write into those files. Without it they still name the executable alone, which is right for packages installing to /usr. The Nix package passes its output path, and the Flatpak manifests pass /app/bin/ghostty, which is what they produced before the port. Fixes ghostty-org#14805 AI disclosure: Claude Code was used in the preparation of this PR.
…tty-org#14814) A stream continuation that ended after an 8-bit C1 introducer had aborted an APC could not be exported. For example, `ESC _ data 0x9B` ends the APC and starts a CSI, but the tracker only treats ESC as the start of a new sequence, so it kept the aborted APC. Replaying that would end the APC a second time, and validation rejected it. Export now starts at the last C1 introducer that moved the parser into a new sequence and writes it in its 7-bit ESC form.
…`ghostty_osc_free` Signed-off-by: Uzair Aftab <git@uzaaft.me> Change-Id: I4efdf6a51f568b4bc2678ef4a6aa1c106a6a6964
…`ghostty_osc_free` (ghostty-org#14818)
Triggered by [discussion comment](ghostty-org#14822 (comment)) from @jcollie. Vouch: @AlJohri Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Implement the kitty_read, kitty_write, and list (paste event) requests in the GTK apprt on top of the existing core protocol support, and wire the confirmation dialog up to Kitty requests, including session-grant remember support. Also fix two adjacent issues found while testing: the clipboard-write signal now carries a "cleared" flag so image-only writes toast as copies instead of clears, and a failed OSC 52 text read now answers with an empty reply instead of leaving the client waiting forever. TODO: the new remember-row strings in the confirmation dialog are deliberately not marked for translation; wrap them in i18n._() and regenerate the translation files once they should be translated.
Decode the first image/* representation of a Kitty clipboard request with gdk_texture_new_from_bytes and show it in the dialog in place of the text preview, falling back to the text preview when there is no decodable image. The picture's paintable and the visible preview page are bound declaratively to the clipboard-image property.
Remembering the denial set clipboard-read to deny before the request was answered, and the OSC 52 reply is written by the same path that serves an allowed read, which asserts reads aren't denied.
A multipart payload was reduced to one preview — the first decodable image, else the first text, else a bare list of MIME types — so the user authorized data they were never shown. The dialog now gives each representation its own page, named by MIME type.
The script exited as soon as it had written the transaction, so the terminal's status packet arrived with nothing left to read it and printed itself on the next shell prompt. It also carries a name and a session password now, so a run exercises the permission prompt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Erasing scrollback (ED3) moved Kitty image placements anchored in the erased rows onto the top-left of the active area, where they became visible again until the next screen clear. PageList.eraseRows moves tracked pins in erased rows to the top-left of the retained rows without marking them garbage, so the image storage never noticed the placement had lost its row. Remove pin-backed placements in the erased history range (and any relative placements orphaned by that) before erasing the rows, while their pins still identify them. The PageList pin semantics are left unchanged since search relies on erased pins not being garbage. Fixes: ghostty-org#14831
Erasing scrollback (ED3) moved Kitty image placements anchored in the erased rows onto the top-left of the active area, where they became visible again until the next screen clear. PageList.eraseRows moves tracked pins in erased rows to the top-left of the retained rows without marking them garbage, so the image storage never noticed the placement had lost its row. Remove pin-backed placements in the erased history range (and any relative placements orphaned by that) before erasing the rows, while their pins still identify them. The PageList pin semantics are left unchanged since search relies on erased pins not being garbage. Fixes: ghostty-org#14831 AI disclosure: Claude Code was used in the preparation of this PR.
StreamHandler.changeConfig queued a color_scheme_report message into the termio mailbox. changeConfig runs on the io thread, which is the only reader of that mailbox, so when the mailbox was full (for example, from a burst of query replies queued by the reader thread) the io thread blocked forever pushing to itself. Every other thread then blocked on its next send to the same mailbox, freezing Ghostty on a config reload. Write the report from Termio.changeConfig instead, using the same colorSchemeReportLocked the message handler uses. The report still follows the config update in order with other output. Fixes: ghostty-org#14833
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes a regression of ghostty-org#1297 on GTK. **Issue** Splits can be dragged or resized down to 0px, which just looks like a thick divider. The 10px minimum from ghostty-org#1323 was lost in the GTK rewrite. **Fix** Splits are now at least one cell plus padding in size, and the divider can't be dragged past that. This also clamps keyboard resizes. Tested on Fedora 44. Dragging and `resize_split` stop at one column or line. I believe that macOS already has its own minimum and is unchanged. First pass written with Claude Code (Claude Opus 5.5), reviewed and reprompted by me.
Triggered by [discussion comment](ghostty-org#14844 (comment)) from @jcollie. Denounce: @ifmael Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…hostty-org#14859) The zsh integration reported the working directory with `print`, which expands backslash escapes in every argument, including `$PWD`. A directory named `x\a\e]52;c;SGVsbG8=\a` ended our OSC 7 early and sent a real OSC 52 sequence. A directory name containing a raw ESC or BEL byte did the same thing in both zsh and bash. zsh now uses `print -r` so backslashes in the path are printed as-is, and writes the ESC and BEL framing bytes with `$'...'` quoting. Both zsh and bash strip control bytes from the hostname and directory before sending them, the same way the zsh title code already does. Fish was already safe because it percent-encodes the path.
- expose read-write `name override` property on tab and terminal classes in Ghostty.sdef
- implement `titleOverride` accessors in `ScriptTab` and `ScriptTerminal`
- add `titleOverride` property to `SurfaceView` to manage manual terminal title overrides
- fix minor inconsistencies in comments
AppleScript API usage:
```applescript
-- Setting and clearing a tab name override via AppleScript
tell application "Ghostty"
-- Target the selected tab of the front window
set targetTab to selected tab of front window
-- Set name override
set name override of targetTab to "My Custom Tab Title"
log "Tab title: " & (name of targetTab)
log "Tab override: " & (name override of targetTab)
delay 2.0 -- delay is here only for illustrative purposes
-- Clear override
set name override of targetTab to ""
end tell
```
AI disclosure: Antigravity CLI was used for the first draft. Iterated, minimised, reviewed, and tested by me.
Closes: ghostty-org#12048
Discussion: ghostty-org#12047
Co-Authored-By: Gemini 4 Argon (Medium)
Co-Authored-By: Gemini 3.8 Flash (Medium)
Co-Authored-By: Antigravity CLI 1.3.5
Agent-Session: cdd11bbe-928a-4a00-a085-c8f87a57966f
Signed-Off-By: Paal Øye-Strømme <paal.o.eye@gmail.com>
When closing sibling splits down to a single terminal leaf while zoomed via AppleScript, `SplitTree` retained its zoomed node reference because the target being removed was not the zoomed node itself. Because the tree was no longer split but the zoomed property remained non-nil, the window's zoom state stayed active and the reset zoom indicator remained visible. `SplitTree` now validates that a tree can only have a zoomed node if it actually contains splits and the zoomed node exists in root. In addition, `SplitTree` exposes an `isZoomed` property, and the terminal controller and window reactively update the zoom state and accessory controls accordingly. AI disclosure: Antigravity CLI wrote the tests initially. Iterated, reviewed, and tested by me. Co-Authored-By: Gemini 3.8 Flash (Medium) <gemini-code-assist@google.com> Signed-Off-By: Paal Øye-Strømme <paal.o.eye@gmail.com>
…g#14733) - expose read-write `name override` property on tab and terminal classes in Ghostty.sdef - implement `titleOverride` accessors in `ScriptTab` and `ScriptTerminal` - add `titleOverride` property to `SurfaceView` to manage manual terminal title overrides - fix minor inconsistencies in comments AppleScript API usage: ```applescript -- Setting and clearing a tab name override via AppleScript tell application "Ghostty" -- Target the selected tab of the front window set targetTab to selected tab of front window -- Set name override set name override of targetTab to "My Custom Tab Title" log "Tab title: " & (name of targetTab) log "Tab override: " & (name override of targetTab) delay 2.0 -- delay is here only for illustrative purposes -- Clear override set name override of targetTab to "" end tell ``` AI disclosure: Antigravity CLI was used for the first draft. Iterated, minimised, reviewed, and tested by me. Closes: ghostty-org#12048 Discussion: ghostty-org#12047
…#14703) When closing sibling splits down to a single terminal leaf while zoomed via AppleScript, `SplitTree` retained its zoomed node reference because the target being removed was not the zoomed node itself. Because the tree was no longer split but the zoomed property remained non-nil, the window's zoom state stayed active and the reset zoom indicator remained visible. `SplitTree` now validates that a tree can only have a zoomed node if it actually contains splits and the zoomed node exists in root. In addition, `SplitTree` exposes an `isZoomed` property, and the terminal controller and window reactively update the zoom state and accessory controls accordingly. AI disclosure: Antigravity CLI wrote the tests initially. Iterated, reviewed, and tested by me. <details> <summary>UX before:</summary> <video src="https://github.com/user-attachments/assets/263557d1-1be8-41ca-9070-85075c659afb" width="100%"></video> </details> <details> <summary>UX after:</summary> <video src="https://github.com/user-attachments/assets/55ba6778-0901-4722-aa51-8ea0b0c83a1c" width="100%"></video> </details> Minimal reproducible example (MRE) using `AppleScript`: ```applescript tell application id "com.mitchellh.ghostty" activate -- Get the current focused terminal set t1 to focused terminal of selected tab of front window -- Create 4 splits (2x2 grid) -- [ t1 | t2 ] -- [ t3 | t4 ] set t2 to split t1 direction right delay 0.5 set t3 to split t1 direction down delay 0.5 set t4 to split t2 direction down delay 0.5 -- Zoom one of the splits (t1) perform action "toggle_split_zoom" on t1 delay 0.5 -- Close other splits try close t4 on error perform action "close_surface" on t4 end try delay 0.2 try close t3 on error perform action "close_surface" on t3 end try delay 0.2 try close t2 on error perform action "close_surface" on t2 end try end tell ```
Co-authored-by: OshDubh <60195526+OshDubh@users.noreply.github.com>
This adds support for FreeBSD to libghostty-vt and validates it in CI. There were only a few places we really need to make compatibility fixes: - The memory decommit/recommit stuff, which is very OS specific. - Kitty graphics shared memory paths - TinyIO, one method
Picked and amended from ghostty-org#14868
Triggered by [discussion comment](ghostty-org#14877 (comment)) from @jcollie. Vouch: @rtgibbons Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Integrate upstream release 83fb956 while retaining the native Windows runtime, text-only clipboard mode gate, cache maintenance, and disabled upstream publishing workflows.
Preserve clipboard ownership and allocation bounds, resolve surfaces after modal close confirmation, discard aborted application APC commands, sanitize PowerShell OSC payloads, and adapt native OpenSSH output and terminfo arguments. Add focused regressions without desktop-global input.
Recognize cursor:blink and cursor:steady from setupFeatures and verify prompt/Enter output with actual feature strings under PowerShell 5.1 and 7 without accepting input.
Require clean annotated Windows tags for production packages, compare executable and PE versions, reject missing resources, and validate the staged portable layout. Add package regression tests and Windows CI payload checks under PowerShell 5.1 and 7.
Publish top-level show/hide transitions, keep hidden layouts occluded, and preserve zoomed-out pane visibility during restore. Add a no-global-input integration regression for mode 2033 across normal and quick-terminal window states.
Document the exact upstream release baseline, tested Windows fixes, confirmed common GUI and shell gaps, and distinct platform-specific roadmap work. Hold 1.4 tagging and publication until full feature parity is implemented and verified.
Give fixture builds and helper-launched builds the same disposable local cache even when setup-zig exports ZIG_LOCAL_CACHE_DIR. Verify the maintenance suite with an inherited CI-style cache override.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Integrate upstream Ghostty v1.4.0 (
83fb95624, 73 commits after our previous sync) while preserving the Win32 runtime, WGL/ConPTY adaptations, cache helpers, and disabled upstream publishing workflows.Fix Windows clipboard ownership and bounded reads, close-dialog surface lifetime, application APC cancellation, PowerShell OSC sanitization and cursor features, native OpenSSH CRLF parsing/options, and hidden-window/split-zoom visibility. Harden portable packaging with complete resource and executable/PE-version verification.
The shared core is aligned; full native feature parity is not achieved. README/ROADMAP record the confirmed clipboard, inspector, split movement, navigation, state-indicator, bell, inactive-pane, and PowerShell integration gaps separately from platform-specific roadmap commitments. Hold win-v1.4.0 tagging and publication until full parity is implemented and verified.
Validation:
This PR merges the upstream baseline and audited fixes; it does not authorize a 1.4 release or claim UI parity.