Skip to content

feat(gui): record custom keyboard shortcuts - #971

Open
AprilNEA wants to merge 3 commits into
masterfrom
feat/custom-shortcut-gui
Open

AprilNEA wants to merge 3 commits into
masterfrom
feat/custom-shortcut-gui

Conversation

@AprilNEA

Copy link
Copy Markdown
Owner

Summary

  • Add end-to-end recording and assignment of custom physical keyboard shortcuts to mouse buttons and gestures.
  • Keep global input capture in the agent and the desktop UI as an IPC-only client, using the published inputs and controls crates.
  • Address the custom-shortcut workflow requested in [Feature]: ability to add a custom shortcut #792.

Changes

  • Agent / core / IPC / injector: add keyboard-only, non-suppressing recording sessions with bounded callback handoff, stale-session rejection, cancellation, teardown handling, and a 60-second lease; extend physical-key conversion and cross-platform shortcut injection (including numpad keys); bump the append-only IPC protocol to v29 and cover its wire format.
  • Desktop / UI: add localized record, waiting, cancel, retry, unavailable, unsupported, and interrupted states; save a recorded shortcut only to the exact selected device/profile/button or gesture after the agent acknowledges the session; cancel when that selection context changes.
  • Linux packaging: grant active-seat users recording-time read access to keyboard evdev nodes through the packaged udev rule and remove it on uninstall. Recording remains observe-only and never grabs or suppresses keyboard input.

Testing

  • cargo fmt --all -- --check
  • RUSTFLAGS=\"-D warnings\" cargo clippy --workspace --all-targets --locked -- -D warnings
  • RUSTFLAGS=\"-D warnings\" cargo test --workspace --locked
  • RUSTDOCFLAGS=\"-D warnings\" cargo doc --workspace --no-deps --document-private-items --exclude openlogi-ui --exclude openlogi-desktop --exclude openlogi-overlay --exclude openlogi-agent
  • cargo test --locked -p openlogi-ipc --test wire_format
  • cargo test --locked -p openlogi-desktop
  • cargo test --locked -p openlogi-desktop i18n
  • cargo xtask ci clippy-windows
  • macOS aarch64-apple-darwin cross-Clippy for openlogi-core, openlogi-inject, openlogi-ipc, openlogi-agent-core, and openlogi-agent
  • cargo xtask ci wasm
  • cargo xtask ci shell with shellcheck 0.9.0 and shfmt 3.13.1
  • cargo xtask release check-publish
  • cargo deny --config .cargo/deny.toml --all-features --manifest-path crates/openlogi/Cargo.toml check
  • cargo xtask linux package with nfpm 2.47.0 (DEB, RPM, and Arch packages created)

Not runtime-tested on physical keyboard/mouse hardware. Maintainer verification: record modifier/key and numpad combinations for a button and gesture, save them, and trigger them on macOS, Linux/X11, Linux/Wayland, and Windows; on Linux, verify the installed udev rule grants the active desktop session keyboard access after re-login or rule reload.

The native GPUI interaction and screenshots were not exercised because the Linux orb is headless; desktop state/interaction tests passed. Nix formatting/evaluation/package builds and udevadm parser/runtime checks were not run because those tools are unavailable in the orb.

Fixes #573

AprilNEA and others added 3 commits August 25, 2026 08:57
Co-authored-by: Xuan Zhang <xuan@arcbox.dev>
Co-authored-by: Xuan Zhang <xuan@arcbox.dev>
Co-authored-by: Xuan Zhang <xuan@arcbox.dev>
@AprilNEA
AprilNEA requested a review from davidbudnick as a code owner August 25, 2026 09:11
Copilot AI lite review requested due to automatic review settings August 25, 2026 09:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@greptile-apps

greptile-apps Bot commented Aug 25, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds agent-owned recording of physical keyboard shortcuts, transports recording state over IPC, saves shortcuts to mouse-button or gesture targets, expands cross-platform key injection, and updates Linux device permissions.

  • Adds a bounded, session-identified keyboard recorder with cancellation and timeout handling.
  • Extends the IPC snapshot and desktop workflow for recording, displaying, and persisting custom shortcuts.
  • Adds numpad and additional function-key conversion and injection mappings.
  • Grants Linux active-seat users access to keyboard evdev nodes, introducing a persistent keystroke-read boundary concern.

Confidence Score: 3/5

The PR is not safe to merge until Linux keyboard-node access is constrained so unrelated active-user processes do not gain persistent global keystroke visibility.

The recording and IPC flow is session-gated, but the Linux packaging change broadens keyboard evdev access from a temporary OpenLogi operation to every process under the active desktop identity.

Files Needing Attention: packaging/linux/udev/70-openlogi.rules

Security Review

The Linux udev rule grants every process running as the active desktop user persistent access to all keyboard event nodes. This access is not restricted to OpenLogi or to the explicit 60-second recording session.

Important Files Changed

Filename Overview
crates/openlogi-agent-core/src/shortcut_recording.rs Adds the agent-owned bounded recording state machine, portable key conversion, session rejection, timeout, and listener lifecycle.
crates/openlogi-desktop/src/features/mouse/view.rs Coordinates recording sessions with the selected button or gesture and session-gates completed shortcuts before persistence.
crates/openlogi-desktop/src/services/ipc.rs Adds recording commands and acknowledgement handling while resetting long-held observations around session mutations.
crates/openlogi-ipc/src/ipc.rs Extends the append-only protocol with recording state and commands alongside a protocol-version bump.
crates/openlogi-inject/src/inject/windows.rs Expands Windows shortcut injection for newly recordable physical keys, including selected extended-key handling.
packaging/linux/udev/70-openlogi.rules Grants session-wide keyboard-node access to the active user, exposing keystrokes outside OpenLogi recording sessions.

Sequence Diagram

sequenceDiagram
    participant UI as Desktop UI
    participant IPC as IPC Client
    participant Agent as Agent Recorder
    participant OS as Keyboard Listener
    UI->>IPC: Start recording
    IPC->>Agent: start_shortcut_recording()
    Agent-->>IPC: Session ID
    Agent->>OS: Start observe-only listener
    OS-->>Agent: Physical key events
    Agent-->>IPC: Generation-stamped recording state
    IPC-->>UI: Recording / waiting / complete
    UI->>UI: Save shortcut to selected target
    UI->>IPC: Cancel or consume session
    IPC->>Agent: cancel_shortcut_recording()
    Agent->>OS: Drop listener
Loading

Fix all with Greploop Fix All in Codex Fix All in Claude Code

Reviews (1): Last reviewed commit: "fix(linux): grant shortcut recorder keyb..." | Re-trigger Greptile

# `uaccess` grants an ACL to the active local seat user; it does not make the node
# world-readable. This also covers Bluetooth keyboards on the virtual uhid bus,
# which logind's normal physical-seat rules may not classify on their own.
SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_KEYBOARD}=="1", TAG+="uaccess"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Keyboard ACL outlives recording

When this rule is installed, uaccess grants every process running as the active desktop user access to all keyboard event nodes for the session, not just OpenLogi during its 60-second recording window, exposing global keystrokes to unrelated or compromised processes under that identity. How this was verified: The rule applies a user-scoped ACL to every ID_INPUT_KEYBOARD node, while recorder teardown only drops OpenLogi's listener and never revokes that ACL.

Knowledge Base Used: Distribution packaging and CI

Fix in Codex Fix in Claude Code

@ra4-z

ra4-z commented Sep 20, 2026

Copy link
Copy Markdown

Hi @AprilNEA — checking in on the status of this one, since it looks like the most complete answer to #573 (real key recording rather than typing a chord as text).

I'd argue this is the single biggest gap left between OpenLogi and Options+ right now. Binding an arbitrary chord to a button is what turns the mouse from "a few fixed actions" into a per-app control surface: Cmd+Shift+A to mute in Zoom, Win+Shift+T in a launcher, a hotkey for an AutoHotkey/Raycast script, a Super-bound GNOME shortcut — and combined with the per-app profile overlay it means the same button does the right thing in every app. That's the workflow people are describing in #573 and #1190 (14 comments before it was closed as a duplicate), and it's the one thing several of them say they still keep Options+ around for. Every one of them ends up hand-editing config.toml, which works but is exactly the "confusing configuration file" experience the project set out to replace.

A few things I noticed that may be blocking it:

Is agent-side recording still the direction you want, or would you rather land a text-input editor first and layer recording on top later?

If it's just a matter of bandwidth, I'm happy to help: rebase the branch onto current master, and/or rework the Linux access so the agent grants read access only for the lifetime of a recording session (e.g. a transient ACL applied by the agent on start_shortcut_recording and removed on cancel/timeout) instead of a standing udev rule. Let me know which you'd prefer and I'll open a follow-up PR against your branch.

This branch has not been deployed

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

Labels

platform: all Cross-platform issue type: feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Keyboard shortcuts can't be set to mouse buttons

4 participants