Summary
On GNOME/Mutter Wayland, IBus text injection is a silent no-op: the Vocalinux IBus engine activates, commit_text() reports success and IBusTextInjector.inject_text() returns True, but the text never reaches the focused application. Because _check_dependencies() prefers IBus whenever it is the active input method, Vocalinux never falls back to ydotool/wtype, so dictation silently disappears into the void with no error.
Environment
- OS: Ubuntu 24.04 (noble)
- Desktop: GNOME on Wayland (
XDG_CURRENT_DESKTOP=ubuntu:GNOME, Mutter)
QT_IM_MODULE=ibus, XMODIFIERS=@im=ibus (so is_ibus_active_input_method() returns True)
- ibus-daemon running; Vocalinux engine reachable over its socket
Steps to reproduce
- GNOME Wayland session with IBus active (the default on Ubuntu).
- Focus any text field and dictate.
- Nothing is inserted, and the log shows the IBus path "succeeding".
Evidence
Minimal end-to-end test: a GTK Entry is shown and grabs focus, then the Vocalinux IBus client injects into it.
inj = IBusTextInjector()
inj.prepare_engine()
ok = inj.inject_text("Bonjour, accents: éàç ù €")
# logs:
# INFO Activating Vocalinux IBus engine...
# INFO Vocalinux IBus engine activated
# INFO Starting IBus text injection: 'Bonjour, accents: éà...'
print(ok) # -> True
print(repr(entry.get_text())) # -> '' (the focused field received NOTHING)
ibus engine vocalinux does switch the active engine successfully (the engine registers dynamically via register_component(), so it is not listed by ibus list-engine but can still be activated). Despite that, commit_text() from the engine instance does not land in the focused client on Mutter.
Why it matters
_check_dependencies() deliberately prefers IBus when it is the active input method:
# Prefer IBus on both X11 and Wayland - it sends Unicode directly,
# bypassing keyboard layout issues entirely
if is_ibus_available():
if not is_ibus_active_input_method(): ...
...
self._ibus_injector = IBusTextInjector(...)
ibus_requested = True
On GNOME Wayland (the largest Linux desktop) IBus is the active input method by default, so this is the path most users hit — and it injects nothing while reporting success. The existing runtime fallback (_switch_to_non_ibus_backend) only triggers when IBus injection returns False, which never happens here.
Possible directions (happy to help / open a PR)
- Verify IBus injection actually delivered, and fall back to
ydotool/wtype when it didn't (hard to do reliably — commit_text gives no delivery confirmation).
- Prefer a working
ydotool daemon over IBus when one is available (uinput-level injection bypasses the compositor's IM integration entirely). I'm running this locally as a small guard around _start_ibus_initialization() and it fixes injection on this setup — but it reverses the current "prefer IBus" design, so it needs a maintainer decision.
- Detect Mutter specifically and de-prioritise the IBus path there.
Note: the layout/clipboard reliability bugs that this interacts with are addressed separately in #480; this issue is specifically about the silent IBus no-op and backend-selection policy.
Happy to turn whichever direction you prefer into a PR.
Summary
On GNOME/Mutter Wayland, IBus text injection is a silent no-op: the Vocalinux IBus engine activates,
commit_text()reports success andIBusTextInjector.inject_text()returnsTrue, but the text never reaches the focused application. Because_check_dependencies()prefers IBus whenever it is the active input method, Vocalinux never falls back toydotool/wtype, so dictation silently disappears into the void with no error.Environment
XDG_CURRENT_DESKTOP=ubuntu:GNOME, Mutter)QT_IM_MODULE=ibus,XMODIFIERS=@im=ibus(sois_ibus_active_input_method()returnsTrue)Steps to reproduce
Evidence
Minimal end-to-end test: a GTK
Entryis shown and grabs focus, then the Vocalinux IBus client injects into it.ibus engine vocalinuxdoes switch the active engine successfully (the engine registers dynamically viaregister_component(), so it is not listed byibus list-enginebut can still be activated). Despite that,commit_text()from the engine instance does not land in the focused client on Mutter.Why it matters
_check_dependencies()deliberately prefers IBus when it is the active input method:On GNOME Wayland (the largest Linux desktop) IBus is the active input method by default, so this is the path most users hit — and it injects nothing while reporting success. The existing runtime fallback (
_switch_to_non_ibus_backend) only triggers when IBus injection returnsFalse, which never happens here.Possible directions (happy to help / open a PR)
ydotool/wtypewhen it didn't (hard to do reliably —commit_textgives no delivery confirmation).ydotooldaemon over IBus when one is available (uinput-level injection bypasses the compositor's IM integration entirely). I'm running this locally as a small guard around_start_ibus_initialization()and it fixes injection on this setup — but it reverses the current "prefer IBus" design, so it needs a maintainer decision.Note: the layout/clipboard reliability bugs that this interacts with are addressed separately in #480; this issue is specifically about the silent IBus no-op and backend-selection policy.
Happy to turn whichever direction you prefer into a PR.