fix:prefer xdotool/wtype over evdev for auto-typing
O turbo-whisper é ditado por voz no estilo SuperWhisper: atalho global, waveform em PyQt6, transcrição com OpenAI Whisper em 99 idiomas. Ezequias fez um fork de knowall-ai/turbo-whisper e achou um bug que só aparece pra quem digita em ABNT2.
O texto transcrito era digitado via evdev, que injeta scancodes crus assumindo um teclado US-QWERTY. A posição física da tecla de apóstrofo no US é a tecla de til no ABNT2. Então cada ' do texto chegava na tela como ~.
| @@ def type_text(text: str) -> None: @@ | ||
| 1 | - | # evdev first: raw scancodes straight into uinput |
| 2 | - | if type_with_evdev(text): |
| 3 | - | return |
| 1 | + | wayland = bool(os.environ.get("WAYLAND_DISPLAY")) \ |
| 2 | + | or os.environ.get("XDG_SESSION_TYPE") == "wayland" |
| 3 | + | |
| 4 | + | # tools that go through the active keyboard layout |
| 5 | + | if wayland and shutil.which("wtype"): |
| 6 | + | if run(["wtype", text]): |
| 7 | + | return |
| 8 | + | if shutil.which("xdotool"): |
| 9 | + | if run(["xdotool", "type", "--clearmodifiers", |
| 10 | + | "--delay", str(DELAY_MS), text]): |
| 11 | + | return |
| 12 | + | |
| 13 | + | # fallback: evdev still sends US-QWERTY scancodes |
| 14 | + | if type_with_evdev(text): |
| 15 | + | return |
| 16 | if type_with_pyautogui(text): | |
| 17 | return | |
| 18 | paste_from_clipboard(text) |
A nova ordem
- Detecta a sessão por
WAYLAND_DISPLAYouXDG_SESSION_TYPE. - wtype no Wayland, que digita respeitando o layout ativo.
- xdotool type --clearmodifiers --delay no X11: solta modificadores ainda pressionados e espaça as teclas.
- evdev, PyAutoGUI e clipboard continuam como fallback, nessa ordem, pra quem não tem as ferramentas instaladas.
Os outros commits do branch
- feat: language selection, headless recording, clearer offline error+143 linhas em
api.py,config.pyemain.py. - docs: self-hosted setup notes for Pop!_OSServidor faster-whisper em Docker com CUDA (
--gpus all), modeloSystran/faster-whisper-small, porta exposta só em127.0.0.1, cache do HuggingFace montado como volume, áudio por PipeWire/PortAudio.