Ghostty does not report associated text on macOS when
macos-option-as-alt is enabled for _any_ key press, whether or not the
Alt modifier is actually present. The "option as alt" decision should
only be made when the alt modifier is present.
This follows a specific behavior Kitty has, but no other terminal seems
to have, but it is a reasonable behavior that is in use by real programs
as found by our beta testing community.
We diverge from Kitty though in that we only apply this to ASCII
letters. Kitty does not CSIu encode special characters like `@` or `$`.
For these characters, Ghostty still encodes it as specified by fixterms.
Related to #1507
The comments in this change have most of the detail. The primary gist:
- caps-lock is handled correctly so #1501 is still fixed
- only characters pressed with the shift key are affected
Fixes#1505
I verified this behavior with every other terminal and I've added test
cases for it. We previously had a test case to assert the opposite,
which is incorrect.
Previously, we encoded `ctrl+_` in the CSIu format[1]. This breaks most
notably emacs which expects the legacy ambiguous encoding.
This commit utilizes the generator from Kitty to generate our control
key mappings. We also switch from keycode mapping to key contents
mapping which appears to be the correct behavior also compared to other
terminals.
In the course of doing this, I also found one bug with our fixterms
implementation. Fixterms states: "The Shift key should not be considered
as a modifier for Unicode characters, because it is most likely used to
obtain the character in the first place (e.g. the shift key is often
required to obtain the ! symbol)." We were not applying that logic and
now do.
[1]: https://www.leonerd.org.uk/hacks/fixterms/
Fixes#1099
We previously applied application keypad mode logic (`ESC=` or mode 66)
whenever it was active. However, from looking at the behavior of other
terminals (xterm and foot) it appears this isn't correct.
For xterm, application keypad mode only applies unconditionally if the
keyboard mode is VT220 (`-kt vt220`). For modern terminals, application
keypad mode is only applied if mode 1035 is disabled.
Mode 1035 is the "ignore numpad state with keypad mode" mode. It
defaults to true on terminal startup. If this is true, keypads are
always encoded in numerical mode. If this is false, the numlock state
will be respected.
Associated text should only be reported when it was generated from the
key event. To my knowledge, there are no release events which produce
text. This now matches kitty reporting for release events.
> When the key event is related to an actual modifier key, the corresponding
> modifier's bit must be set to the modifier state including the effect for the
> current event. For example, when pressing the :kbd:`LEFT_CONTROL` key, the
> ``ctrl`` bit must be set and when releasing it, it must be reset. When both
> left and right control keys are pressed and one is released, the release event
> must have the ``ctrl`` bit set. See :iss:`6913` for discussion of this design.
Related to https://github.com/mitchellh/ghostty/issues/1082
This fixes two separate issues to follow along with the new spec changes
Kovid pushed to Kitty:
1. When two modifiers are pressed and one is released, this shows up
as a proper release event with the correct side. Previously, the
correct side was shown but as a press event.
2. When two modifiers are pressed and one is released, the Kitty event
should not have that specific modifier set. For example, pressing
left ctrl, then right ctrl, then releasing right ctrl should encode
as "right ctrl released" but with NO modifiers still present.
Associated text should only be sent to the terminal when printable text
is generated from the keypress. Prevent sending associated text when any
modifier is pressed, except for Shift, NumLock, and Capslock
This brings Ghostty inline with the output of Kitty.
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.
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.
User input withe Alt modifier is typically ESC prefixed. Escape
prefixing a non-ascii character can cause bugs in some applications. For
example in bash, emitting an Alt+ф allows the user to backspace one
character into the prompt. This can be repeated multiple times.
When a character is outside the ASCII range (exclusive of 0x7F, this is
handled as a control sequence), print the character as is, with no
prefix.
Fix reporting of alternate keys when using the kitty protocol. Alternate
keyboard layouts were failing to report the "base layout" key. This
implementation now matches kitty's output 1:1, and has some added unit
tests for cyrillic characters.
This also fixes a bug where a caps_lock modified key would report the
shifted key as well. The protocol explicitly requires that shifted keys
are only reported if the shift modifier is true.
This matches Kitty behavior on both macOS and Linux. In certain keyboard
modes and Kitty keyboard modes, the behavior changes but those already
matched (tested).
macOS translates inputs such as shift+tab into the control character tab
(ascii 0x09). Linux/GTK does not translate character inputs except to
printable characters. We don't want control character translations
because these are all handled manually by our key encoder (i.e.
translating ctrl+c to 0x03).