Mac key citations point at the Mac client's published key input (#2912)
benilla's Mac key-handling comments cited the 1.12.1 Mac client as `0x5bf320` and `0x8a4aa`. The first resolved to an unrelated `WoW.exe` function, and nothing documented the second. benilla-re now publishes the Mac client's key input with `mac:` addresses (`systems/core/mackeys.md`), and every citation points there; `cited` finds all 15 backed. Read against it: - Caps Lock queues nothing on macOS, as the Mac client's modifier handler tests only Shift, Control and Option (`mac:08a06c`). - F17-F20 are named by the OS layout there, so benilla's names are noted as its own. - Deviation: Z keeps its capital name, where the Mac client's fill uppercases only a-y (`mac:08a3df`), because the fault leaves the stock sheathe binding unreachable. Tested: Caps Lock is a key only off the Mac. Fixes #2895 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
//!
|
||||
//! Deviation: a press with Super (Cmd) held runs no binding because that way a system chord such as
|
||||
//! Cmd+Tab or Cmd+Q never acts in game. The reference has no such modifier and runs the bare key's
|
||||
//! binding: the Mac enqueues the key with Command held and skips only its text (`0x8a519`), and
|
||||
//! binding: the Mac enqueues the key with Command held and skips only its text (`mac:08a51e`), and
|
||||
//! Windows hands `VK_LWIN`/`VK_RWIN` to the layout arm (`0x42da39`) like any key.
|
||||
//!
|
||||
//! Persistence: `benilla-config/bindings/account.txt` and `<Realm>-<Char>.txt` ([`store`]); the
|
||||
|
||||
@@ -107,6 +107,10 @@ impl Chord {
|
||||
pub(crate) fn key_token(k: KeyCode, layout: &LayoutNames) -> Option<KeyName> {
|
||||
match layout.name(k) {
|
||||
// The lookup folds `a`-`z` up (`0x64b419`), so Turkish `VK_OEM_7`'s `i` is `I`'s key.
|
||||
//
|
||||
// Deviation: the Z key is named `Z` on a Mac too, because the Mac client uppercases only
|
||||
// `a`-`y` (`mac:08a3df`) and so names it `z`, which no binding can press; that fault would
|
||||
// leave a binding to `Z`, the stock `TOGGLESHEATH` key, unreachable there.
|
||||
Some(LayoutName::Char(c)) => Some(KeyName::Char(c.to_ascii_uppercase())),
|
||||
Some(LayoutName::Dropped) => None,
|
||||
None => fixed_name(k),
|
||||
@@ -119,7 +123,9 @@ pub(crate) fn key_token(k: KeyCode, layout: &LayoutNames) -> Option<KeyName> {
|
||||
/// codes the table cannot name, `0x210` and `0x211` (ScrollLock and Pause, and F14 and F15 on a
|
||||
/// Mac). Every other key without a name never reaches the walk: the Windows key table drops it
|
||||
/// where `MapVirtualKeyA` answers 0 (`0x42da39`: the Windows and Menu keys, media keys, a key the
|
||||
/// layout drops), the Mac client's table `0x5bf320` has -1 for Command and fn. Unlike
|
||||
/// layout drops), the Mac client's table `mac:5bf320` has -1 for Command and fn, and its modifier handler queues
|
||||
/// only Shift, Control and Option (`mac:08a06c`, `mac:08a0d3`, `mac:08a13a`), so Caps Lock queues
|
||||
/// nothing. Unlike
|
||||
/// [`key_token`], which is a binding's, a modifier still gets a down and an up.
|
||||
pub(crate) fn walk_name(k: KeyCode, layout: &LayoutNames) -> Option<String> {
|
||||
if let Some(name) = key_token(k, layout) {
|
||||
@@ -157,23 +163,27 @@ fn fixed_name(k: KeyCode) -> Option<KeyName> {
|
||||
F10 => Word("F10"),
|
||||
F11 => Word("F11"),
|
||||
F12 => Word("F12"),
|
||||
// On a Mac F13 is print-screen: the Mac client's key table `0x5bf320` maps keycode
|
||||
// `0x69` to `0x212`, `PRINTSCREEN`, and macOS has no PrintScreen keycode.
|
||||
// On a Mac F13 is print-screen: the Mac client's key table `mac:5bf320` maps keycode
|
||||
// `0x69` to `0x212`, which the namer calls `PRINTSCREEN` (`mac:1de30e`), and macOS has no PrintScreen keycode.
|
||||
#[cfg(target_os = "macos")]
|
||||
F13 => Word("PRINTSCREEN"),
|
||||
// `IsValidBindingKeyString` accepts `F` + any digits (`0x846c04`) and the Mac table maps
|
||||
// keycode `0x6A` to `F16` (`0x30d`). Deviation: the Windows key table stops at `VK_F12`
|
||||
// keycode `0x6A` to `0x30d`, which the namer calls `F16` (`mac:1de48a`). Deviation: the Windows key table stops at `VK_F12`
|
||||
// and drops later F-keys; they are named here because that way a stored `F13`-`F24` can be
|
||||
// pressed.
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
F13 => Word("F13"),
|
||||
// On a Mac F14 and F15 are ScrollLock and Pause: keycodes `0x6B` and `0x71` map to
|
||||
// `0x210` and `0x211`, which the namer calls `UNKNOWN`, so they stay unbindable there.
|
||||
// `0x210` and `0x211`, which the namer calls `UNKNOWN` (`mac:5bf320`, `mac:1de334`), so they stay
|
||||
// unbindable there.
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
F14 => Word("F14"),
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
F15 => Word("F15"),
|
||||
F16 => Word("F16"),
|
||||
// The Mac table leaves keycodes 0x40, 0x4f, 0x50 and 0x5a (F17-F20) at -1 (`mac:5bf320`),
|
||||
// which `KeyTranslate` fills from the layout (`mac:08a3c3`), so the reference's name for
|
||||
// them depends on the OS; these are benilla's.
|
||||
F17 => Word("F17"),
|
||||
F18 => Word("F18"),
|
||||
F19 => Word("F19"),
|
||||
@@ -218,6 +228,9 @@ fn fixed_name(k: KeyCode) -> Option<KeyName> {
|
||||
PrintScreen => Word("PRINTSCREEN"),
|
||||
// No ScrollLock or Pause: the namer (`0x4b66b0`) calls `0x210`/`0x211` `UNKNOWN`, and
|
||||
// `IsValidBindingKeyString` (`0x4b7890`) has neither name.
|
||||
// The Mac client queues no Caps Lock key (`mac:08a06c`): its modifier handler tests only
|
||||
// Shift, Control and Option, though the table `mac:5bf320` maps keycode 0x39 to `0x20e`.
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
CapsLock => Word("CAPSLOCK"),
|
||||
_ => return None,
|
||||
})
|
||||
@@ -391,7 +404,6 @@ mod tests {
|
||||
KeyCode::PageUp,
|
||||
KeyCode::PageDown,
|
||||
KeyCode::NumLock,
|
||||
KeyCode::CapsLock,
|
||||
KeyCode::PrintScreen,
|
||||
KeyCode::Minus,
|
||||
KeyCode::Equal,
|
||||
@@ -462,13 +474,15 @@ mod tests {
|
||||
"PAGEUP",
|
||||
"PAGEDOWN",
|
||||
"NUMLOCK",
|
||||
"CAPSLOCK",
|
||||
"PRINTSCREEN",
|
||||
"MOUSEWHEELDOWN",
|
||||
"MOUSEWHEELUP",
|
||||
]
|
||||
.map(str::to_string),
|
||||
);
|
||||
// The Mac client queues no Caps Lock key (`mac:08a06c`).
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
tokens.push("CAPSLOCK".to_string());
|
||||
tokens.extend(
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=[]\\;',./`"
|
||||
.chars()
|
||||
@@ -488,6 +502,24 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// Caps Lock is a key on Windows and Linux (`CAPSLOCK`); the Mac client's modifier handler
|
||||
/// queues only Shift, Control and Option (`mac:08a06c`), so it names and binds nothing there.
|
||||
#[test]
|
||||
fn caps_lock_is_a_key_only_off_the_mac() {
|
||||
let us = LayoutNames::default();
|
||||
let named = key_token(KeyCode::CapsLock, &us);
|
||||
let parsed = Chord::parse("CAPSLOCK");
|
||||
if cfg!(target_os = "macos") {
|
||||
assert_eq!((named, parsed), (None, None));
|
||||
} else {
|
||||
assert_eq!(named, Some(KeyName::Word("CAPSLOCK")));
|
||||
assert_eq!(
|
||||
parsed.map(|c| c.key),
|
||||
Some(BindKey::Key(KeyName::Word("CAPSLOCK")))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_codec_round_trips_every_keyboard_token() {
|
||||
let us = LayoutNames::default();
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
//! outside its fixed table, `VK_A`-`VK_Z` and `VK_OEM_*` among them, to
|
||||
//! `MapVirtualKeyA(vk, MAPVK_VK_TO_CHAR)` (`0x42da39`), which returns `VK_A`-`VK_Z`'s own letter
|
||||
//! whatever the layout types there. The Mac client fills its letter and punctuation keys from the
|
||||
//! live layout, `KeyTranslate` (`0x8a3c3`) on the current `KCHR` (re-read when it changes,
|
||||
//! `0x8a345`), and fixes its digits by position (`0x5bf320`). Bevy's `KeyboardInput` carries the
|
||||
//! live layout, `KeyTranslate` (`mac:08a3c3`) on the current `KCHR` (re-read when it changes,
|
||||
//! `mac:08a345`), and fixes its digits by position (`mac:5bf320`). Bevy's `KeyboardInput` carries the
|
||||
//! physical key and a `logical_key` with Shift applied, so each platform's name is read off the
|
||||
//! raw winit key messages here, before any `Update` reader.
|
||||
|
||||
@@ -35,7 +35,7 @@ impl Position {
|
||||
/// The keys a layout names: the letters, the digits, the punctuation, the ISO and JIS extras and
|
||||
/// the keypad comma. Windows sends `VK_OEM_102`, `VK_ABNT_C2` and `VK_SEPARATOR` to the layout arm
|
||||
/// like any `VK_OEM_*` key, and the Mac client's table leaves the ISO key `0x0A` and keypad comma
|
||||
/// `0x5F` to `KeyTranslate` (`-1` at `0x5bf320`). winit 0.30 cannot deliver those on a Mac, as on
|
||||
/// `0x5F` to `KeyTranslate` (`-1` at `mac:5bf320`). winit 0.30 cannot deliver those on a Mac, as on
|
||||
/// main: it reports `0x0A` as `Backquote` (whose scancode it gives back as `0x32`) and leaves
|
||||
/// `0x5E` and `0x5F` unidentified, so the `IntlBackslash`, `IntlRo` and `NumpadComma` arms never
|
||||
/// fire there.
|
||||
@@ -114,7 +114,7 @@ impl LayoutNames {
|
||||
/// reported (a headless run) keeps its US name.
|
||||
///
|
||||
/// Deviation: on the Mac and Linux a key its platform reports no character for keeps its US
|
||||
/// name too, where the Mac reference drops it (`0x8a4aa`), and a Linux dead key not yet pressed
|
||||
/// name too, where the Mac reference drops it (`mac:08a4aa`), and a Linux dead key not yet pressed
|
||||
/// bare stays bindable.
|
||||
pub(crate) fn name(&self, key: KeyCode) -> Option<LayoutName> {
|
||||
let position = position(key)?;
|
||||
@@ -289,13 +289,13 @@ mod windows {
|
||||
///
|
||||
/// Deviation: a layout that is not ASCII-capable (Hebrew, Greek, Russian, Arabic, Thai) names its
|
||||
/// keys through the ASCII-capable layout macOS pairs with it, as macOS names its own shortcuts,
|
||||
/// because the reference reads a non-Roman `KCHR`'s byte as MacRoman (`0x8a40f`), which names no
|
||||
/// because the reference reads a non-Roman `KCHR`'s byte as MacRoman (`mac:08a40f`), which names no
|
||||
/// real key.
|
||||
///
|
||||
/// Deviation: a character above U+00FF (Czech `ě`, Polish `ł`, Turkish `ş`) names the key by itself
|
||||
/// because the reference reads `KeyTranslate`'s byte as MacRoman (`0x8a40f`) and keeps it only if
|
||||
/// it converts to Latin-1 (`CFStringGetBytes`, `0x8a46b`, stored at `0x8a482`), else leaves the
|
||||
/// slot `-1`, which `0x8a4aa` drops, so such a key is mislabelled or dropped; named by what it
|
||||
/// because the reference reads `KeyTranslate`'s byte as MacRoman (`mac:08a40f`) and keeps it only if
|
||||
/// it converts to Latin-1 (`CFStringGetBytes`, `mac:08a46b`, stored at `mac:08a482`), else leaves the
|
||||
/// slot `-1`, which `mac:08a4aa` drops, so such a key is mislabelled or dropped; named by what it
|
||||
/// types, it stays bindable and readable.
|
||||
#[cfg(any(target_os = "macos", test))]
|
||||
fn mac_name(
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
//! Off macOS, each keyboard message whose logical key is a named key other than its physical one
|
||||
//! takes that named key's code, before Bevy's input collection, so every reader (the bindings,
|
||||
//! the text boxes, the glue screens, `ButtonInput<KeyCode>`) sees the layout's key. The Mac client
|
||||
//! reads its non-character keys off a fixed table on the physical keycode (`0x5bf320`), so macOS
|
||||
//! reads its non-character keys off a fixed table on the physical keycode (`mac:5bf320`), so macOS
|
||||
//! keeps them physical. A letter, digit or punctuation key keeps its code too: 1.12 names it by
|
||||
//! the virtual key the layout makes it, a digit as itself (`0x42d81c`) and a letter or punctuation
|
||||
//! key through `MapVirtualKeyA` (`0x42da39`), which the game's key namer reads, not by a named
|
||||
|
||||
+7
-6
@@ -29,7 +29,7 @@ A setting boots at the reference's default unless it is listed here (`docs/METHO
|
||||
|
||||
Each entry is the first sentence of a `Deviation:` comment, linking to where it lives.
|
||||
|
||||
- [benilla-app](#benilla-app): 254
|
||||
- [benilla-app](#benilla-app): 255
|
||||
- [benilla-assets](#benilla-assets): 6
|
||||
- [benilla-blp](#benilla-blp): 1
|
||||
- [benilla-formats](#benilla-formats): 24
|
||||
@@ -74,14 +74,15 @@ Each entry is the first sentence of a `Deviation:` comment, linking to where it
|
||||
|
||||
#### bindings
|
||||
|
||||
- A press with Super (Cmd) held runs no binding because that way a system chord such as Cmd+Tab or Cmd+Q never acts in game. The reference has no such modifier and runs the bare key's binding: the Mac enqueues the key with Command held and skips only its text (`0x8a519`), and Windows hands `VK_LWIN`/`VK_RWIN` to the layout arm (`0x42da39`) like any key. ([`src/bindings.rs:19`](../crates/benilla-app/src/bindings.rs#L19))
|
||||
- A press with Super (Cmd) held runs no binding because that way a system chord such as Cmd+Tab or Cmd+Q never acts in game. The reference has no such modifier and runs the bare key's binding: the Mac enqueues the key with Command held and skips only its text (`mac:08a51e`), and Windows hands `VK_LWIN`/`VK_RWIN` to the layout arm (`0x42da39`) like any key. ([`src/bindings.rs:19`](../crates/benilla-app/src/bindings.rs#L19))
|
||||
- A trackpad's `Pixel` deltas are carried until they make a line, and step at most once per event (`crate::ui_script::Record::Wheel`). The reference steps on every `WM_MOUSEWHEEL`, whatever its delta (`0x76c1a9`); the carry is kept because a carried trackpad does not zoom or scroll at its event rate. ([`src/bindings.rs:637`](../crates/benilla-app/src/bindings.rs#L637))
|
||||
- Latches die with the VM that made them, because a latch names a command of that VM's table and releasing it against a new one would run another load's up-half. The reference keeps a held key running through `ReloadUI`; here it re-latches on its next press. The held bits die with it, as the key's Stop would have cleared them. ([`src/bindings.rs:682`](../crates/benilla-app/src/bindings.rs#L682))
|
||||
- The Windows key table stops at `VK_F12` and drops later F-keys; they are named here because that way a stored `F13`-`F24` can be pressed. ([`src/bindings/chord.rs:165`](../crates/benilla-app/src/bindings/chord.rs#L165))
|
||||
- On the Mac and Linux a key its platform reports no character for keeps its US name too, where the Mac reference drops it (`0x8a4aa`), and a Linux dead key not yet pressed bare stays bindable. ([`src/bindings/layout.rs:116`](../crates/benilla-app/src/bindings/layout.rs#L116))
|
||||
- The Z key is named `Z` on a Mac too, because the Mac client uppercases only `a`-`y` (`mac:08a3df`) and so names it `z`, which no binding can press; that fault would leave a binding to `Z`, the stock `TOGGLESHEATH` key, unreachable there. ([`src/bindings/chord.rs:111`](../crates/benilla-app/src/bindings/chord.rs#L111))
|
||||
- The Windows key table stops at `VK_F12` and drops later F-keys; they are named here because that way a stored `F13`-`F24` can be pressed. ([`src/bindings/chord.rs:171`](../crates/benilla-app/src/bindings/chord.rs#L171))
|
||||
- On the Mac and Linux a key its platform reports no character for keeps its US name too, where the Mac reference drops it (`mac:08a4aa`), and a Linux dead key not yet pressed bare stays bindable. ([`src/bindings/layout.rs:116`](../crates/benilla-app/src/bindings/layout.rs#L116))
|
||||
- A character above U+00FF names the key by itself because the reference's `MapVirtualKeyA` returns an ANSI code-page byte, which `0x42da4b` drops past `0xff` and the namer's UTF-8 encoder (`0x41abb0`) otherwise reads as Latin-1, so such a key is mislabelled or dropped; named by what it types, it stays bindable and readable. ([`src/bindings/layout.rs:216`](../crates/benilla-app/src/bindings/layout.rs#L216))
|
||||
- A layout that is not ASCII-capable (Hebrew, Greek, Russian, Arabic, Thai) names its keys through the ASCII-capable layout macOS pairs with it, as macOS names its own shortcuts, because the reference reads a non-Roman `KCHR`'s byte as MacRoman (`0x8a40f`), which names no real key. ([`src/bindings/layout.rs:290`](../crates/benilla-app/src/bindings/layout.rs#L290))
|
||||
- A character above U+00FF (Czech `ě`, Polish `ł`, Turkish `ş`) names the key by itself because the reference reads `KeyTranslate`'s byte as MacRoman (`0x8a40f`) and keeps it only if it converts to Latin-1 (`CFStringGetBytes`, `0x8a46b`, stored at `0x8a482`), else leaves the slot `-1`, which `0x8a4aa` drops, so such a key is mislabelled or dropped; named by what it types, it stays bindable and readable. ([`src/bindings/layout.rs:295`](../crates/benilla-app/src/bindings/layout.rs#L295))
|
||||
- A layout that is not ASCII-capable (Hebrew, Greek, Russian, Arabic, Thai) names its keys through the ASCII-capable layout macOS pairs with it, as macOS names its own shortcuts, because the reference reads a non-Roman `KCHR`'s byte as MacRoman (`mac:08a40f`), which names no real key. ([`src/bindings/layout.rs:290`](../crates/benilla-app/src/bindings/layout.rs#L290))
|
||||
- A character above U+00FF (Czech `ě`, Polish `ł`, Turkish `ş`) names the key by itself because the reference reads `KeyTranslate`'s byte as MacRoman (`mac:08a40f`) and keeps it only if it converts to Latin-1 (`CFStringGetBytes`, `mac:08a46b`, stored at `mac:08a482`), else leaves the slot `-1`, which `mac:08a4aa` drops, so such a key is mislabelled or dropped; named by what it types, it stays bindable and readable. ([`src/bindings/layout.rs:295`](../crates/benilla-app/src/bindings/layout.rs#L295))
|
||||
- The reference saves a full snapshot (`bindings-cache.wtf`); a diff is stored because a full snapshot would leave every command added later unbound for a saved file. ([`src/bindings/store.rs:13`](../crates/benilla-app/src/bindings/store.rs#L13))
|
||||
|
||||
#### blob_shadow
|
||||
|
||||
Reference in New Issue
Block a user