Fixes#7337
AppKit encodes functional keys as PUA codepoints. We don't want to send
that down as valid text encoding for a key event because KKP uses that
in particular to change the encoding with associated text.
I think there may be a more specific solution to this by only doing this
within the KKP encoding part of KeyEncoder but that was filled with edge
cases and I didn't want to risk breaking anything else.
Fixes#7337
AppKit encodes functional keys as PUA codepoints. We don't want to send
that down as valid text encoding for a key event because KKP uses that
in particular to change the encoding with associated text.
I think there may be a more specific solution to this by only doing this
within the KKP encoding part of KeyEncoder but that was filled with edge
cases and I didn't want to risk breaking anything else.
Fixes#7315Fixes#7314Fixes#7310Fixes#7309
**This PR has breaking changes, noted later.**
This changes our internal key events to match the [W3C key event code
specification](https://www.w3.org/TR/uievents-code/). With these
changes, apprts are expected to produce key codes within that spec and
everything follows from there. This gives us a standard cross-platform
keycode behavior.
Previously, due to our history, we based our key codes on GLFW and Linux
more generally (since Ghostty was on Linux first). This served us
surprisingly well through today, but has been riddled with various
issues (many fixed, but note how many bugs this PR is fixing). From a
user experience perspective, it also caused confusion about how
Ghostty's keybinds interact with keyboard layouts which led to various
complicated features like `physical:` (which is removed in this PR).
## Overview of Changes
* `physical:` is now gone. Physical keys are now specified by the W3C
key codes. Example: `ctrl+KeyA` will always match the "a" key on a US
physical layout (the name `KeyA` lining up with US keyboards is mandated
by the spec, not us). Note when we say "physical" here we mean the
keycode sent by the OS or GUI framework; these can often be overridden
using programs to remap keys at the "hardware" level but software
layouts do not do this.
* All single codepoint characters match the character produced by the
keyboard layout (i.e. are layout-dependent). So `ctrl+c` matches the
physical "c" key on a US standard keyboard with a US layout, but matches
the "i" key on a Dvorak layout. This also works for international
characters. Codepoints are case-insensitive and match via Unicode case
folding (this is how both Windows and macOS treat keyboard shortcuts).
* W3C key names replace all previous non-character names and always
match _physical keys_. For example, `ctrl+grave_accent` (Ghostty 1.1x)
is now `ctrl+backquote` to match the W3C spec. This PR maintains
backwards compatibility so the old values are aliased to the new values.
* W3C key names can be both snake case and match the spec exactly. e.g.
`KeyA` and `key_a` are both valid. This is an aesthetic choice, because
I think the capitalization is really ugly. We have tests to verify this
mapping so its officially supported.
* Because we support W3C keys, we now support significantly more media
keys such as `context_menu`, `browser_home` and so many more. These work
as long as your OS and keyboard can produce the valid key codes.
## Breaking Changes
* Key names have changed, e.g. `grave_accent` is now `backquote`. The
new names are all W3C standard. There are backwards compatible aliases,
so **old configurations will still work.** But the `+list-keybinds` CLI
will always output the new versions.
* `physical:` is gone, all W3C names are always physical and all code
points are always logical. There are backwards compatible aliases for
unambiguous keys, so **most old configurations will still work.** If
there is ambiguity, old configurations will error, but I don't expect
this to be common at all.
* Physical keybinds always take priority over logical keybinds. This was
_inconsistent_ before. Physical keybinds are relatively rare so I don't
think this will impact people but just noting this is not an explicit,
tested, documented behavior.
Related to #7316
I'm not going to close the issue yet because I want to also update the
website, but this should help clarify things more. I noticed the README
already makes a distinction, thankfully.
This allows for `keybind = super+d=new_split` to now work (defaults to
"auto"). This will also let us convert void types to union/enum/struct
types in the future without breaking existing bindings.
This allows for `keybind = super+d=new_split` to now work (defaults to
"auto"). This will also let us convert void types to union/enum/struct
types in the future without breaking existing bindings.