You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Fix Ctrl+C / Ctrl+V not working on non-Latin keyboard layouts - #220
First of all β thank you for wmux. I have been using it almost since the very first releases, and it is honestly the best thing I have found for Windows. It is open on my machine all day long.
There is one thing I have been waiting for in every single update: Ctrl+C simply does not work while my keyboard layout is set to Russian. I switch layouts dozens of times a day, and every time I want to copy something out of the terminal I first have to switch back to English. After waiting for a while I decided to just sit down and fix it myself.
And it is not only about Russian. The exact same thing happens on every non-Latin layout β Ukrainian, Bulgarian, Serbian, Greek, Hebrew, Arabic, Armenian, Georgian and others. So this small change helps quite a lot of people at once.
Thank you again for everything you put into this project β it is genuinely the best terminal experience on Windows. π
What goes wrong
The terminal key handler matches the shortcut against event.key:
event.key is the character the key produces with the current layout. On a Russian layout that physical key produces Ρ β U+0441, Cyrillic "es" β and not c β U+0063, Latin "c". The two look identical on screen but they are different characters, so the condition is never true. The keystroke then falls through to the PTY as a plain ^C, which is why copying silently does nothing and the running command gets interrupted instead. Ctrl+V has the same problem.
Native Windows applications do not suffer from this because they match virtual-key codes, which are layout-independent. That is why Ctrl+C works everywhere else in the OS and this looks like a wmux-specific bug to the user.
The fix
event.code is the physical key and never changes with the layout: KeyC stays KeyC on Russian, Greek, Hebrew or anything else. Fixing all of them therefore does not need a list of languages β one check is enough.
Matching on event.code alone would be wrong, though. On Dvorak or Colemak the user presses the key that shows C, which is physically a different key. So event.key is still checked first, and event.code is only used as a fallback when the produced character is not a Latin letter:
The predicate lives in src/renderer/hooks/terminal-keys.ts, next to isShiftEnter, so it can be tested without spinning up Electron.
What is deliberately not changed
Ctrl+C with no selection still falls through to the PTY as ^C (SIGINT). Only the "there is a selection, so copy it" branch is affected, exactly as before.
Ctrl+Shift+C is unchanged on Latin layouts: Shift uppercases event.key, so it arrives as C, which is still a Latin letter and therefore never reaches this branch β it goes to the global copy shortcut as it always did. On a non-Latin layout it now lands in the terminal copy branch, which does the same thing the copy shortcut would have done; previously it did nothing at all there, because the global handler compares characters too.
The trimTrailingWhitespace handling from copy bugΒ #102 and the preventDefault that stops the double paste are kept as they were.
Tests
Added unit tests in tests/unit/terminal-keys.test.ts covering Latin, Cyrillic, Greek and both Dvorak directions.
Also verified manually on Windows 10 with Russian and English layouts:
Russian layout, text selected, Ctrl+C β copies (was: nothing, and the command got interrupted)
Russian layout, nothing selected, Ctrl+C β still interrupts the command
Russian layout, Ctrl+V β pastes
English layout β behaves exactly as before
npm test, npm run typecheck and npm run lint are all as green as they are on master. (The one failing test I see locally, pty-manager β "finds a real file for pwsh", fails on a clean master checkout too β PowerShell 7 is simply not installed on this machine.)
A note for a possible follow-up
The same symbol-based matching lives in useKeyboardShortcuts.ts and key-remaps.ts, which means that on a non-Latin layout none of the letter shortcuts work, not just copy and paste. I kept this PR narrow on purpose, but I would be happy to send a follow-up with the same treatment if you think it is worth it.
Merged β thank you, and thank you for the kind words about wmux. π
This is the right diagnosis and the right fix. The part I want to call out for anyone reading later is the bit that's easy to get wrong: matching on event.codealone would have "fixed" Cyrillic and quietly broken Dvorak and Colemak, where the user presses the key that shows C and that key is physically KeyI. Checking event.key first and falling back to code only when the produced character isn't a Latin letter is what makes this correct for both directions at once β and your table plus the two Dvorak test cases are what prove it, including the one that must NOT match (physical KeyC producing j).
The Ctrl+Shift+C reasoning is also correct and worth having written down: Shift uppercases event.key to C, which is still Latin, so it never enters this branch on a Latin layout and still reaches the global copy shortcut. On a non-Latin layout it now lands in the terminal copy branch and does the same thing the global shortcut would have β which is strictly better than the nothing it did before.
Shipping in v2.9.3.
On your follow-up offer: yes, please. useKeyboardShortcuts.ts and key-remaps.ts comparing characters means that on a Russian layout essentially the whole shortcut table is dead, not just copy/paste β which is a much bigger papercut than this one and the same predicate solves it. Two things worth keeping in mind when you get to it:
key-remaps.ts is user-authored config ([keys] in config.toml), so whatever a user wrote there is a character they typed and expects to match by character. The code fallback has to be additive, never a reinterpretation of an existing binding.
Keep it as narrow per-PR as you did here and it'll go in just as fast.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hi! π
First of all β thank you for wmux. I have been using it almost since the very first releases, and it is honestly the best thing I have found for Windows. It is open on my machine all day long.
There is one thing I have been waiting for in every single update:
Ctrl+Csimply does not work while my keyboard layout is set to Russian. I switch layouts dozens of times a day, and every time I want to copy something out of the terminal I first have to switch back to English. After waiting for a while I decided to just sit down and fix it myself.And it is not only about Russian. The exact same thing happens on every non-Latin layout β Ukrainian, Bulgarian, Serbian, Greek, Hebrew, Arabic, Armenian, Georgian and others. So this small change helps quite a lot of people at once.
Thank you again for everything you put into this project β it is genuinely the best terminal experience on Windows. π
What goes wrong
The terminal key handler matches the shortcut against
event.key:event.keyis the character the key produces with the current layout. On a Russian layout that physical key producesΡβ U+0441, Cyrillic "es" β and notcβ U+0063, Latin "c". The two look identical on screen but they are different characters, so the condition is never true. The keystroke then falls through to the PTY as a plain^C, which is why copying silently does nothing and the running command gets interrupted instead.Ctrl+Vhas the same problem.Native Windows applications do not suffer from this because they match virtual-key codes, which are layout-independent. That is why
Ctrl+Cworks everywhere else in the OS and this looks like a wmux-specific bug to the user.The fix
event.codeis the physical key and never changes with the layout:KeyCstaysKeyCon Russian, Greek, Hebrew or anything else. Fixing all of them therefore does not need a list of languages β one check is enough.Matching on
event.codealone would be wrong, though. On Dvorak or Colemak the user presses the key that shows C, which is physically a different key. Soevent.keyis still checked first, andevent.codeis only used as a fallback when the produced character is not a Latin letter:event.keyevent.codecKeyCcKeyCΡ,Ο,Χβ¦KeyCcKeyIj)jKeyCThe predicate lives in
src/renderer/hooks/terminal-keys.ts, next toisShiftEnter, so it can be tested without spinning up Electron.What is deliberately not changed
Ctrl+Cwith no selection still falls through to the PTY as^C(SIGINT). Only the "there is a selection, so copy it" branch is affected, exactly as before.Ctrl+Shift+Cis unchanged on Latin layouts: Shift uppercasesevent.key, so it arrives asC, which is still a Latin letter and therefore never reaches this branch β it goes to the globalcopyshortcut as it always did. On a non-Latin layout it now lands in the terminal copy branch, which does the same thing thecopyshortcut would have done; previously it did nothing at all there, because the global handler compares characters too.trimTrailingWhitespacehandling from copy bugΒ #102 and thepreventDefaultthat stops the double paste are kept as they were.Tests
Added unit tests in
tests/unit/terminal-keys.test.tscovering Latin, Cyrillic, Greek and both Dvorak directions.Also verified manually on Windows 10 with Russian and English layouts:
Ctrl+Cβ copies (was: nothing, and the command got interrupted)Ctrl+Cβ still interrupts the commandCtrl+Vβ pastesnpm test,npm run typecheckandnpm run lintare all as green as they are onmaster. (The one failing test I see locally,pty-managerβ "finds a real file for pwsh", fails on a cleanmastercheckout too β PowerShell 7 is simply not installed on this machine.)A note for a possible follow-up
The same symbol-based matching lives in
useKeyboardShortcuts.tsandkey-remaps.ts, which means that on a non-Latin layout none of the letter shortcuts work, not just copy and paste. I kept this PR narrow on purpose, but I would be happy to send a follow-up with the same treatment if you think it is worth it.