Linux

Why Wayland Blocks Synthetic Typing (and How ydotool Fixes It)

23 September 2026 4 min read

Wayland compositors deliberately don't let one application send fake keystrokes to another. On X11, any client could call XTestFakeKeyEvent or XSendEvent and type into whatever window it wanted, no permission asked. Wayland's security model treats that as a bug, not a feature, so it removed the capability outright โ€” which is why dictation tools, autoclickers, and remote-control software can't just "type into the focused window" on Wayland the way they used to.

The X11 hole Wayland was built to close

X11's input model assumes every client is trustworthy. Any app on your desktop can read keystrokes from any other window, inject synthetic events into any window, or take a screenshot of the entire screen without asking. That's how X11 has worked since the 1980s, and it's also a well-documented keylogging and input-injection vector โ€” a malicious or compromised app has essentially unrestricted access to everything else running on your session.

Wayland's design starts from the opposite assumption. Each client only gets input events for its own surface, and there's no protocol call that lets an arbitrary client synthesize a keypress and hand it to a different, unrelated window. That's not an oversight the protocol will eventually patch โ€” it's the specific threat model Wayland was built to close. The tradeoff is that anything relying on the old behavior, including legitimate tools like voice dictation, has to find another route in.

How ydotool gets around it

ydotool doesn't talk to the compositor at all. Instead of going through the Wayland protocol, it goes underneath the entire display server stack and talks to the Linux kernel directly via /dev/uinput, the userspace input subsystem that lets a program register a fake input device โ€” a virtual keyboard or mouse that the kernel's evdev layer treats exactly like a physical USB device plugged into the machine.

When ydotool sends a keystroke, it isn't asking any application for permission โ€” it's telling the kernel "a keyboard just pressed this key," and the kernel routes that event through the normal input pipeline to whatever has focus, same as it would for a real keyboard. Neither Wayland nor X11 has any way to distinguish that from physical hardware, because at that layer it genuinely isn't a Wayland or X11 concept anymore. That's also why ydotool works identically under GNOME, KDE, Sway, or old-school X11 โ€” it never touches the display server's input-permission logic in the first place.

This is exactly the mechanism Voxtty relies on for typing transcribed text. Speech is transcribed on-device with faster-whisper, and the resulting text is handed to ydotool to type into whatever has focus, the same way a real keyboard would. If you want to try it, try Voxtty free and see the flow end to end.

Because /dev/uinput is a privileged kernel device node, it isn't world-writable by default โ€” that's the second half of the puzzle. ydotool runs a small background daemon, ydotoold, that opens the device once and listens on a local socket for typing requests. Getting a regular user account permission to talk to that daemon (or to open the device directly) normally means a udev rule that creates an input group, adjusts the permissions on /dev/uinput, and adds the user to that group. It's a one-time setup step, but it's a real permission boundary, not just a config toggle.

Where this gets messy

Granting a program uinput access is powerful in a way that's worth being honest about: a virtual keyboard device can type anything, anywhere, at any time, indistinguishable from you typing it. That's precisely why distros don't add users to the input group by default, and why some hardened setups (SELinux, certain immutable distros, tighter corporate images) block it entirely regardless of group membership. It's also why ydotool itself has no concept of "which window" โ€” it can't target an app by name, because from the kernel's point of view there's no such thing, only whatever currently has focus.

Some distros also don't package ydotoold to run persistently as a systemd service out of the box, so the daemon needs to be started (and kept running) separately from whatever app is using it. And because none of this goes through Wayland's protocol, there's no compositor-level way to ask "is dictation currently allowed in this window" โ€” permission is all-or-nothing at the group level, not scoped per-application the way Wayland scopes everything else.

One thing to check today

If you're on Wayland and curious whether this will just work, check two things: whether ydotool is packaged for your distro, and whether /dev/uinput exists and which group owns it (ls -l /dev/uinput). If it's owned by root:input, you're one usermod -aG input $USER and a re-login away from a working virtual keyboard โ€” no display server workarounds required.

Try Voxtty free

Local-first voice dictation for Linux. Press Alt+D, speak, and your words land in whatever app has focus โ€” nothing leaves your machine.

Try Voxtty free โ†’

Related Articles

Linux
How to Set Up Global Voice Dictation on Linux (Wayland or X11)
Privacy
How to Verify a "Local" Dictation App Never Phones Home
Privacy
What Voxtty Stores on Your Linux Machine
Dictation
Why Dictation Feels Awkward at First (And How to Fix It)
โ† Back to blog