Commit Graph

12953 Commits

Author SHA1 Message Date
Mitchell Hashimoto
2f49e0c902 remove screenclone test cause it leaks memory on purpose 2025-11-17 06:42:00 -10:00
Mitchell Hashimoto
09d41fd4af terminal: page tests for full clone 2025-11-17 06:10:38 -10:00
Mitchell Hashimoto
9a46397b59 benchmark: screen clone 2025-11-17 05:08:19 -10:00
Mitchell Hashimoto
711e10d930 macOS: Fix dictation icon's position while speaking (#9605)
Fixes #8493.

There is still an "overflow" issue since preedit doesn't wrap right now,
but that's kind of off-topic.


https://github.com/user-attachments/assets/a7ae6018-76c7-4d16-9a9b-e0167072d910
2025-11-16 06:58:03 -08:00
Lukas
011fc77caa macOS: Fix dictation icon's position while speaking 2025-11-16 12:17:31 +01:00
Mitchell Hashimoto
b76203bbb9 Update iTerm2 colorschemes (#9603)
Upstream release:
https://github.com/mbadolato/iTerm2-Color-Schemes/releases/tag/release-20251110-150531-d5f3d53
2025-11-15 19:50:41 -08:00
Mitchell Hashimoto
4c0d7379db Search Thread (#9602)
Progress towards #189 

## Search Thread

This completes an initial implementation of the search thread. This is a
separate thread that manages a terminal search operation, triggering
event callbacks for various scenarios. The performance goal of the
search thread is to minimize time spent within the critical area of the
terminal lock while making forward progress on search outside of that.

The search thread sends two messages back to the caller right now:

- Total matches: sent continuously as new matches are found, just a
number
- Viewport matches: a list of `Selection` structures spanning the
current viewport of matches within the visible viewport. Sent whenever
the viewport changes (location or content).

I think that's enough to build a rudimentary search UI.

For this initial implementation, the search also relies on a "refresh
timer" which trigger every 24ms (40 FPS) to grab the lock and look for
any reconciliation that needs to happen: viewport moved, active screen
changed, active area changed, etc. This is a total guess and is
arbitrary currently. The value should be tuned to balance responsiveness
and IO throughput (lock-holding). I actually suspect this may be too
frequent right now.

A TODO is noted for the future to pause the refresh timer when the
terminal being search isn't focused. We'll have to do that before
shipping search because the way its built right now we will definitely
consume unnecessary CPU while unfocused. But only while search is
active.

## `ViewportSearch`

I also determined the need for what is called the `ViewportSearch`
layer. This is similar to `ActiveSearch` in that it throws away and
re-searches an area, but is tuned towards efficiently detecting viewport
changes. I found its more efficient to continuously research the visible
viewport than to hunt for those matches within the cached ScreenSearch
results, which can be very large.

## Future

Next up we need to hook up the search thread to some keybindings to
start and stop the search so we can then trigger those from our apprts
(GUIs).

I highly suspect this is going to expose some major performance issues
(overly active message sending being the likely culprit) that we can fix
up in the search thread thereafter. Up until this point we can only run
this stuff in isolation in unit tests which is good for testing
correctness but difficult for testing resource usage.

There are some written TODOs in the Thread.zig file in this PR. I may
address some of them before merging, since I think a couple are pretty
obvious performance gotchas.
2025-11-15 19:50:28 -08:00
Mitchell Hashimoto
79af2378d2 terminal: unify all notification sending into the notify command 2025-11-15 19:48:09 -08:00
mitchellh
ead01e8ffd deps: Update iTerm2 color schemes 2025-11-16 00:15:33 +00:00
Mitchell Hashimoto
caf5040a6d macOS: find correct tab bar when in fullscreen (#9596)
Fixes #9597
2025-11-15 14:13:30 -08:00
Mitchell Hashimoto
90a6ea7aa5 terminal: note some search thread TODOs we can address later 2025-11-15 14:03:27 -08:00
Mitchell Hashimoto
f0af63db15 terminal: search thread refresh timer to reconcile state 2025-11-15 13:43:26 -08:00
Mitchell Hashimoto
acab8c90a2 terminal: search.Thread searches viewport and notifies viewport results 2025-11-15 13:30:32 -08:00
Mitchell Hashimoto
99d47a4627 terminal: viewport search 2025-11-15 13:00:58 -08:00
Mitchell Hashimoto
05366485da macOS: fix misplaced frame modifier (#9598)
As per #9504, this was supposed to be on `ZStack`, not on the overlay.
See also #9503. I cherry-picked it in the wrong place before.
2025-11-15 06:37:55 -08:00
Lukas
8d1dd332c6 macOS: fix misplaced frame modifier
As per #9504, this was supposed to be on `ZStack`, not on the overlay. See also #9503. I cherry-picked it in the wrong place before.
2025-11-15 10:14:43 +01:00
Lukas
b124b78313 macOS: find correct tab bar when in fullscreen
Fixes #9593
2025-11-15 08:10:05 +01:00
Mitchell Hashimoto
bfa397b196 terminal: search thread active screen reconciliation loop 2025-11-14 21:24:18 -08:00
Mitchell Hashimoto
1867928b84 terminal: search thread search ticking 2025-11-14 21:05:05 -08:00
Mitchell Hashimoto
d1ad32eadd terminal: search.Thread starting search loop 2025-11-14 17:04:34 -08:00
Mitchell Hashimoto
19dfc0aa98 terminal: search.Thread more boilerplate, test starting 2025-11-14 16:29:45 -08:00
Mitchell Hashimoto
466a004c39 lib-vt: export stream.Action for custom streams (#9595) 2025-11-14 16:06:59 -08:00
Mitchell Hashimoto
de545eeae1 lib-vt: export stream.Action for custom streams 2025-11-14 16:01:57 -08:00
Mitchell Hashimoto
7cc8ea7efb terminal: change primary/alt screens to use a ScreenSet, stable pointers (#9594)
This PR changes our primary/alt screen tracking from being by-value
fields that are copied during switch to heap-allocated pointers that are
stable. This is motivated now by #189 since our search thread needs a
stable screen pointer, but this will also help us in the future with our
future N-screens proposal I have.

Also, as a nice bonus, alt screen memory is now initialized on demand
when you first enter alt-screen, so this saves a few MB of memory for a
new terminal if you never use alt screen!

This is something I've wanted to do for a veryyyyyy long time, but the
annoyance of the task really held me back. I finally pushed through and
did this with the help of some AI agents for the rote tasks (renaming
stuff).
2025-11-14 16:00:47 -08:00
Mitchell Hashimoto
2452026ff3 terminal: kitty limits only if kitty graphics being built 2025-11-14 15:53:00 -08:00
Mitchell Hashimoto
4ba00dbe89 fix harfbuzz 2025-11-14 15:48:06 -08:00
Mitchell Hashimoto
580f9f057b convert t.screen to t.screens.active 2025-11-14 15:40:31 -08:00
Mitchell Hashimoto
3aff5f0aff ScreenSet 2025-11-14 15:08:10 -08:00
Mitchell Hashimoto
368f4f565a terminal: Screen opts is a structure 2025-11-14 14:10:37 -08:00
Mitchell Hashimoto
a5a914c2b8 Considerably more search internals (#9585)
Chugging along towards #189

This adds significantly more internal work for searching. A long time
ago, I added #2885 which had a hint of what I was thinking of. This
simultaneously builds on this and changes direction.

The change of direction is that instead of making PageList fully
concurrency safe and having a search thread access it concurrently, I'm
now making an architectural shift where our search thread will grab the
big lock (blocking all IO/rendering), but with the bet that we can make
our critical areas small enough and time them well enough that the
performance hit while actively searching will be minimal. **Results yet
to be seen, but the path to implement this is much, much simpler.**

## Rearchitecting Search

To that end, this PR builds on #2885 by making `src/terminal/search` and
entire package (rather than a single file).

```mermaid
graph TB
    subgraph Layer5 ["<b>Layer 5: Thread Orchestration</b>"]
        Thread["<b>Thread</b><br/>━━━━━━━━━━━━━━━━━━━━━<br/>• MPSC queue management<br/>• libxev event loop<br/>• Message handling<br/>• Surface mailbox communication<br/>• Forward progress coordination"]
    end
    
    subgraph Layer4 ["<b>Layer 4: Screen Coordination</b>"]
        ScreenSearch["<b>ScreenSearch</b><br/>━━━━━━━━━━━━━━━━━━━━━<br/>• State machine (tick + feed)<br/>• Result caching<br/>• Per-screen (alt/primary)<br/>• Composes Active + History search<br/>• Interrupt handling"]
    end
    
    subgraph Layer3 ["<b>Layer 3: Domain-Specific Search</b>"]
        ActiveSearch["<b>ActiveSearch</b><br/>━━━━━━━━━━━━━━━━━━━━━<br/>• Active area only<br/>• Invalidate & re-search<br/>• Small, volatile data"]
        
        PageListSearch["<b>PageListSearch</b><br/>━━━━━━━━━━━━━━━━━━━━━<br/>• History search (reverse order)<br/>• Separated tick/feed ops<br/>• Immutable PageList assumption<br/>• Garbage pin detection"]
    end
    
    subgraph Layer2 ["<b>Layer 1: Primitive Operations</b>"]
        SlidingWindow["<b>SlidingWindow</b><br/>━━━━━━━━━━━━━━━━━━━━━<br/>• Manual linked list node management<br/>• Circular buffer maintenance<br/>• Zero-allocation search<br/>• Match yielding<br/>• Page boundary handling"]
    end
    
    Thread --> ScreenSearch
    ScreenSearch --> ActiveSearch
    ScreenSearch --> PageListSearch
    ActiveSearch --> SlidingWindow
    PageListSearch --> SlidingWindow
    
    classDef layer5 fill:#0a0a0a,stroke:#ff0066,stroke-width:3px,color:#ffffff
    classDef layer4 fill:#0f0f0f,stroke:#ff6600,stroke-width:3px,color:#ffffff
    classDef layer3 fill:#141414,stroke:#ffaa00,stroke-width:3px,color:#ffffff
    classDef layer2 fill:#1a1a1a,stroke:#00ff00,stroke-width:3px,color:#ffffff
    
    class Thread layer5
    class ScreenSearch layer4
    class ActiveSearch,PageListSearch layer3
    class SlidingWindow layer2
    
    style Layer5 fill:#050505,stroke:#ff0066,stroke-width:2px,color:#ffffff
    style Layer4 fill:#080808,stroke:#ff6600,stroke-width:2px,color:#ffffff
    style Layer3 fill:#0c0c0c,stroke:#ffaa00,stroke-width:2px,color:#ffffff
    style Layer2 fill:#101010,stroke:#00ff00,stroke-width:2px,color:#ffffff
```

Within the package, we have composable layers that let us test each
point:

- `SlidingWindow`: The lowest layer, the caller manually adds linked
list page nodes and it maintains a sliding window we search over,
yielding results without allocation (besides the circular buffers to
maintain the sliding window).
- `PageListSearch`: Searches a PageList structure in reverse order
(assumption: more recent matches are more valuable than older), but
separates out the `tick` (search, but no PageList access) and `feed`
(PageList access, prep data for search but don't search) operations.
This lets us `feed` in a critical area and `tick` outside. **This
assumes an immutable PageList, so this is for history.**
- `ActiveSearch`: Searches only the active area of a PageList. The
expectation is that the active area changes much more regularly, but it
is also very small (relative to scrollback). Throws away and re-searches
the active area as necessary.
- `ScreenSearch`: Composes the previous three components to coordinate
searching an active terminal screen. You'd have one of these per screen
(alt vs primary). This also caches results unlike the other components,
with the expectation that the caller will revisit the results as screens
change (so if you switch from neovim back to your shell and vice versa
with a search active, it won't start over).
- `Thread`: A dedicated search thread that will receive messages via
MPSC queues while managing the forward progress of a `ScreenSearch` and
sending matches back to the surface mailbox for apprt rendering. **The
thread component is not functional, just boilerplate, in this PR.**

ScreenSearch is a state machine that moves in an iterative `tick` +
`feed` fashion. This will let us "interrupt" the search with updates on
the search thread (read our mailbox via libxev loops for example) and
will let us minimize critical areas with locks (only `feed`).

Each component is significantly unit tested, especially around page
boundary cases. Given the complexity, there is no way this is perfect,
but the architecture is such that we can easily add regression tests as
we find issues.

## Other Changes, Notes

The only change to actually used code is that tracked pins in a
`PageList` can now be flagged as "garbage." A garbage tracked pin is one
that had to be moved in a non-sensical way because the previous location
it tracked has been deleted. This is used by the searcher to detect that
our history was pruned.

**If my assumption about the big lock is wrong** and this ends up being
godawful for performance, then it should still be okay because more
granular locking and reference counting such as that down by @dave-fl in
#8850 can be pushed into these components and reused. So this work is
still valuable on its own.

## Future

This PR is still just a bunch of internals, split out into its own PR so
I don't make one huge 10K diff PR. There are a number of future tasks:

- Flesh out `ScreenSearch` and hook it up to `Thread`
- Pull search thread management into `Surface` (or possibly the render
thread or shared render state since active area changes can be
synchronized with renderer frame rebuilds. Not sure yet.)
- Send updates back to the surface thread so that apprts can update UI.
- Apprt actions, input bindings, etc. to hook this all up (the easy
part, really).

The next step is to continue to flesh out the `ScreenSearch` as required
and hook it up to `Thread`.

**AI disclosure:** AI reviewed the code and assisted with some tests,
but didn't write any of the logic or design. This is beyond its ability
(or my ability to spec it out clearly enough for AI to succeed).
2025-11-14 12:38:06 -08:00
Mitchell Hashimoto
89e23e9190 macOS: Use small scrollbar (#9589)
As per #9557. This PR includes both the style change and disabling
autohiding for legacy scrollbars, such that the scrollbar slot is always
visible in the right margin, albeit without a knob if there's no content
to scroll. Wasn't 100 % clear on whether to include the latter, let me
know if I should drop that part.

**Before**


https://github.com/user-attachments/assets/49617f1f-12dc-477d-9df9-93617296cea7

**After**


https://github.com/user-attachments/assets/2497f12d-b127-4004-9947-b8cd67b6b0eb
2025-11-14 08:27:25 -08:00
Daniel Wennberg
49bf73458b don't autohide scrollers 2025-11-14 07:40:51 -08:00
Daniel Wennberg
d48f855a48 macOS: set scrollbar size to .small 2025-11-14 07:36:54 -08:00
Mitchell Hashimoto
5ab23e6493 macOS: restore visiblity state when hiding quick terminal (#9576)
Fixes #8414 and a case where `toggle_visibility` is not working after
hiding using `cmd+h`


https://github.com/user-attachments/assets/be28c2d9-b416-467f-9fe9-7b7c97278330
2025-11-14 07:29:46 -08:00
Mitchell Hashimoto
05b42919d5 macOS: add more cursor style and fixes #8409 (#9580)
Fixes #8409


https://github.com/user-attachments/assets/c9e7ad9b-c1eb-451b-a537-90f380f5f5f3
2025-11-14 07:28:20 -08:00
Mitchell Hashimoto
6ef850ba8e wuffs: protect against crafted images that cause overflows (#9581)
Fixes #9579

Protect against panics caused by integer overflows by using functions
that allow integer overflows to be caught instead of causing a panic.

Also protect against DOS from images that might not cause an overflow
but do consume an absurd amount of memory by limiting images to a
maximum size of 4GiB.
2025-11-14 07:26:27 -08:00
Mitchell Hashimoto
6b805a318e terminal: ScreenSearch can omit overlapped results in history tick 2025-11-14 07:24:22 -08:00
Mitchell Hashimoto
d349cc8932 terminal: ScreenSearch to search a single terminal screen 2025-11-13 15:07:35 -08:00
Mitchell Hashimoto
7b26e6319e terminal: Pin.garbage tracking 2025-11-13 13:16:38 -08:00
Jeffrey C. Ollie
ec55cbc879 wuffs: protect against crafted images that cause overflows
Fixes #9579

Protect against panics caused by integer overflows by using functions
that allow integer overflows to be caught instead of causing a panic.

Also protect against DOS from images that might not cause an
overflow but do consume an absurd amount of memory by limiting
images to a maximum size of 4GiB (which is the maximum size of
`image-storage-limit`).
2025-11-13 14:20:19 -06:00
Mitchell Hashimoto
2b647ba4cb terminal: PageListSearch updated to split next and feed 2025-11-13 10:14:12 -08:00
Mitchell Hashimoto
22496b8f0e terminal: sliding window needs to handle hard-wraps properly (tested) 2025-11-13 10:07:32 -08:00
Lukas
1486be0cdf macOS: add more cursor style and fixes #8409 2025-11-13 18:20:09 +01:00
Lukas
bcb5112b24 macOS: restore visiblity state when hiding quick terminal 2025-11-13 11:30:43 +01:00
Mitchell Hashimoto
0ea350a8f2 terminal: ActiveSearch for searching the active area 2025-11-12 20:59:18 -08:00
Mitchell Hashimoto
0f64b9a8e8 apprt/gtk: remove explicit X11 clipboard atom (#9570)
Fixes #9532
Supersedes #9554

Turns out the explicit `UTF8_STRING` atom was not needed after all and
GTK adds it automatically when running under X11; just having the
explicit UTF-8 charset type is enough.

This corrects situations where it may not be necessary to include
(Wayland), in addition to removing a duplicate atom under X11.

Importantly, this also corrects issues under Wayland in some scenarios,
such as using Electron-based apps (e.g., VSCode/Codium under Ubuntu
24.04 LTS).
2025-11-12 13:41:39 -08:00
Chris Marchesi
4f6c5a8d4f apprt/gtk: remove explicit X11 clipboard atom
Turns out this was not needed after all and GTK adds it automatically
when running under X11; just having the explicit UTF-8 charset type is
enough.

This corrects situations where it may not be necessary to include
(Wayland), in addition to removing a duplicate atom under X11.

Importantly, this also corrects issues under Wayland in some scenarios,
such as using Electron-based apps (e.g., VSCode/Codium under Ubuntu
24.04 LTS).
2025-11-12 13:12:42 -08:00
Mitchell Hashimoto
43835d1468 terminal: SlidingWindow supports forward/reverse directions 2025-11-12 11:46:52 -08:00
Mitchell Hashimoto
6439af0afc terminal: SlidingWindow search to dedicated file 2025-11-12 11:03:29 -08:00
Mitchell Hashimoto
8848e98271 terminal: search thread boilerplate (does nothing) 2025-11-12 10:07:21 -08:00