fix: skip unbridged IBus on KDE Plasma Wayland (#577)
* fix(injection): skip unbridged IBus on KDE Plasma Wayland Do not auto-start XIM ibus-daemon on Wayland (circular viability check). On KDE, require KWin VirtualKeyboard enabled before selecting IBus. Fixes #574 * refactor(injection): tighten KDE VirtualKeyboard bridge check Ponytail cleanup: shorter logs and fewer failure branches, same behavior. * style: black-format ibus daemon Wayland test for CI * fix(injection): parse KWin VirtualKeyboard gdbus variants strictly Match <<true>>/<<false>> wrappers instead of bare substrings so ambiguous gdbus output cannot flip the #574 IBus bridge decision. Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>
This commit is contained in:
co-authored by
Jatin K Malik
Cursor Agent
parent
4c070ded46
commit
c59fe8b577
@@ -269,8 +269,10 @@ def start_ibus_daemon():
|
||||
"""
|
||||
Start the IBus daemon if it's not already running.
|
||||
|
||||
This is useful for desktop environments where IBus doesn't start automatically,
|
||||
such as some KDE Plasma installations or minimal window managers.
|
||||
X11 only. On Wayland we must not spawn ``ibus-daemon -x -d -r``: that XIM-mode
|
||||
daemon is not bridged to the compositor, but still makes
|
||||
``is_ibus_daemon_running()`` return True and leads to silent no-op injection
|
||||
(issue #574). The compositor/DE must own the Wayland-bridged IBus instance.
|
||||
|
||||
Returns:
|
||||
True if daemon was started or already running, False on failure
|
||||
@@ -278,6 +280,11 @@ def start_ibus_daemon():
|
||||
if is_ibus_daemon_running():
|
||||
return True
|
||||
|
||||
if _is_wayland_session():
|
||||
# XIM -x is not compositor-bridged; spawning it only fools the pgrep check (#574).
|
||||
logger.debug("Not starting ibus-daemon on Wayland (see #574)")
|
||||
return False
|
||||
|
||||
if not is_ibus_available():
|
||||
return False
|
||||
|
||||
|
||||
@@ -233,6 +233,57 @@ class TextInjector:
|
||||
"weston",
|
||||
)
|
||||
|
||||
def _kde_virtual_keyboard_enabled(self) -> bool:
|
||||
"""Return True when KWin VirtualKeyboard / input method is enabled.
|
||||
|
||||
On KDE Plasma Wayland, IBus only reaches native apps when this is on
|
||||
(issue #574). Disabled or unqueryable → treat IBus as unbridged.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[
|
||||
"gdbus",
|
||||
"call",
|
||||
"--session",
|
||||
"--dest",
|
||||
"org.kde.KWin",
|
||||
"--object-path",
|
||||
"/VirtualKeyboard",
|
||||
"--method",
|
||||
"org.freedesktop.DBus.Properties.Get",
|
||||
"org.kde.kwin.VirtualKeyboard",
|
||||
"enabled",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=2,
|
||||
)
|
||||
except (subprocess.SubprocessError, FileNotFoundError) as e:
|
||||
logger.info(
|
||||
"Could not query KWin VirtualKeyboard (%s); treating IBus as unbridged.",
|
||||
e,
|
||||
)
|
||||
return False
|
||||
|
||||
out = (result.stdout or "").strip().lower() if result.returncode == 0 else ""
|
||||
# gdbus prints variant wrappers like: (<<true>>,) or (<<false>>,)
|
||||
if "<<true>>" in out:
|
||||
return True
|
||||
if "<<false>>" in out:
|
||||
logger.info(
|
||||
"KWin Virtual Keyboard is disabled; IBus commits will not reach "
|
||||
"native apps. Falling back to ydotool/wtype. Enable: System "
|
||||
"Settings → Keyboard → Virtual Keyboard → IBus Wayland."
|
||||
)
|
||||
return False
|
||||
|
||||
logger.info(
|
||||
"KWin VirtualKeyboard not confirmed (rc=%s out=%r); treating IBus as unbridged.",
|
||||
result.returncode,
|
||||
result.stdout,
|
||||
)
|
||||
return False
|
||||
|
||||
def _wayland_compositor_bridges_ibus(self) -> bool:
|
||||
"""Whether native Wayland clients receive IBus commits on this compositor.
|
||||
|
||||
@@ -242,6 +293,10 @@ class TextInjector:
|
||||
those we must use a virtual-keyboard tool (wtype/ydotool) instead. We use
|
||||
a denylist rather than an allowlist so that unrecognised desktops keep the
|
||||
previous IBus-preferred behaviour.
|
||||
|
||||
On KDE Plasma Wayland, bridging also requires KWin VirtualKeyboard to be
|
||||
enabled (issue #574); otherwise commit_text succeeds at the IBus layer
|
||||
but never reaches apps.
|
||||
"""
|
||||
if self.environment != DesktopEnvironment.WAYLAND:
|
||||
# X11 / XWayland: IBus reaches apps through XIM regardless of DE.
|
||||
@@ -250,7 +305,11 @@ class TextInjector:
|
||||
os.environ.get(var, "")
|
||||
for var in ("XDG_CURRENT_DESKTOP", "XDG_SESSION_DESKTOP", "DESKTOP_SESSION")
|
||||
).lower()
|
||||
return not any(name in desktop for name in self._IBUS_UNBRIDGED_COMPOSITORS)
|
||||
if any(name in desktop for name in self._IBUS_UNBRIDGED_COMPOSITORS):
|
||||
return False
|
||||
if _is_kde_plasma_session():
|
||||
return self._kde_virtual_keyboard_enabled()
|
||||
return True
|
||||
|
||||
def _ydotool_socket_paths(self) -> list:
|
||||
"""Return candidate Unix socket paths used by ydotoold."""
|
||||
|
||||
Reference in New Issue
Block a user