Skip to content

fix(cua-driver/linux): report dead input backend on KDE/GNOME Wayland instead of silent no-op (#1982) - #1992

Merged
f-trycua merged 1 commit into
mainfrom
fix/wayland-no-input-backend-1982
Jun 24, 2026
Merged

fix(cua-driver/linux): report dead input backend on KDE/GNOME Wayland instead of silent no-op (#1982)#1992
f-trycua merged 1 commit into
mainfrom
fix/wayland-no-input-backend-1982

Conversation

@f-trycua

@f-trycua f-trycua commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Problem

On KDE Plasma 6.x (and GNOME) Wayland, the agent cursor renders but clicks and key presses are never delivered — and cua-driver doctor reports all-green, so the failure is invisible. Fixes #1982 (the near-term half).

Root cause

Non-wlroots compositors (KWin/Plasma, Mutter/GNOME) don't implement zwlr_virtual_pointer_v1. The only input path that works there is libei via xdg-desktop-portal RemoteDesktop, which is feature-gated behind portal-libei and compiled out of the published curl-pipe-bash tarball (#1967 — the debian:11 CD container can't satisfy the PipeWire/libei build deps without raising the GLIBC floor).

So on those compositors open_vptr_session finds no virtual-pointer manager and there's no fallback in the binary — input has no backend. Worse, the doctor's wayland_backend check returned a misleading partial-pass ("input may fall back where virtual-pointer is absent") whenever capture + foreign-toplevel + wl_shm were present, which is exactly the KWin case.

Fix (issue author's recommended option #2 — end the silent failure mode)

  • Add wayland::PORTAL_LIBEI_ENABLED = cfg!(feature = "portal-libei").
  • doctor wayland_backend: when virtual_pointer is absent and this build has no libei/portal support, return a FAIL with an actionable hint (use the portal-enabled build, or a wlroots compositor) instead of a false partial-pass. list_windows / capture are explicitly noted as unaffected.
  • open_vptr_session: emit the same actionable error at input time, so a click/type call on KDE/GNOME returns a clear "no input backend… use the portal build" error rather than looking like a silent success.

This does not add the libei path to the published binary — the two-variant publish (option #1, …-portal.tar.gz selected by an install.sh glibc sniff) remains separate, larger release-infra work. This PR's job is to make the current limitation honest and diagnosable.

Verification

  • Build-verified on Linux (Ubuntu, system libxcb/Wayland deps): cargo build -p platform-linux recompiled green at commit d8885e5 (default features — i.e. portal-libei off, exactly the published-binary config that exercises the new FAIL path).
  • Runtime behaviour on a live KDE Plasma session not exercised here (no KDE Wayland host in the test fleet); the change is a verdict/error-message correction along the existing no-backend code path.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved health diagnostics for input injection on Wayland compositors, providing clearer error messages when input features are unavailable or incompatible.

… instead of silent no-op (#1982)

On non-wlroots compositors (KWin/Plasma, Mutter/GNOME) there is no
zwlr_virtual_pointer; the only working input path is libei via
xdg-desktop-portal, which is feature-gated behind `portal-libei` and compiled
OUT of the published tarball (#1967). Result: the agent cursor renders, but
clicks/keys are never delivered, and `doctor` reported a misleading partial
pass ('input may fall back where virtual-pointer is absent').

- Add wayland::PORTAL_LIBEI_ENABLED (= cfg!(feature = "portal-libei")).
- doctor wayland_backend: when virtual-pointer is absent AND this build has no
  libei/portal support, FAIL with an actionable message (use the portal build
  or a wlroots compositor) instead of a false partial-pass.
- open_vptr_session: same actionable error at input time so the no-op failure
  surfaces to the caller instead of looking like a silent success.

Addresses the issue author's recommended near-term fix (option #2): end the
silent failure mode. The two-variant publish (option #1) remains separate work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMXCW4M5uK1HRGjjH4wueZ
@vercel

vercel Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Jun 23, 2026 9:06am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a public compile-time constant PORTAL_LIBEI_ENABLED derived from the portal-libei Cargo feature. Uses it in open_vptr_session to return a more specific error when the virtual-pointer manager is absent and portal support is compiled out. Adds an explicit CheckEntry::fail branch in check_wayland_backend for the same condition.

Portal-libei feature detection and health reporting

Layer / File(s) Summary
PORTAL_LIBEI_ENABLED constant and open_vptr_session error branching
libs/cua-driver/rust/crates/platform-linux/src/wayland/mod.rs
Declares pub const PORTAL_LIBEI_ENABLED: bool = cfg!(feature = "portal-libei") and updates open_vptr_session to conditionally return either a "protocol missing on compositor" error or a "no input backend compiled in" error based on that constant.
Explicit health-check failure for missing input backend
libs/cua-driver/rust/crates/platform-linux/src/health_report.rs
Adds a branch in check_wayland_backend that emits CheckEntry::fail when snap.virtual_pointer is false and PORTAL_LIBEI_ENABLED is false, with guidance that clicks/keys won't be dispatched and directing users to a portal-enabled build or a wlroots compositor.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Possibly related PRs

  • trycua/cua#1966: Introduced the native Wayland virtual-pointer and portal/libei backend plumbing that this PR's PORTAL_LIBEI_ENABLED constant and health-check failure directly extend.

Suggested reviewers

  • r33drichards

Poem

🐇 Hop, hop — no pointer found!
The portal gate is locked, unwound.
But now the doctor clearly cries:
"No clicks will land, no keys will rise!"
With one small flag the truth is told —
No silent failures, brave and bold. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main fix: reporting dead input backend on KDE/GNOME Wayland instead of silent no-op, directly matching the core change.
Linked Issues check ✅ Passed The PR fully implements the recommended near-term fix from issue #1982: adds PORTAL_LIBEI_ENABLED flag, updates doctor to report FAIL when virtual_pointer is absent and portal-libei is disabled, and provides actionable error messages.
Out of Scope Changes check ✅ Passed All changes are narrowly scoped to issue #1982: adding a feature-detection constant, updating health checks, and improving error messages for KDE/GNOME Wayland input issues.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/wayland-no-input-backend-1982

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@libs/cua-driver/rust/crates/platform-linux/src/health_report.rs`:
- Around line 292-305: The error message in the CheckEntry::fail call for the
NAME_WAYLAND_BACKEND check unconditionally states that list_windows and screen
capture are unaffected, but this branch executes whenever virtual_pointer is
unavailable and portal_libei is disabled, regardless of whether
foreign_toplevel, screencopy, or wl_shm are present. Modify the message to
either conditionally include the "unaffected" statement only when those other
required globals are verified to exist, or remove the specific claim about which
capabilities are unaffected to avoid misleading diagnosis on compositors with
missing additional globals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a099ad3f-5f1f-4bb9-a0cd-428432a4d861

📥 Commits

Reviewing files that changed from the base of the PR and between c898d7b and d8885e5.

📒 Files selected for processing (2)
  • libs/cua-driver/rust/crates/platform-linux/src/health_report.rs
  • libs/cua-driver/rust/crates/platform-linux/src/wayland/mod.rs

Comment on lines +292 to +305
if !snap.virtual_pointer && !crate::wayland::PORTAL_LIBEI_ENABLED {
return CheckEntry::fail(
NAME_WAYLAND_BACKEND,
format!(
"Input injection has no backend on this compositor ({msg}): it \
advertises no zwlr_virtual_pointer and this build was compiled \
without libei/portal support, so clicks and key presses will not \
be delivered (the agent cursor still renders). list_windows and \
screen capture are unaffected."
),
"Use the portal-enabled Linux build (compiled with --features \
portal-libei) for input on KDE Plasma / GNOME, or a wlroots \
compositor (sway, labwc, hyprland) where zwlr_virtual_pointer exists.",
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Avoid unconditional “unaffected” wording for other capabilities.

Line [299]-Line [300] says list_windows and screen capture are unaffected, but this branch also runs when foreign_toplevel/screencopy/wl_shm are missing. That can mislead diagnosis on compositors missing additional globals.

Suggested wording fix
         return CheckEntry::fail(
             NAME_WAYLAND_BACKEND,
             format!(
                 "Input injection has no backend on this compositor ({msg}): it \
                  advertises no zwlr_virtual_pointer and this build was compiled \
                  without libei/portal support, so clicks and key presses will not \
-                 be delivered (the agent cursor still renders). list_windows and \
-                 screen capture are unaffected."
+                 be delivered (the agent cursor still renders). list_windows and \
+                 screen capture depend on foreign-toplevel/screencopy/wl_shm \
+                 availability."
             ),
             "Use the portal-enabled Linux build (compiled with --features \
              portal-libei) for input on KDE Plasma / GNOME, or a wlroots \
              compositor (sway, labwc, hyprland) where zwlr_virtual_pointer exists.",
         );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if !snap.virtual_pointer && !crate::wayland::PORTAL_LIBEI_ENABLED {
return CheckEntry::fail(
NAME_WAYLAND_BACKEND,
format!(
"Input injection has no backend on this compositor ({msg}): it \
advertises no zwlr_virtual_pointer and this build was compiled \
without libei/portal support, so clicks and key presses will not \
be delivered (the agent cursor still renders). list_windows and \
screen capture are unaffected."
),
"Use the portal-enabled Linux build (compiled with --features \
portal-libei) for input on KDE Plasma / GNOME, or a wlroots \
compositor (sway, labwc, hyprland) where zwlr_virtual_pointer exists.",
);
if !snap.virtual_pointer && !crate::wayland::PORTAL_LIBEI_ENABLED {
return CheckEntry::fail(
NAME_WAYLAND_BACKEND,
format!(
"Input injection has no backend on this compositor ({msg}): it \
advertises no zwlr_virtual_pointer and this build was compiled \
without libei/portal support, so clicks and key presses will not \
be delivered (the agent cursor still renders). list_windows and \
screen capture depend on foreign-toplevel/screencopy/wl_shm \
availability."
),
"Use the portal-enabled Linux build (compiled with --features \
portal-libei) for input on KDE Plasma / GNOME, or a wlroots \
compositor (sway, labwc, hyprland) where zwlr_virtual_pointer exists.",
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/cua-driver/rust/crates/platform-linux/src/health_report.rs` around lines
292 - 305, The error message in the CheckEntry::fail call for the
NAME_WAYLAND_BACKEND check unconditionally states that list_windows and screen
capture are unaffected, but this branch executes whenever virtual_pointer is
unavailable and portal_libei is disabled, regardless of whether
foreign_toplevel, screencopy, or wl_shm are present. Modify the message to
either conditionally include the "unaffected" statement only when those other
required globals are verified to exist, or remove the specific claim about which
capabilities are unaffected to avoid misleading diagnosis on compositors with
missing additional globals.

@github-actions

Copy link
Copy Markdown
Contributor

Linux visual regression artifacts

Matrix jobs now run independently. Download visual artifacts from this workflow run.
Each background-GUI job uploads a .gif of the interaction plus two annotated PNGs (<app>.png raw, <app>-atspi.png with AT-SPI element boxes); the cua-driver-linux-som-overlays artifact adds <app>-som.png cua Set-of-Marks overlays:

  • cua-driver-linux-cursor-click-gif
  • cua-driver-linux-background-terminal-gif
  • cua-driver-linux-parallel-drag-xserver
  • cua-driver-linux-background-gui-chromium
  • cua-driver-linux-background-gui-tk
  • cua-driver-linux-background-gui-gtk3-gedit
  • cua-driver-linux-background-gui-gtk3-mousepad
  • cua-driver-linux-background-gui-gtk3-scite
  • cua-driver-linux-background-gui-gtk4-characters
  • cua-driver-linux-background-gui-qt5-manuskript
  • cua-driver-linux-background-gui-qt5-klog
  • cua-driver-linux-background-gui-qt5-openambit
  • cua-driver-linux-background-gui-qt6-kate
  • cua-driver-linux-background-gui-qt6-kcalc
  • cua-driver-linux-background-gui-qt6-okular
  • cua-driver-linux-background-gui-qt6-qownnotes
  • cua-driver-linux-background-gui-electron-zettlr
  • cua-driver-linux-background-gui-electron-joplin
  • cua-driver-linux-background-gui-electron-logseq
  • cua-driver-linux-som-overlays

Open workflow run and download artifacts

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cua-driver-rs (Linux/Wayland): KDE Plasma 6.7 — agent cursor renders but input doesn't dispatch (portal-libei feature gated off in published binary)

2 participants