GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
fix(backend): ctrl+letter shortcuts get the keysym, not the control-transformed utf8
handle_key's Character fallback preferred event.utf8, which xkb runs
through the legacy control-character transformation while Ctrl is held
(ctrl+j = "\n", ctrl+a = 0x01, ...) — so app-side ctrl+<letter> matches
like settings' ctrl+j/k/i/u section nav could NEVER fire, from hardware
or injection alike. With Ctrl held the keysym (untransformed) is now
preferred; the utf8 path is unchanged otherwise, and KeyEvent.text still
carries the raw utf8.
Found by driving the newly modifier-capable ccectl key injection (cce
114ef89) on the nested rig: settings received Character("\n") ctrl=true.
After the fix, ctrl+j/k cycle the section highlight and ctrl+i/u
descend/ascend, verified by pixel diffs of the section borders.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Fb2AGNKjfQZxfbxP43fVbC
src/backend/window_runner.rs | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/backend/window_runner.rs b/src/backend/window_runner.rs
index 37c9b4a..f26037b 100644
--- a/src/backend/window_runner.rs
+++ b/src/backend/window_runner.rs
@@ -2615,7 +2615,19 @@ impl<A: Application> EngineState<A> {
xkeysym::Keysym::Shift_L | xkeysym::Keysym::Shift_R => Key::Named(NamedKey::Shift),
xkeysym::Keysym::F5 => Key::Named(NamedKey::F5),
_ => {
- if let Some(ref text) = event.utf8 {
+ // With Ctrl held, xkb's utf8 goes through the legacy control-character
+ // transformation (ctrl+j = "\n", ctrl+a = 0x01, ...); the keysym is
+ // untransformed, so prefer it there or ctrl+<letter> shortcuts can
+ // never match their letter.
+ if self.ctrl_pressed {
+ if let Some(ch) = event.keysym.key_char() {
+ Key::Character(ch.to_string())
+ } else if let Some(ref text) = event.utf8 {
+ Key::Character(text.clone())
+ } else {
+ return;
+ }
+ } else if let Some(ref text) = event.utf8 {
Key::Character(text.clone())
} else if let Some(ch) = event.keysym.key_char() {
Key::Character(ch.to_string())