Commit Graph

17507 Commits

Author SHA1 Message Date
Mitchell Hashimoto
719def70f3 macOS: update default behaviour of KeyboardLayout.character(for:modifiers:) (#14009)
Follow up for #13888, and prepare for #13205.

The comments are copied from the history commit.

## AI Disclosure

The tests are updated by Claude, I cherrypicked them.
2026-08-25 05:41:01 -07:00
Lukas
f1b9efed80 macOS: update default behaviour of KeyboardLayout.character(for:modifiers:) 2026-08-25 13:56:21 +02:00
Mitchell Hashimoto
8867c37c55 terminal: update Kitty clipboard text input validation to spec (#14005)
Validate decoded OSC 5522 metadata, read MIME lists, and alias lists as
UTF-8. Treat an alias without a target MIME type as an invalid write
packet.

Malformed write packets now return EINVAL and terminate the in-flight
transaction instead of leaving it active. Malformed reads are dropped
without disturbing an active write.

Latest changes upstream to spec:

458421af46
2026-08-24 21:33:57 -07:00
Mitchell Hashimoto
4888c0a02c terminal: reject oversized Kitty clipboard writes (#14004)
Update OSC 5522 writes to reject every transaction that exceeds the
configured decoded-data limit. The previous behavior truncated text
while rejecting only non-text data.

Programs now receive EFBIG as soon as a write crosses the limit. The
clipboard remains untouched, and remaining write packets are ignored
until a new transaction begins. Raise the default to the protocol
minimum of 64 MiB.

This applies the latest spec change:

32ea104192
2026-08-24 21:25:29 -07:00
Mitchell Hashimoto
e8d8945b53 terminal: update Kitty clipboard text input validation to spec
Validate decoded OSC 5522 metadata, read MIME lists, and alias
lists as UTF-8. Treat an alias without a target MIME type as an
invalid write packet.

Malformed write packets now return EINVAL and terminate the in-flight
transaction instead of leaving it active. Malformed reads are dropped
without disturbing an active write.

Latest changes upstream to spec:
458421af46
2026-08-24 21:25:06 -07:00
Mitchell Hashimoto
70f0065759 terminal: reject oversized Kitty clipboard writes
Update OSC 5522 writes to reject every transaction that exceeds the
configured decoded-data limit. The previous behavior truncated text
while rejecting only non-text data.

Programs now receive EFBIG as soon as a write crosses the limit. The
clipboard remains untouched, and remaining write packets are ignored
until a new transaction begins. Raise the default to the protocol
minimum of 64 MiB.

This applies the latest spec change:
32ea104192
2026-08-24 21:14:36 -07:00
Mitchell Hashimoto
600a86dcfd terminal: make Kitty clipboard write limit configurable (#14002)
Add a new `clipboard-write-limit-bytes` option (similar to
`scrollback-limit-bytes`) to limit the maximum OSC 5522 write size.
Defaults to 32 MB.

This also adds a new `GHOSTTY_TERMINAL_OPT_CLIPBOARD_WRITE_MAX_BYTES`
option for libghostty-vt embedders to control the same.

Kitty has a limit too and it works by truncating all data. I decided on
purpose to diverge from this because I don't think truncated binary data
is useful. Instead, we reject it so the application knows the write
didn't work.

We truncate text data, and we try to do it at the nearest complete UTF-8
sequence (if possible).

For the future: Kitty spools any write data more than some size (can't
remember) to a temp file on disk. We might want to consider doing
something similar since we're all in-memory at the moment. This PR
doesn't change that.
2026-08-24 13:55:29 -07:00
Mitchell Hashimoto
75606a6900 terminal: exempt Kitty clipboard listing reads from permission prompts (#14001)
A Kitty clipboard protocol (OSC 5522) read that only requests the
targets type ('.') is now served without a permission prompt and never
consults (or consumes) session password grants.

The spec requires this so that a client listing the available data types
before reading one doesn't present the user with a double permission
prompt.
2026-08-24 13:35:44 -07:00
Mitchell Hashimoto
5350d4a5f5 terminal: make Kitty clipboard write limit configurable
Add a new `clipboard-write-limit-bytes` option (similar to 
`scrollback-limit-bytes`) to limit the maximum OSC 5522 write size.
Defaults to 32 MB.

This also adds a new `GHOSTTY_TERMINAL_OPT_CLIPBOARD_WRITE_MAX_BYTES`
option for libghostty-vt embedders to control the same.

Kitty has a limit too and it works by truncating all data. I decided on
purpose to diverge from this because I don't think truncated binary data
is useful. Instead, we reject it so the application knows the write
didn't work.

We truncate text data, and we try to do it at the nearest complete UTF-8
sequence (if possible).
2026-08-24 13:34:46 -07:00
Mitchell Hashimoto
13b9857a25 macos: restore paste semantics for dropped text (#13999)
Discussion #13979

Dropped paths and text once again honor bracketed paste mode. IME,
dictation, emoji picker, and character viewer commits remain typed
input.

sendText calls ghostty_surface_text, which applies the clipboard paste
pipeline and bracketed paste framing when enabled. Separating the paths
at the drag-and-drop caller preserves the input-method behavior
introduced by #13817.
2026-08-24 13:25:53 -07:00
Mitchell Hashimoto
4f4da7657b macos: answer ENOSYS for Kitty clipboard writes to primary (#14000)
A Kitty clipboard protocol (OSC 5522) write transaction targeting
`loc=primary` replied `type=write:status=DONE` in the macOS app even
though macOS has no primary selection and the data was silently
discarded.

The spec requires ENOSYS when the requested location is not available on
the system, which the read path already answers correctly:
https://sw.kovidgoyal.net/kitty/clipboard/
2026-08-24 13:25:40 -07:00
Mitchell Hashimoto
928c7f0e79 terminal: exempt Kitty clipboard listing reads from permission prompts
A Kitty clipboard protocol (OSC 5522) read that only requests the
targets type ('.') is now served without a permission prompt and never
consults (or consumes) session password grants. 

The spec requires this so that a client listing the available data types 
before reading one doesn't present the user with a double permission prompt.
2026-08-24 13:25:12 -07:00
Mitchell Hashimoto
1334cc213e macos: answer ENOSYS for Kitty clipboard writes to primary
A Kitty clipboard protocol (OSC 5522) write transaction targeting
`loc=primary` replied `type=write:status=DONE` in the macOS app even
though macOS has no primary selection and the data was silently
discarded. 

The spec requires ENOSYS when the requested location is not
available on the system, which the read path already answers correctly:
https://sw.kovidgoyal.net/kitty/clipboard/
2026-08-24 13:11:23 -07:00
Mitchell Hashimoto
550151882a macos: restore paste semantics for dropped text
Discussion #13979

Dropped paths and text once again honor bracketed paste mode.
IME, dictation, emoji picker, and character viewer commits remain typed input.

sendText calls ghostty_surface_text, which applies the clipboard paste
pipeline and bracketed paste framing when enabled. Separating the
paths at the drag-and-drop caller preserves the input-method behavior
introduced by #13817.
2026-08-24 12:49:42 -07:00
Mitchell Hashimoto
89d17b378e macos: implement Kitty clipboard protocol writes (#13998)
Programs can now write the system clipboard through the Kitty clipboard
protocol in the macOS app. This also does all the hard work plumbing
through core termio/apprt so GTK should be an easy follow.

This functionality lets clients copy arbitrary representations (images,
HTML, etc.) into the clipboard. Writes honor `clipboard-write`: allow
applies silently, deny answers EPERM up front before any data is used,
and ask shows the standard confirmation prompt.

After this, I believe the core and macOS have 100% Kitty clipboard
implementation but I'll double check after this.

## Demo



https://github.com/user-attachments/assets/71234fa0-f539-48eb-a633-8dea3addddd5
2026-08-24 12:32:02 -07:00
Mitchell Hashimoto
25c61e852f macos: implement Kitty clipboard protocol writes
Programs can now write the system clipboard through the Kitty
clipboard protocol in the macOS app. This also does all the hard work
plumbing through core termio/apprt so GTK should be an easy follow.

This functionality lets clients copy arbitrary representations (images, 
HTML, etc.) into the clipboard. Writes honor `clipboard-write`: allow 
applies silently, deny answers EPERM up front before any data is used, 
and ask shows the standard confirmation prompt.
2026-08-24 12:18:46 -07:00
Mitchell Hashimoto
7c49e723a3 terminal: fix stale cursor style/hyperlink state after scroll clear (#13997)
Clearing the screen into scrollback and then printing could crash debug
builds with a page integrity violation, or silently corrupt
style/hyperlink reference counts in release builds. Found in #13991 via
fuzzing.

The cursor's style and hyperlink IDs are only valid on the page the
cursor is on. When the scroll clear moved the start of the fresh screen
onto a new page, the reset path in cursorReload updated the cursor's
position directly instead of going through cursorChangePin, so the
cursor kept IDs from its old page. On the new page those IDs pointed at
entries that were dead or belonged to something else, and the next print
used them.

Fix this by making the reset path go through `cursorChangePin` like
every other cross-page cursor move, which releases the style and
hyperlink from the old page and recreates them on the new one.
2026-08-24 12:15:09 -07:00
Mitchell Hashimoto
9313d580c6 terminal: fix stale cursor style/hyperlink state after scroll clear
Clearing the screen into scrollback and then printing could crash debug 
builds with a page integrity violation, or silently corrupt style/hyperlink
reference counts in release builds. Found in #13991 via fuzzing.

The cursor's style and hyperlink IDs are only valid on the page the
cursor is on. When the scroll clear moved the start of the fresh
screen onto a new page, the reset path in cursorReload updated the
cursor's position directly instead of going through cursorChangePin,
so the cursor kept IDs from its old page. On the new page those IDs
pointed at entries that were dead or belonged to something else, and
the next print used them.

Fix this by making the reset path go through `cursorChangePin` like
every other cross-page cursor move, which releases the style and
hyperlink from the old page and recreates them on the new one.
2026-08-24 12:05:01 -07:00
Mitchell Hashimoto
c8554f28e0 macOS: enable mode 5522 paste events (#13995)
Advertise Kitty clipboard protocol mode 5522 on macOS and route
clipboard paste requests through the protocol when it is enabled.
2026-08-24 09:52:17 -07:00
Mitchell Hashimoto
1dcf4eb2df renderer/image: Fuse copying data and converting pixel format (#13987)
Profiling `mpv --vo=kitty --vo-kitty-use-shm <video>` shows up a copy
and then swizzle in `prepImage`
This comes from the renderer copying the raw image data for ownership,
then doing an rgb to rgba conversion to replace the copied data.
This change optimize this case by letting the format conversion read
from the data source instead of a copy of it.

<img width="3825" height="1579" alt="image"
src="https://github.com/user-attachments/assets/25851c04-b582-4bad-8f8d-930448d89fa2"
/>
<img width="3825" height="1579" alt="image"
src="https://github.com/user-attachments/assets/fbb1ca73-a86f-421b-992d-a764ce08c83e"
/>
> Above-Before: prepImage profiles a memcpy + swizzle
> Below-After: prepImage profiles just a swizzle


The existing data path for kitty images is:
```

Read tty for Kitty image transmission (srgb, srgba, or PNG bytes)
-> copy into Kitty graphics ImageStorage (cpu-owned)

Renderer updateFrame creates Image.Pending in renderer-owned CPU storage
-> sync Kitty ImageStorage with renderer-owned ImageMap
-> copy bytes into renderer.ImageMap (renderer-owned) 
-> convert ImageMap bytes to preferred GPU upload format

Renderer drawFrame uploads image data to the GPU
-> iterate through renderer.ImageMap
  -> for Pending image uploads
    -> convert the pixel format (no-op if already done), create the GPU-side texture and upload the data
```

# Note
Kitty graphics only supports RGB and RGBA data
The image file decode path uses a wuffs png and jpeg decode function
configured to return RGBA 8-bit, so I think in practice we only ever
upload RGB8 or RGBA8. And the gray-alpha and gray pixel formats aren't
ever used.


# AI Disclosure
I didn't use any LLM assistance for this.
2026-08-24 09:50:00 -07:00
Mitchell Hashimoto
c2c0db68aa macOS: enable mode 5522 paste events
Advertise Kitty clipboard protocol mode 5522 on macOS and route
clipboard paste requests through the protocol when it is enabled.
2026-08-24 09:37:57 -07:00
Mitchell Hashimoto
53d1b28ad3 docs: reformatting for help book support (#13994) 2026-08-24 09:09:12 -07:00
Lukas
88dc6f9723 docs: reformatting for help book support 2026-08-24 18:01:32 +02:00
Mitchell Hashimoto
75d657788a macOS: Kitty clipboard read support (#13993)
This adds Kitty clipboard protocol _read_ support to macOS. In the
process, this also does most of the core termio, apprt, and Surface work
so GTK is likely very easy to do, I just didn't have the machine on hand
to test at the given moment. I will create an issue to follow up with
that.

This fully supports:

- Non-text data, like images! For this, we show an image preview.
- Per-program "remember"
- Showing the program name if given instead of generic "An application"

<img width="1848" height="996" alt="CleanShot 2026-08-24 at 08 37 45@2x"
src="https://github.com/user-attachments/assets/549d9031-2e98-46bf-90d4-94171b255c42"
/>
2026-08-24 09:00:58 -07:00
Mitchell Hashimoto
9f2aa93e82 libghostty: Kitty clipboard write permission prompts and grants (#13992)
The `clipboard_write` effect now is similar to read: it must response to
a "reply" callback synchronously. This lets the embedder ask for write
permission, too.

We also now pass through program name and grant information from Kitty
clipboard protocol so that embedders can use that if they want.

This is a breaking ABI change.
2026-08-24 08:46:00 -07:00
Mitchell Hashimoto
1bc188739d typos 2026-08-24 08:40:11 -07:00
Mitchell Hashimoto
7ae9b11138 libghostty: Kitty clipboard write permission prompts and grants
The `clipboard_write` effect now is similar to read: it must response
to a "reply" callback synchronously. This lets the embedder ask for write
permission, too.

We also now pass through program name and grant information from Kitty 
clipboard protocol so that embedders can use that if they want.

This is a breaking ABI change.
2026-08-24 08:35:34 -07:00
Mitchell Hashimoto
df14efaf33 macos: preview images in the clipboard read confirmation dialog 2026-08-24 08:33:37 -07:00
Mitchell Hashimoto
c1f0ef73a9 macos: serve copied files as text/uri-list in Kitty clipboard reads 2026-08-24 08:18:36 -07:00
Mitchell Hashimoto
af9470b19b macos: Kitty clipboard reads support pw/name session grants 2026-08-24 08:18:36 -07:00
Mitchell Hashimoto
8c7a34d4c9 macos: Kitty clipboard reads serve all clipboard content types 2026-08-24 08:18:36 -07:00
Mitchell Hashimoto
0ce9054bf9 macos: implement Kitty clipboard protocol reads (OSC 5522) 2026-08-24 08:18:36 -07:00
Mitchell Hashimoto
a53771af01 libghostty: gate mode 5522 reports on clipboard read callback (#13990)
Report Kitty paste event mode 5522 as unrecognized when the stream
handler has no clipboard_read effect.

Previously libghostty-vt advertised Kitty paste events unconditionally
but Kitty clipboard reads can't work without a clipboard read effect
set.
2026-08-24 08:17:37 -07:00
Mitchell Hashimoto
94b6dae423 libghostty: gate mode 5522 reports on clipboard read callback
Report Kitty paste event mode 5522 as unrecognized when the stream
handler has no clipboard_read effect. 

Previously libghostty-vt advertised Kitty paste events
unconditionally but Kitty clipboard reads can't work without a clipboard
read effect set.
2026-08-24 07:29:44 -07:00
Mitchell Hashimoto
7a9bca6a6e macOS: fix responsiveness for repeated new tab action (#13985)
Fixes #13725
2026-08-24 06:58:12 -07:00
Mitchell Hashimoto
f9206be827 macOS: fix swiftlint warnings (#13986)
swiftlint 0.63.3 introduced a new rule called
[`legacy_swiftui_aspect_ratio`](76363aa4d7/CHANGELOG.md (L314))

<img width="509" height="451" alt="image"
src="https://github.com/user-attachments/assets/1ff6f593-ce8a-493e-a241-e9ae418746ee"
/>
2026-08-24 06:57:51 -07:00
Mitchell Hashimoto
874735a9af ci: update actions/upload-artifact pinned tag comment (#13989) 2026-08-24 06:57:35 -07:00
Jon Parise
2303bcf08d ci: update actions/upload-artifact pinned tag comment 2026-08-24 09:31:43 -04:00
azhn
b17abd96df refactor(image): Restrict prepForUpload to Image.Pending 2026-08-24 19:48:24 +10:00
Lukas
1d24eecb20 macOS: fix responsiveness for repeated new tab action 2026-08-24 11:37:34 +02:00
Lukas
6cf7e0cc54 macOS: fix swiftlint warnings
swiftlint 0.63.3 introduced a new rule called [`legacy_swiftui_aspect_ratio`](76363aa4d7/CHANGELOG.md (L314))
2026-08-24 11:34:38 +02:00
azhn
169213cd29 renderer/image: Fuse copy to owned data and pixel format conversion in prepImage 2026-08-24 19:16:58 +10:00
Lukas
6a508fd5e3 macos: translate physical menu shortcuts (#13888)
Translate printable physical keybindings through the current macOS
keyboard layout before assigning menu key equivalents. Previously these
bindings could not be represented because SwiftUI shortcuts are
character-based, so actions such as `super+backquote` had no native menu
shortcut.

Keep native keycodes as dispatch identity so translated display
characters do not change physical semantics or precedence over Unicode
bindings. Refresh shortcuts when the input source changes, and prevent
AppKit from transforming equivalents that are already localized.

**AI Usage:** The approach was suggested by GPT 5.6 Sol, but I wrote
most of the code and understand it all.
2026-08-24 09:55:02 +02:00
Mitchell Hashimoto
e77b2309fc libghostty: paste reads clipboard contents on demand, streams to pty (#13983)
Follow up to #13978

`ghostty_terminal_paste` no longer takes the clipboard's data up front.
The request now carries only the list of available MIME types plus a a
callback that writes one representation's bytes into a `GhosttyWriter`.

Previously an embedder had to load every representation for every MIME
type into memory before pasting. For a clipboard holding a large image
or video next to some text that could be hundreds of megabytes that were
never used.

I also took care to make sure that the data is only read once, to avoid
any time-of-check/time-of-use (TOCTOU) issues.

There is only one case where data might be fully buffered in memory now:
unsafe text data that needs to be checked. This is true for how Ghostty
GUI works today too.
2026-08-23 20:56:16 -07:00
Mitchell Hashimoto
da27e6c908 libghostty: paste reads clipboard contents on demand, streams to pty
Follow up to #13978

`ghostty_terminal_paste` no longer takes the clipboard's data up front.
The request now carries only the list of available MIME types plus a
a callback that writes one representation's bytes into a `GhosttyWriter`. 

Previously an embedder had to load every representation for every MIME
type into memory before pasting. For a clipboard holding a large image
or video next to some text that could be hundreds of megabytes that
were never used.

I also took care to make sure that the data is only read once, to avoid
any time-of-check/time-of-use (TOCTOU) issues.

There is only one case where data might be fully buffered in memory now:
unsafe text data that needs to be checked. This is true for how Ghostty
GUI works today too.
2026-08-23 20:40:40 -07:00
ghostty-vouch[bot]
a36dc245b0 Sync CODEOWNERS vouch list (#13981)
Sync CODEOWNERS owners with vouch list.

## Added Users

- @ollioddi
- @rkoten
- @tuananh
- @vasilmytsyk

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-24 00:26:53 +00:00
trag1c
9f0e1719dc i18n: update bg_BG translations (#13802) 2026-08-23 18:06:12 +02:00
Mitchell Hashimoto
e424060675 libghostty: centralize pasting to ghostty_terminal_paste, enable mode 5522 (#13978)
**Note: this has no changes for Ghostty GUI yet.** This only impacts
libghostty-vt.

This introduces a new `ghostty_terminal_paste` C API along with a
central `terminal.paste.paste` function that handles (1) mode 5522
(Kitty clipboard) (2) bracketed paste (3) normal paste all in one place,
combined with unsafe value detection and proper xterm-style newline
handling.

Terminal pasting is now stateful because for the Kitty clipboard
protocol in particular, it must mint "grants" that stay with the
terminal. Previously, paste encoding was stateless.

To start, this is only exposed/used by libghostty to enable Kitty
clipboard handling.

Other changes:

- **IO: randomSecure.** This also adds the `io.randomSecure`
implementation to `TinyIo` and a global sys override for it because
Kitty clipboard requires the ability to create one-time passwords and
the implementation (following Kitty) requires a crypto random source.
The sys model is for libghostty embedders.

- **New C result value: rejected.** This introduces a new C result enum
value "rejected" for values that are valid but rejected for some reason.
Its very possible that prior "invalid value" users will have to update
to this, and I recognize that its close to both but it fills an
important semantic difference.

Also note this still _eagerly_ requires all clipboard contents. I want
to move to a callback based model but it made the PR much more
complicated. I plan on playing with that before converting apprt's to
this.
2026-08-23 07:23:30 -07:00
ghostty-vouch[bot]
5834a0e3df Update VOUCHED list (#13977)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/13976#discussioncomment-18121426)
from @pluiedev.

Denounce: @tangivis

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-23 05:15:39 +00:00
ghostty-vouch[bot]
da0093671a Update VOUCHED list (#13975)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/13899#discussioncomment-18120807)
from @jcollie.

Vouch: @j-c-m

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-23 03:03:08 +00:00