Skip to content

IBus text injection is a silent no-op on GNOME/Mutter Wayland (reports success, nothing typed) #481

Description

@fsioni

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

  1. GNOME Wayland session with IBus active (the default on Ubuntu).
  2. Focus any text field and dictate.
  3. 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)

  1. 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).
  2. 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.
  3. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions