A chorded action button must run both halves, and now a test says so

grom's slam macro sits on SHIFT-1, which his bindings file resolves to
MULTIACTIONBAR1BUTTON1, and pfUI points both `MultiActionButtonDown` and
`MultiActionButtonUp` at the same `pfActionButton` (`modules/actionbar.lua`
:1516-17), which calls `frame:Click()`. So the reference evaluates that macro
twice per press — once on the press, once on the release — and he reported
seeing it evaluate once. That second evaluation is a second roll at a 0.2 s
no-clip window, so it is worth a test of its own.

The test holds a modifier across both edges, as a hand holding shift does, and
asserts the down half on the press and the up half on the release. It passes:
the registry's `Kind::EdgeUpDown` does run both legs through a chord. The
harness says the same one layer up — `MultiActionButtonDown` and
`MultiActionButtonUp` each reach `UseAction` exactly once with pfUI loaded —
so whatever is costing him the second evaluation is not in either of these two
layers, and this test is here to keep it that way while the search goes on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
2026-10-31 09:15:08 -06:00
co-authored by Claude Opus 5
parent 3f29824458
commit 89556c991a
+46
View File
@@ -899,6 +899,52 @@ mod tests {
.expect("eval")
}
/// A **chorded** registry `EdgeUpDown` runs both halves, which is what an action button on a
/// modified key is.
///
/// grom's slam macro sits on `SHIFT-1` → `MULTIACTIONBAR1BUTTON1`
/// (`bindings/C_Thun-Gromgosh.txt:28`), and pfUI points both `MultiActionButtonDown` and
/// `MultiActionButtonUp` at the same `pfActionButton` (`modules/actionbar.lua:1516-17`), so
/// the reference runs his macro twice per press — once on the press, once on the release —
/// and he reported seeing it run once. Both halves have to reach the VM for that second roll
/// at a 0.2 s window to exist.
#[test]
fn a_chorded_action_button_runs_both_halves() {
let mut script = UiScript::new().expect("VM");
script.register_bindings(&registry_commands());
script
.run(
"MULTI_DOWN = 0 MULTI_UP = 0 \
function MultiActionButtonDown() MULTI_DOWN = MULTI_DOWN + 1 end \
function MultiActionButtonUp() MULTI_UP = MULTI_UP + 1 end \
SetBinding(\"SHIFT-1\", \"MULTIACTIONBAR1BUTTON1\")",
)
.expect("bind");
let mut app = vm_harness(script);
// The modifier is held across both edges, as a hand holding shift is.
press_key(&mut app, KeyCode::ShiftLeft);
app.update();
press_key(&mut app, KeyCode::Digit1);
app.update();
assert_eq!(lua_count(&app, "MULTI_DOWN"), 1, "the press half");
assert_eq!(lua_count(&app, "MULTI_UP"), 0, "not released yet");
release_key(&mut app, KeyCode::Digit1);
app.update();
assert_eq!(
lua_count(&app, "MULTI_UP"),
1,
"the release half — the second evaluation of the macro"
);
assert_eq!(
lua_count(&app, "MULTI_DOWN"),
1,
"and not the down half again"
);
}
/// An addon's `runOnUp` body is one chunk run twice, `keystate` "down" then "up"; our own
/// registry holds two strings ([`Kind::EdgeUpDown`]) instead.
#[test]