Adds `-fPIC` flag for musl targets when building highway and simdutf C++
dependencies, matching the existing freebsd behavior.
## What is PIC?
Position Independent Code (PIC) generates machine code using relative
addresses instead of absolute ones, allowing the code to be loaded at
any memory address. This is required when linking static libraries into
shared libraries (.so files).
## Why both freebsd and musl need it
Both freebsd and musl use strict relocation policies that reject non-PIC
code in shared libraries. Without `-fPIC`, linking fails with errors
like:
```
relocation R_X86_64_PC32 cannot be used against symbol '__cxa_begin_catch'
```
glibc is more permissive and handles these relocations at runtime, which
is why linux-gnu targets work without this flag.
## Context
This enables cross-compiling ghostty-vt to musl/Alpine Linux targets.
Discovered while integrating ghostty-vt into opentui:
https://github.com/sst/opentui/pull/440
---
This PR was created with help from Claude Opus 4.5.
Adds the `selection_for_search` action, with Cmd+E keybind by default.
This action inputs the currently selected text into the search field
without changing focus, matching standard macOS behavior.
Implements discussion #9776 and #10036
<details><summary>AI Disclosure</summary>
<p>
Tab completions with Codestral.
Reviewed by Gemini 3 Flash via chatting.
No Agentic coding tools were involved.
</p>
</details>
Adds test coverage for bitmap font rendering in the FreeType backend
using the Spleen 8x16 font in three formats:
- BDF (Bitmap Distribution Format)
- PCF (Portable Compiled Format)
- OTB (OpenType Bitmap)
Tests validate glyph dimensions and pixel-perfect rendering against
expected patterns, following the model established by the existing
TerminusTTF test.
Spleen was chosen because it ships in all three required formats from a
single source, providing consistent test data across formats. Its BSD
2-Clause license is compatible with the existing font licenses in the
repo (OFL, MIT). No existing embedded fonts could be used since they are
all TTF/OTF files that use the TrueType loader rather than the
BDF/PCF/OTB loaders being tested.
Addresses #8524.
---
This PR was written with assistance from Claude Code.
Add test coverage for bitmap font rendering using the Spleen 8x16 font
in three formats: BDF (Bitmap Distribution Format), PCF (Portable
Compiled Format), and OTB (OpenType Bitmap). Tests validate glyph
rendering against expected pixel patterns.
Addresses #8524.
The "unimplemented OSC command" warning is a frequent source of red
herrings as there are many OSCs that we parse but deliberately do not
implement. It's also a small drag on performance due to the function
call overhead and the overhead of formatting and outputting the message.
This PR lowers the message from warning to debug. Debug logs are
compiled out of release builds so there should be less confusion from
general users who will no longer see the message.
Adds the `selection_for_search` action, with Cmd+E keybind by default.
This action inputs the currently selected text into the search
field without changing focus, matching standard macOS behavior.
This fixes the Windows build failure discussed in
https://github.com/ghostty-org/ghostty/discussions/10148
When building on Windows, `symbols-unigen` and `props-unigen` crash with
`error.FileTooBig` because `stdout.end()` calls `setEndPos()` to
truncate the output. Windows does not support `SetEndOfFile` on pipes or
console handles - it returns `ERROR_INVALID_PARAMETER`, which Zig maps
to `error.FileTooBig`.
Using `flush()` instead of `end()` is correct here because:
1. `end()` flushes AND truncates - useful when overwriting files that
might have leftover content
2. For stdout captured as a pipe, there's nothing to truncate - we're
writing sequentially to a fresh pipe
3. `flush()` ensures all buffered data is sent, which is all that's
needed
CI before fix was failing with FileTooBig, after fix builds
successfully:
https://github.com/remorses/opentui/actions/runs/20671299561/job/59352503875
This PR simplifies and corrects the logic for placing a glyph
vertically, by using the `position.y` from `CoreText` directly, instead
of using an offset from the cell's starting `y`. The logic was incorrect
from the beginning, always treating the first glyph of a cell as being
at `y` of zero. We only need to be subtracting the cell's starting `x`
to align the glyphs to the cell grid.
Enabling the commented out logging, I found no instances of `position.y
differs from old offset.y` lines with `JetBrains Mono` with ligatures
turned on, but running
[ttylang](https://github.com/jacobsandlund/ttylang) (printing the
Universal Declaration of Human Rights in various languages) revealed 676
instances of this, with many only slightly off.
An example log from some Tai Tham text is the following, and this PR
adds a test based on this:
```
...pos=(0.00,-8.21) run_offset=(69.41,-8.21) cell_offset=(69.41,-8.21) old offset.y=0.00 cps = \u{1a49}\u{1a60} \u{1a3f}▸\u{1a69} \u{1a2f} → ᩉ᩠ᨿᩩᨯ
```
Browsers display this as:
ᩉ᩠ᨿᩩ
`main` is printing:
<img width="852" height="90" alt="CleanShot 2026-01-05 at 10 28 17@2x"
src="https://github.com/user-attachments/assets/c97b738c-8fe4-48b5-81f8-e0e79f1a9269"
/>
this PR prints:
<img width="958" height="90" alt="CleanShot 2026-01-05 at 10 29 07@2x"
src="https://github.com/user-attachments/assets/88fd26a7-8041-4b33-ab02-56f411204b04"
/>
Since this is a ligature of two different grapheme clusters, Ghostty
ends up subtracting too much of the `x` value with the `cell_offset.x`
(starting x), so neither of the screenshots above are correct, but the
second is closer and gets the `y` value right.
AI disclaimer: I didn't use AI for the code, but did ask it about this
Tai Tham text and why it wasn't a single grapheme cluster:
https://ampcode.com/threads/T-019b8ea2-1822-75bb-a8eb-55a9ddb9f7ea
On main, after rearranging panes, the window becomes permanently
immovable. Grab handles temporarily set `window.isMovable = false` on
hover to prevent window dragging from interfering with pane drags
(fixing [#10110](https://github.com/ghostty-org/ghostty/issues/10110)),
but the restoration logic failed when views were destroyed during pane
rearrangement (which happens each time a pane is rearranged).
The previous approach managed `window.isMovable` state across the view
lifecycle:
1. `mouseEntered` → saved and disabled `window.isMovable`
2. View removed during rearrangement → `mouseExited` never fired
3. `deinit` ran with `self.window` already nil → restoration failed
4. Window stuck with `isMovable = false`
Instead of managing window state, prevent the mouseDown event from
reaching the window's drag handler by overriding mouse event handling in
the grab handle view.
Per [Apple's Event Handling
Guide](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html):
> Custom NSView objects should not invoke super in their implementations
of NSResponder mouse-event-handling methods such as mouseDown:,
mouseDragged: and mouseUp: unless it is known that the inherited
implementation provides some needed functionality.
This eliminates all state management while solving both the original
issue (#10110) and the new bug.
AI disclosure: claude code found and wrote the fix. I tested it manually
to see that it works. I pressed claude quite hard here to come up with
the best fix, and looked at documentation to understand what the fix was
doing. It seems like this is a better approach overall to preventing the
main window from being dragged when grabbing the Surface Drag handle.
After rearranging panes, the window becomes permanently unmovable.
Grab handles temporarily set `window.isMovable = false` on hover to prevent
window dragging from interfering with pane dragging.
Override `viewWillMove(toWindow:)` to catch when the view is being removed from
the window. This lifecycle method is called before the window reference
becomes nil, allowing us to restore `window.isMovable`.