Skip to content

fix(hotkeys): match terminal Ctrl chords by event.code under non-Latin IME#3405

Closed
AytuncYildizli wants to merge 1 commit into
superset-sh:mainfrom
AytuncYildizli:fix/hotkeys-ime-terminal-chords
Closed

fix(hotkeys): match terminal Ctrl chords by event.code under non-Latin IME#3405
AytuncYildizli wants to merge 1 commit into
superset-sh:mainfrom
AytuncYildizli:fix/hotkeys-ime-terminal-chords

Conversation

@AytuncYildizli
Copy link
Copy Markdown

@AytuncYildizli AytuncYildizli commented Apr 13, 2026

Summary / What changed

  • matchesHotkeyEvent (apps/desktop/src/shared/hotkeys.ts): when the parsed hotkey is a single letter a–z, also match against event.code (KeyAKeyZ). Mirrors the existing digit-key fallback at line 272.
  • Two new regression tests in hotkeys.test.ts cover Turkish (ç + KeyC) and Korean ( + KeyD).

Why

Originally reported by @eungkyu in #3365 for Korean 2-Set IME. Same bug reproduces on Turkish layout: Ctrl+C emits event.key = "ç" while event.code stays "KeyC". Without the fallback, terminal-reserved chords (Ctrl+C/D/Z/V…) stop reaching the PTY whenever a non-Latin IME is active.

The patch is intentionally narrow: only single-letter a–z hotkeys gain the event.code fallback. This keeps existing matching behavior for everything else and follows the same pattern the code already uses for digits and slash.

Tests

  • bun test apps/desktop/src/shared/hotkeys.test.ts
  • 15/15 pass (13 existing + 2 new IME regressions).

Real-world validation

Issue

Fixes #3365.


Summary by cubic

Fixes terminal Ctrl letter chords failing under non-Latin IMEs by matching single-letter hotkeys against event.code (KeyAKeyZ) in matchesHotkeyEvent (fixes #3365). Adds regression tests for Turkish (ç + KeyC) and Korean ( + KeyD).

Written for commit c4f5db0. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes
    • Improved hotkey detection reliability when using non-Latin keyboard layouts or IME input methods. Hotkeys like Ctrl+C and Ctrl+D now work correctly even when keyboard input transforms key values.

… non-Latin IME

When a non-Latin IME is active (Turkish, Korean, Russian, etc.), `event.key`
returns the IME-transformed character: Ctrl+C reports `ç` on Turkish, `ㅇ` on
Korean 2-Set, etc. `matchesHotkeyEvent` only compared against `event.key`,
so `Ctrl+C/D/Z` and other terminal-reserved chords stopped reaching the PTY
under those layouts.

Add a fallback that matches single-letter shortcuts against `event.code`
(`KeyA`–`KeyZ`), mirroring the existing pattern for digit keys (line 272).
The physical key is layout-independent, so the chord is detected regardless
of IME state.

Tests: 15/15 pass, including two new regressions for Turkish (`ç` + `KeyC`)
and Korean (`ㅇ` + `KeyD`).

Fixes superset-sh#3365.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fc713819-acd1-4e78-9fd5-6ddfd5ccd554

📥 Commits

Reviewing files that changed from the base of the PR and between 102633c and c4f5db0.

📒 Files selected for processing (2)
  • apps/desktop/src/shared/hotkeys.test.ts
  • apps/desktop/src/shared/hotkeys.ts

📝 Walkthrough

Walkthrough

The changes extend hotkey handling to support non-Latin IME layouts by using event.code (physical key) as a fallback when event.key (logical key) is IME-transformed, including new regression tests to verify this behavior.

Changes

Cohort / File(s) Summary
Test Coverage for IME Scenarios
apps/desktop/src/shared/hotkeys.test.ts
Adds two regression tests for isTerminalReservedEvent: verifies ctrl+c detection when key is IME-transformed to "ç" but code: "KeyC" is present, and ctrl+d detection when key is IME-transformed to "ㅇ" but code: "KeyD" is present. Ensures detection relies on event.code under non-Latin IME scenarios.
IME-Aware Hotkey Matching
apps/desktop/src/shared/hotkeys.ts
Adds fallback match path in matchesHotkeyEvent for single-letter hotkeys: when configured key is lowercase ASCII and event.code matches the key pattern, returns true before final normalization comparison, enabling hotkey matching when event.key is IME-transformed but event.code remains stable.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A keyboard dance, yet keyboards speak true,
Regardless of tongue or the IME you use,
Code holds the secret, not keys re-arranged,
Now hotkeys flow freely where characters changed!
The rabbit hops forward, all languages freed.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: fixing hotkey matching for terminal Ctrl chords under non-Latin IME by using event.code instead of event.key.
Description check ✅ Passed The PR description comprehensively covers the change, includes related issue links, testing results, and real-world validation. It matches the template structure with summary, justification, and tests.
Linked Issues check ✅ Passed The PR fully addresses issue #3365 by implementing the proposed fix: matchesHotkeyEvent now matches single-letter hotkeys against event.code (KeyA-KeyZ) for IME-independent terminal reserved chord detection.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing issue #3365: hotkeys.ts adds event.code matching for single-letter hotkeys, and hotkeys.test.ts adds regression tests for Turkish and Korean IME scenarios.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch fix/hotkeys-ime-terminal-chords

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 13, 2026

Greptile Summary

This PR adds a narrow IME/non-Latin keyboard layout fallback inside matchesHotkeyEvent so that terminal-reserved Ctrl chords (Ctrl+C, Ctrl+D, Ctrl+Z, etc.) continue to fire when a non-Latin input method (Turkish, Korean, Russian, etc.) is active and event.key carries the IME-transformed character instead of the Latin base key. The fix mirrors the existing digit-key fallback pattern already in the codebase and is accompanied by two targeted regression tests.

Key changes:

  • apps/desktop/src/shared/hotkeys.ts: A single new if-block in matchesHotkeyEvent that checks event.code (e.g., \"keyc\") when the parsed hotkey has a single a–z key and event.key didn't already produce a match.
  • apps/desktop/src/shared/hotkeys.test.ts: Two new regression tests under isTerminalReservedEvent covering the Turkish (ç/KeyC) and Korean (/KeyD) IME scenarios.

Confidence Score: 5/5

Safe to merge — the change is minimal, intentionally narrow, follows an established in-codebase pattern, and is covered by two targeted regression tests.

The fix is a single if-block that only activates for single a–z hotkeys via event.code, mirroring the digit-key fallback already present. Logic is correct, the test suite passes (15/15), and there are no side effects on non-Latin-key or non-letter hotkeys. The only finding is a trivial redundant guard (key.length === 1) that has no runtime impact.

No files require special attention.

Important Files Changed

Filename Overview
apps/desktop/src/shared/hotkeys.ts Adds a single a–z event.code fallback in matchesHotkeyEvent to handle IME-mangled event.key; logic is correct and follows the existing digit-key pattern at line 272.
apps/desktop/src/shared/hotkeys.test.ts Two new regression tests for Turkish and Korean IME scenarios added under isTerminalReservedEvent; both tests are well-structured and cover the exact bug report from issue #3365.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[matchesHotkeyEvent called] --> B{canonicalizeHotkey returns key?}
    B -- No --> Z1[return false]
    B -- Yes --> C{Modifier keys match?}
    C -- No --> Z2[return false]
    C -- Yes --> D{key === 'slash'?}
    D -- Yes --> E{eventKey or eventCode === 'slash'?}
    E -- Yes --> Z3[return true]
    E -- No --> F{Arrow key alias match?}
    D -- No --> F
    F -- Yes --> Z4[return true]
    F -- No --> G{key matches digit pattern AND eventCode === digit+key?}
    G -- Yes --> Z5[return true]
    G -- No --> H{key is single a-z AND eventCode === 'key'+key?}
    H -- Yes --> Z6[return true - NEW: IME fallback]
    H -- No --> I{eventKey === key?}
    I -- Yes --> Z7[return true]
    I -- No --> Z8[return false]
    style Z6 fill:#22c55e,color:#fff
    style H fill:#bbf7d0
Loading

Reviews (1): Last reviewed commit: "fix(hotkeys): match terminal-reserved Ct..." | Re-trigger Greptile

Comment on lines +279 to +281
if (key.length === 1 && /^[a-z]$/.test(key) && eventCode === `key${key}`) {
return true;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redundant key.length === 1 guard

The leading key.length === 1 check is already implied by /^[a-z]$/.test(key) — the anchored single-character regex can only ever match a string of length 1. Dropping it makes the condition a little cleaner and avoids the reader wondering whether the two predicates cover different cases.

Suggested change
if (key.length === 1 && /^[a-z]$/.test(key) && eventCode === `key${key}`) {
return true;
}
if (/^[a-z]$/.test(key) && eventCode === `key${key}`) {

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@AytuncYildizli
Copy link
Copy Markdown
Author

Closing — investigated further and realized this PR targets apps/desktop/src/shared/hotkeys.ts which was removed in the v1.5.x migration. The active code path is now apps/desktop/src/renderer/hotkeys/utils/resolveHotkeyFromEvent.ts which already uses event.code (fixed in #3391). Sorry for the noise. Will re-investigate the user-facing report and open a fresh issue if the bug is reproducible on the current code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Terminal-reserved Ctrl chords (Ctrl+C/D/Z…) fail under non-Latin IME (e.g. Korean)

1 participant