Skip to content

Add an opt-in x11 feature: X11 backend + keyboard grab#4

Open
domenkozar wants to merge 3 commits into
dsociative:mainfrom
domenkozar:feat/x11
Open

Add an opt-in x11 feature: X11 backend + keyboard grab#4
domenkozar wants to merge 3 commits into
dsociative:mainfrom
domenkozar:feat/x11

Conversation

@domenkozar

Copy link
Copy Markdown

Implements proposal #2 from #1 (X11 keyboard grab), made opt-in to respect the crate's "no X11 dependencies" default.

Adds an x11 Cargo feature, off by default:

  • The default build stays Wayland-only and links no libX11 (x11-dl).
  • Enabling x11 turns on winit's X11 windowing backend and an XGrabKeyboard anti-snoop grab (Drop-guarded, retry-until-viewable, no-op off X11), covering every dialog window (GETPIN and CONFIRM/MESSAGE).

On X11, other clients can keylog a passphrase prompt unless it grabs the keyboard (this is why GnuPG's own pinentry does XGrabKeyboard).

Verified: x11-dl is absent from the default cargo tree and present with --features x11; cargo test passes both ways, with zero warnings.

Design note: because the grab is the only reason this crate needs X11 at all, I bundled winit's X11 display backend under the same x11 feature. So with the feature off the build is Wayland-only, which matches the crate's "Native Wayland pinentry" identity. If you would rather keep X11 display available without the grab, the feature can be split into x11 (backend) and a separate grab toggle. Your call.

Stacking: this is stacked on #3 (CPU rendering) and #2 (zeroizing input), so the diff below includes those until they merge. The commit specific to this PR is 1aef2ae ("Add an opt-in x11 feature ...").

Opened per the discussion in #1. Happy to adjust, split the feature, or hold entirely depending on how you want to handle the X11 question.

Feed keystrokes directly into a zeroize::Zeroizing<String> and draw a
masked view, rather than an egui TextEdit whose retained widget state and
undo history keep the plaintext around after the dialog closes. Move the
value into the SecretString on submit (no clone; the buffer is zeroized on
drop). Tests drive the field with synthetic input events since the masked
view is no longer an accessible widget.
Replace the eframe/glow (OpenGL) backend with a pure-CPU pipeline: winit
for windowing, egui_software_backend to rasterize egui frames on the CPU,
and softbuffer to present them. No GPU, OpenGL, or Vulkan is required, so
the dialog runs on machines without working GL drivers.

- Bump egui, egui-winit, and egui_kittest to the 0.34 line (pinned by
  egui_software_backend 0.0.3, which pins egui 0.34 / winit 0.30).
- Drive one process-wide winit EventLoop with run_app_on_demand so a
  single gpg-agent connection can show several GETPIN/CONFIRM dialogs.
- Keep the Assuan protocol layer, the zeroizing masked passphrase buffer,
  and the show_dialog(state, want_pin) signature unchanged.
- Port the egui_kittest UI tests to the 0.34 API.
The default build stays Wayland-only and links no libX11. Enabling `x11`
turns on winit's X11 backend and adds an XGrabKeyboard anti-snoop grab
(Drop-guarded, retry-until-viewable, no-op off X11), covering every dialog
window.

@dsociative dsociative left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Design accepted, including bundling winit's X11 backend under the same x11 feature — the default build getting stricter than main ("Wayland-only" now literally true at link level) is a nice touch. Verified: x11-dl absent from the default tree, present with --features x11; tests pass both ways.

One non-blocking nit: in redraw(), GrabAttempt::Retrywindow.request_redraw() retries unboundedly, so if another client holds the grab (AlreadyGrabbed) the dialog busy-loops redraws for its lifetime. A bounded retry count or a short timer between attempts would be kinder. Happy to take that as a follow-up instead of blocking this.

For transparency: I don't run X11 sessions, so the grab path was verified by review and feature-gate checks, not exercised live.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants