feat: Select/Copy Links On Right Click If Present
This is a solution for https://github.com/ghostty-org/ghostty/issues/2107.
AI Disclosure: I used Gemini CLI to help me with this PR because while I have many years of programming experience, this is my first time writing Zig. I prototyped a couple different approaches with AI before landing on this one, so AI generated various prototypes and I chose the final imlementation. I've verified that my code compiles and works as intended.
When a user right-clicks, and there's no existing selection, the existing behavior is to try to select the word under the cursor:
https://github.com/ghostty-org/ghostty/blob/3548acfac63e7674b5e25896f6b393474fe8ea65/src/Surface.zig#L3740-L3742
This PR tweaks that behavior slightly: If there's a link under our cursor, as determined by linkAtPos, select the link (to copy with the right-click context menu). Otherwise, select the word as before.
As noted in https://github.com/ghostty-org/ghostty/issues/2107, this matches the behavior of iTerm and Gnome Terminal.
It's worth noting that linkAtPos already does the right thing in terms of checking the links from config and their highlight/hover states (modified by Ctrl or Super depending on platform).
https://github.com/ghostty-org/ghostty/blob/3548acfac63e7674b5e25896f6b393474fe8ea65/src/Surface.zig#L3896-L3901
It also therefore respects link-url from config.
https://github.com/ghostty-org/ghostty/blob/3548acfac63e7674b5e25896f6b393474fe8ea65/src/config/Config.zig#L3411-L3416
By using linkAtPos, we get all that behavior for free. In practical
terms, that means:
- If I'm holding Ctrl so a link is underlined and I right click on it, it selects the underlined link.
- If I'm not holding Ctrl and I right click on a link that is no underlined, it selects the word as before.
- This behavior respects per-platform key bindings and user config settings.
linkAtPos requires that the render state mutex is held. I believe it's safe to call because we're inside a block holding the mutex:
https://github.com/ghostty-org/ghostty/blob/3548acfac63e7674b5e25896f6b393474fe8ea65/src/Surface.zig#L3702-L3704
Original Behavior: (first without ctrl, then with ctrl)
https://github.com/user-attachments/assets/f9236c44-bea4-4be8-a54b-24d5ae24b2e7
New Behavior: (first without ctrl, then with ctrl, then pasting)
https://github.com/user-attachments/assets/1e7fa1a9-236e-471d-9504-c820c68600bb