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
Punctuation at 14th unique character position in Chromium/Electron #71
When typing into Chromium or Electron apps, if a punctuation character happens to be the 14th unique character in the string, wtype fails to type correctly.
# Focus a text field in Chromium/Vivaldi/any Electron app, then run:
wtype "abcdefghijklm?XYZ"# 14 unique chars, ? is 14th# Expected: abcdefghijklm?XYZ# Actual: abcdefghijklXYZ (? interpreted as backspace, deletes 'm')
wtype "abcdefghijklmn?XYZ"# 15 unique chars, ? is 15th# Expected: abcdefghijklmn?XYZ# Actual: abcdefghijklmn?XYZ (works correctly)
This seems to happen on specifically Chromium / electron apps (e.g. Vivaldi or Brave browser, Joplin, etc).
I think this might be related to keycode 22 being BackSpace in the standard evdev keymap:
If wtype assigns keycodes starting at 9, the 14th unique character would get keycode 22. Maybe Chromium is interpreting the raw keycode as BackSpace for certain characters despite the custom keymap?
Confirming this on Hyprland 0.56.2 / wtype 0.4, with measurements suggesting the scope is wider than the title. Posting in case it helps anyone arriving from one of the other reports.
It is positional, not character-specific
The 33-letter Cyrillic alphabet, every letter distinct, so position == assigned keycode:
Now т and с. So it is not "punctuation", and not any particular character — it is whichever keycode a character is assigned.
Indexing is per character, not per byte: н is at character index 14 but byte offset 28, and it produced a Tab (keycode 23). Byte indexing would have put it on keycode 37 (Control_L), which emits nothing.
Two distinct failure bands
Holding the client fixed and varying only the script, all three strings arranged so indices 13, 14 and 28 map to keycodes 22, 23 and 37:
I do not have an explanation for why the low band spares ASCII and would rather flag it than guess. A plausible direction is keysym representation — ASCII lands in 0x20–0x7E while non-ASCII becomes 0x01000000 + codepoint — but I have not verified that.
Not limited to Chromium/Electron
Same input, different clients, different collisions:
keycode
ghostty
foot
Obsidian (Electron)
22
broken
broken
broken
23
broken
broken
fine
37 / 64
fine
fine
broken
68–75
broken
broken
F9 only
Which collisions bite depends on which keys a client special-cases by scancode rather than by keysym. (This matches @cilki's comment above that it is not Electron-only.)
Damage can exceed the dropped character
In Obsidian, keycode 22 acts as a real BackSpace and deletes the preceding character:
sent: ...звучит как что-то очень нетехническое и от человека ... как всё работает.
got: ...учит как что-то очень нетеническое и от челека ... каксё работает.
звучит → учит, человека → челека, как всё → каксё. In ghostty the same keycode is swallowed silently. Either way there is no error.
⚠️ Beyond ~keycode 80 this stops being a text bug
A string with 151 distinct characters reaches keycode 159, which is where Super, Print Screen, the media keys and the XF86 keys live. Running that did not merely lose characters — it executed those keys: opened a calculator, took a screenshot, and changed the mode of the focused application.
So with enough distinct characters, wtype can trigger arbitrary system actions. Anyone reproducing this should stay inside the printable range.
Reproduction
wtype 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя'# indices 13,14 → keycodes 22,23
wtype 'αβγδεζηθικλμνξοπρστυφχψωΑΒΓΔΕΖΗΘΙ'# same indices, different script
Both reproduced identically across 11/11 runs. A short pure-ASCII string does not reproduce it — it has to reach keycode 37 or above.
Not expecting a fix here
Last commit on this repo is 2022-01-27, so this is documentation for the next person searching rather than a fix request. The same root cause appears to explain #72, #46, #58, #40, #31, #37, #38 and #76 (!/* as first character → keycode 9 → Escape). Both #4 ("Use libxkbcommon to generate the keymap string") and #5 ("Use input-method if available") point at the real fix.
Workaround
Any keycode-based approach inherits this. What works reliably is not typing at all: put the text on the clipboard as UTF-8 and issue a single paste — on Hyprland that can be done through the compositor's own key injection, with no virtual keyboard involved.
So the final characters aren’t simply getting lost: the n is typed successfully, then the period acts as Backspace and deletes it.
This confirms the keycode-22 explanation above. In wtype v0.4, each different character gets the next available keycode, starting at 9. Repeated characters reuse their assigned code. The period is the 14th different character in this sentence, so it gets keycode 22—the code normally used for the physical Backspace key.
A fix is to assign text only to keycodes normally used for printable characters, skipping keys such as Backspace, Escape and Tab. If there are more distinct characters than available codes, wtype can reuse those codes by updating the character map between completed keypresses.
Same thing here today, typing into Discord (Vesktop) on niri with wtype 0.4. A part of text that started with a space lost every space in it (slot 1 is Escape), and a period that was the 14th distinct character deleted the letter before it (slot 14 is Backspace). Letters on those slots come through fine. Emoji arrive cut to 16 bits with any keycode (U+1F916 shows up as U+F916), so that part is Chromium's keysym handling rather than the keymap. Pasting through the clipboard works around all of it.
Activity
cilki commentedon Feb 21, 2026
Took me forever to figure this one out. I use wtype for passwords and certain ones simply would not work. Now I know...
I don't find this to be limited to electron apps, though. It happens in my terminal as well.
hoblin commentedon Aug 15, 2026
[claude-opus-5] on behalf of hoblin
Confirming this on Hyprland 0.56.2 / wtype 0.4, with measurements suggesting the scope is wider than the title. Posting in case it helps anyone arriving from one of the other reports.
It is positional, not character-specific
The 33-letter Cyrillic alphabet, every letter distinct, so position == assigned keycode:
м(index 13 → keycode 22) vanishes;н(index 14 → keycode 23) arrives as a literal Tab.The same alphabet reversed moves the damage to different letters at the same indices:
Now
тandс. So it is not "punctuation", and not any particular character — it is whichever keycode a character is assigned.Indexing is per character, not per byte:
нis at character index 14 but byte offset 28, and it produced a Tab (keycode 23). Byte indexing would have put it on keycode 37 (Control_L), which emits nothing.Two distinct failure bands
Holding the client fixed and varying only the script, all three strings arranged so indices 13, 14 and 28 map to keycodes 22, 23 and 37:
n✅o✅C❌м❌н❌ы❌ξ❌ο❌Ε❌I do not have an explanation for why the low band spares ASCII and would rather flag it than guess. A plausible direction is keysym representation — ASCII lands in 0x20–0x7E while non-ASCII becomes
0x01000000 + codepoint— but I have not verified that.Not limited to Chromium/Electron
Same input, different clients, different collisions:
Which collisions bite depends on which keys a client special-cases by scancode rather than by keysym. (This matches @cilki's comment above that it is not Electron-only.)
Damage can exceed the dropped character
In Obsidian, keycode 22 acts as a real BackSpace and deletes the preceding character:
звучит→учит,человека→челека,как всё→каксё. In ghostty the same keycode is swallowed silently. Either way there is no error.A string with 151 distinct characters reaches keycode 159, which is where Super, Print Screen, the media keys and the XF86 keys live. Running that did not merely lose characters — it executed those keys: opened a calculator, took a screenshot, and changed the mode of the focused application.
So with enough distinct characters,
wtypecan trigger arbitrary system actions. Anyone reproducing this should stay inside the printable range.Reproduction
Both reproduced identically across 11/11 runs. A short pure-ASCII string does not reproduce it — it has to reach keycode 37 or above.
Not expecting a fix here
Last commit on this repo is 2022-01-27, so this is documentation for the next person searching rather than a fix request. The same root cause appears to explain #72, #46, #58, #40, #31, #37, #38 and #76 (
!/*as first character → keycode 9 → Escape). Both #4 ("Use libxkbcommon to generate the keymap string") and #5 ("Use input-method if available") point at the real fix.Workaround
Any keycode-based approach inherits this. What works reliably is not typing at all: put the text on the clipboard as UTF-8 and issue a single paste — on Hyprland that can be done through the compositor's own key injection, with no virtual keyboard involved.
cilki commentedon Aug 15, 2026
@hoblin We know what the problem is. Maybe you could have generated an MR instead?
hoblin commentedon Aug 16, 2026
Sorry, I'm not quite sure what MR is 🙃
tijszwinkels commentedon Sep 21, 2026
I reproduced this with wtype 0.4-2 on Arch, using Hyprland 0.56.2 and Chromium 153.0.8010.36 on Wayland:
The browser records these events when wtype reaches the period:
So the final characters aren’t simply getting lost: the n is typed successfully, then the period acts as Backspace and deletes it.
This confirms the keycode-22 explanation above. In wtype v0.4, each different character gets the next available keycode, starting at 9. Repeated characters reuse their assigned code. The period is the 14th different character in this sentence, so it gets keycode 22—the code normally used for the physical Backspace key.
A fix is to assign text only to keycodes normally used for printable characters, skipping keys such as Backspace, Escape and Tab. If there are more distinct characters than available codes, wtype can reuse those codes by updating the character map between completed keypresses.
MR forthcoming.
tijszwinkels commentedon Sep 21, 2026
Fixed in #77
fix(typer): type through printable keycodes only, without wtype
ayagmar commentedon Oct 14, 2026
Same thing here today, typing into Discord (Vesktop) on niri with wtype 0.4. A part of text that started with a space lost every space in it (slot 1 is Escape), and a period that was the 14th distinct character deleted the letter before it (slot 14 is Backspace). Letters on those slots come through fine. Emoji arrive cut to 16 bits with any keycode (U+1F916 shows up as U+F916), so that part is Chromium's keysym handling rather than the keymap. Pasting through the clipboard works around all of it.
feat(launcher-pass): switch the Type/Autotype backend from wtype to y…
feat(launcher-pass): added ydotool autotyping backend support (v2.7.0, …
Type on Wayland through a built-in virtual keyboard
Use printable keycodes for literal text
Paste voxtype output instead of typing it