In practice, the primary and selection clipboards are treated exactly
the same, but this allows OSC 52 sequences to use either 's' or 'p' as
the clipboard target.
Fixes#880
If a command is specified but it can't be found, then we try to fallback
to a default command like "sh" and log the issue. This prevents Ghostty
from simply exiting.
This enables shifted alt-prefixed keys, such as `shift+alt+.` on
US standard becoming `M->`. To do this, we needed to fix a few bugs:
(1) translation mods should strip alt even if other mods are set
(2) AppKit translation event needs to construct new characters with
the translation mods.
(3) Alt-prefix handling in KeyEncoder needs to allow ASCII utf8
translations even for macOS.
Fixes#872
In #867 we fixed macos-option-as-alt, but unfortunately AppKit ALSO does
some translation so some behaviors were not working correctly.
Specifically, when you had macos-option-as-alt set, option+e would
properly send `esc+e` to the pty but it would ALSO set the dead key
state for "`" since AppKit was still translating the option key.
This commit introduces a function to strip alt when necessary from the
translation modifiers used at the AppKit layer, preventing this
behavior.
This regressed sometime -- I can't find the exact commit -- but in any
case I've moved this handling directly into the KeyEncoder so we can
unit test it and prevent future regressions.
Fixes#865
Related to #861
In #861, we fixed a deadlock that could happen if the writer mailbox was
full from the reader thread by waking up the writer thread for
processing.
Unfortunately, the writer thread ALSO handles messages that require the
terminal lock (i.e. resizing, focus state, etc.). If the mailbox
contains these messages, it cannot make forward progress on the writes
(which do not require a lock). This makes it possible still under heavy
write scenarios to fully deadlock the read/write threads.
This commit modifies the behavior so that while we are attempting to
queue a writer message after it fails, we release the lock. This is a
very slow path since we are releasing/acquiring locks under heavy
contention. We can improve it in the future but for now its okay because
this is also a rare situation that only happens under the heaviest loads
that also produce heavy writes.
Fixes#741
This completely reimplements double-click-and-drag logic for selecting
by word. The previous implementation was horribly broken. See #741 for
all the details.
The implemented logic now is:
* A double-click initiates a select-by-word selection mechanism.
- A double-click may start on a word or whitespace
- If the initial double-click is on a word, that word is immediately selected.
- If the initial double-click is on whitespace, the whitespace is not selected.
* A "word" is determined by a non-boundary character meeting a boundary character.
- A boundary character is `NUL` ` ` (space) `\t` `'` `"`
- This list is somewhat arbitrary to make the terminal "feel" good.
- Cell SGR states (fg/bg, bold, italic, etc.) have no effect on boundary determination or selection logic.
* As the user drags _on the same line_:
- No selection change occurs until the cursor is over a new word. Whitespace change does nothing.
- When selection is over a new word, that entire word added to the selection.
* When the user drags _up_ one or more lines:
- If the cursor is over whitespace, all lines from the selection point up to but not including the cursor line are selected.
* This selection is done in accordance to the previous rules.
- If the cursor is over a word, the word becomes the beginning of the selection.
- The end of the selection in all cases is the first word at or before the initial double-click point.
* When the user drags _down_ one or more lines:
- The same logic as _up_ but swap the "beginning" and "end" of selection terminology.
* With this logic, the behavior of Ghostty has the following invariants:
- Whitespace is never selected unless it is between two selected words
- Selection implies at least one word is highlighted
- The initial double-click point marks the beginning or end of a selection, never the middle.
Normally, we queue all the writes we need from a single `read()` syscall
and only wake up the writer thread at the end of processing that batch
of data.
But under very heavy load or large batches of data, it is possible for the
terminal sequences to generate enough writes to the pty to fill the
writer thread queue while we're still processing the data from `read()`.
This modifies our queuer to attempt to queue, but if the queue is full
we wake up the writer thread immediately then queue again (which should
succeed in every case -- eventually).
This maybe is a robust way to get Monaspace fonts working.
Previously, we used leading as part of the calculation in cell height. I
don't remember why. It appears most popular monospace fonts (Fira Code,
Berkeley Mono, JetBrains Mono, Monaco are the few I tested) have a value
of 0 for leading, so this has no effect. But some fonts like Monaspace
have a non-zero (positive) value, resulting in overly large cell
heights.
The issue is that we simply add leading to the height, without modifying
ascent. Normally this is what you want (normal typesetting) but for
terminals, we're trying to set text centered vertically in equally
spaced grid cells. For this, we want to split the leading between the
top and bottom.
Instead of making a separate enum that must be translated from the
ClipboardRequest type, simply re-use ClipboardRequest to determine the
clipboard confirmation reason.
PR #850 introduced several color palette OSC setting and querying
sequencing. In doing so, an active palette was introduced to enable
resetting back to the default (configured) palette. The active palette
was not initialized with the configured palette, thus any configured
theme by the terminal was not set at launch.
This behavior can be confirmed thanks to PR #852, which resets the
active palette on configuration reload. To observe the behavior:
1. Set the configured palette to something other than the default
2. Open ghostty. Observe the color palette
3. Reload the configuration
4. Press enter for a new shell prompt. Note the palette has changed
This patch sets the configured palette as the active palette at
initialization.
When the config is changed, update the active palette in addition to the
default palette, but only those colors which have not been changed with
OSC 4.