Skip to content

Stop long multilingual typing from dropping characters on the remote desktop - #563

Merged
pallaoro merged 1 commit into
mainfrom
desktop-typing-drops-non-ascii-characters-in-long-text
Nov 9, 2026
Merged

pallaoro merged 1 commit into
mainfrom
desktop-typing-drops-non-ascii-characters-in-long-text

Conversation

@pallaoro

@pallaoro pallaoro commented Nov 9, 2026

Copy link
Copy Markdown
Member

Problem

computer → type lost non-ASCII characters in long text. Typing 4000 characters (1237 non-ASCII) into Mousepad on a 1-vCPU Ubuntu 24.04 box lost between 3 and 137 of them per call on main, while every ASCII character arrived. Some characters also came out duplicated ("日本語語").

Cause

In xdo.c (xdo_send_keysequence_window_list_do, the same in Ubuntu 24.04's 3.20160805.1 and upstream master), xdotool binds every character missing from the keymap to one scratch keycode, sends the key press, and clears the keycode 3 ms later. The next character rebinds the same keycode. Applications look the keycode up when they process the key, against the server's keymap at that moment. An app more than about 3 ms behind reads an empty binding (dropped character) or the next character's binding (wrong or duplicated character).

Fix

  • Before xdotool runs, type binds each non-ASCII character missing from the keymap to an empty keycode of its own, in one xmodmap call. xdotool finds them in the keymap and never rebinds.
  • Bindings stay until a later character needs the keycode, so a lagging app never loses the end of a call. The service clears its keycodes when it stops.
  • The lowest empty keycode (xdotool's scratch) and the highest (x11vnc's added keysyms) stay free. That leaves 17 on Xvfb's default keymap. Text with more distinct characters is typed in runs, reusing the keycode pressed longest ago after a 100 ms pause.
  • install-browser.sh now installs x11-xserver-utils for xmodmap. Without it, typing behaves as before and the service logs one line.
  • linux-smoke.mjs also asserts that each non-ASCII character had its own keycode, because short text can survive the old race by luck.

Verification

Unit tests for keymap parsing and run planning in test/x11.test.ts. Typecheck and lint pass.

Live, on a throwaway 1-vCPU / 4 GB Ubuntu 24.04 VM (Xvfb :99 1280x720x24, Openbox, Mousepad), typing 4000 characters in one MCP call and comparing the saved file:

Text main this PR
mixed Latin/Greek/Japanese, 1237 non-ASCII lost 6, then 3 exact ×4 (27.2 to 27.9 s)
same, with one CPU busy loop lost 51, then 53 (53.5 s) exact (28.8 s)
Russian, 3190 non-ASCII, 67 distinct exact exact ×4
Chinese, 3999 non-ASCII, 82 distinct lost 1 exact ×5

linux-smoke.mjs passes on the final build. After the service stopped, all of Xvfb's 19 empty keycodes were empty again.

Tradeoff

Long text with more distinct missing characters than free keycodes is slower: about 66 s for the Russian text and 92 s for the Chinese text with the CPU busy, against about 30 s before, when it was lossy. Without the pause, the same texts took 33 to 38 s and were still exact, so the 100 ms is margin. Binding a second keysym per keycode on the Shift level would roughly halve the reuses, if this matters.

Rollout

A box gets the fix when its ateam-novnc service restarts on the new desktop.js. A box without xmodmap also needs the browser installer rerun.

xdotool binds every character missing from the keymap to one scratch
keycode and clears it 3 ms after the key press. An app that looks the
key up later reads an empty or a newer binding, so long multilingual
text lost characters (up to 137 of 1237 in a 4000-character call).

Before typing, desktop-control now binds each such character to an
empty keycode of its own with one xmodmap call, so xdotool finds it in
the keymap and never rebinds. Bindings stay until a later character
needs the keycode and are released when the service stops. Text with
more distinct characters than free keycodes (17 on Xvfb) is typed in
runs, reusing the keycode pressed longest ago after a 100 ms pause.

The browser installer now installs x11-xserver-utils for xmodmap.
Without it, typing falls back to xdotool's own rebinding.
@pallaoro
pallaoro merged commit 7a516fa into main Nov 9, 2026
1 check passed
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.

1 participant