OpenLogi Actions Ring Configuration: Complete Guide to the 8-Slot Cursor Menu
OpenLogi implements an eight-slot Actions Ring that appears around the cursor, allowing users to assign quick actions like Cut, Copy, and Paste through TOML configuration or the Desktop UI editor, with support for per-application overrides and haptic feedback.
The OpenLogi Actions Ring configuration system provides a radial quick-action menu for customizable input devices. Defined in the openlogi-core crate and rendered by the desktop and overlay components, this feature enables device-wide and application-specific shortcuts without moving hands from the hardware. Understanding the configuration architecture allows you to customize the eight fixed slots, enable haptic feedback, and create context-aware layouts tailored to specific workflows.
Architecture and Source Files
The Actions Ring implementation spans multiple crates, separating data models, UI editing, and rendering concerns.
Core Data Structures
In crates/openlogi-core/src/binding/action_ring.rs, the ActionRingConfig struct holds device-wide settings including the enabled boolean and haptics toggle. This structure contains a default ActionRingLayout and a per_app hash map for overrides. The layout stores eight fixed positions mapped to ActionRingEntry objects, each containing a RingAction, optional ActionRingIcon, and optional label.
Desktop UI Editor
The ActionRingPanel in crates/openlogi-desktop/src/features/action_ring.rs provides the graphical configuration interface. This component reads the current state from AppState and allows users to edit individual slots, assign custom icons, modify labels, and toggle both the enabled state and haptic feedback settings.
Overlay Rendering
The stand-alone openlogi-overlay binary defined in crates/openlogi-overlay/src/main.rs handles the visual presentation. When the user triggers the ShowActionsRing binding, this lightweight GPUI host renders the ring at the current cursor position using the active configuration transmitted via IPC.
IPC Communication Layer
Configuration data travels between the agent and desktop through structures defined in crates/openlogi-ipc/src/ipc.rs. The ActionRingPresentation and ActionRingInvocation types carry the layout data and display requests across process boundaries.
Understanding the Eight-Slot Layout
The OpenLogi Actions Ring uses a fixed geometric design with eight immutable positions that form a circle around the cursor.
The eight slots follow compass directions:
- Top
- TopRight
- Right
- BottomRight
- Bottom
- BottomLeft
- Left
- TopLeft
Each slot accepts a RingAction enum variant representing concrete commands such as Action::Copy or custom application shortcuts. The system validates configurations to prevent recursive invocation: the ShowActionsRing action cannot be assigned to any slot within the ring itself, as enforced by the validation logic in binding/action_ring.rs.
Configuring the Actions Ring
Users can configure the ring through TOML files or programmatically via the Rust API.
TOML Configuration
The user-editable config.toml file mirrors the Rust structs via serde. The action_ring table configures device-specific settings, default layouts, and per-application overrides as documented in docs/config.example.toml.
[devices."receiver:1234abcd:slot:1".action_ring]
enabled = true # Show the ring when ShowActionsRing is invoked
haptics = true # Play haptic feedback on hover/activation
# Default layout – one entry per slot; omitted slots become empty
[devices."receiver:1234abcd:slot:1".action_ring.default.slots]
Top = { action = "Copy", icon = "Keyboard" }
TopRight = { action = "Paste" }
Right = { action = { OpenApplication = { path = "/Applications/Slack.app", display_name = "Slack" } }, icon = "Applications" }
BottomRight = { action = "ShowDesktop", label = "Desktop" }
Bottom = { action = "PlayPause" }
BottomLeft = { action = "BrowserBack" }
Left = { action = "Undo" }
TopLeft = { action = "Redo" }
Programmatic Configuration
For dynamic configuration, Rust code can manipulate the ActionRingConfig structure directly.
use openlogi_core::binding::{ActionRingConfig, ActionRingSlot, RingAction};
// Load the per‑device config (typically via AppState)
let cfg: ActionRingConfig = /* … */;
// Replace the top‑right slot with a custom shortcut
let mut layout = cfg.default.clone();
layout.set_action(ActionRingSlot::TopRight, Some(RingAction::new(Action::CustomShortcut("Ctrl+Shift+P".into())).unwrap()));
Creating a per-application override at runtime:
let mut cfg = ActionRingConfig::default();
let mut app_layout = cfg.default.clone();
app_layout.set_action(ActionRingSlot::Bottom, Some(RingAction::new(Action::ShowDesktop).unwrap()));
cfg.per_app.insert("com.apple.Safari".to_string(), app_layout);
Advanced Customization Features
Beyond basic action assignment, the configuration system supports visual customization and context-specific behaviors.
Custom Icons and Labels
Each ActionRingEntry may override the automatically derived icon with an ActionRingIcon and display a custom label string. When these fields are None, the UI falls back to the action's default icon and label as defined in the locale files located in crates/openlogi-ui/locales/en.toml.
Per-Application Layouts
The per_app field in ActionRingConfig maps foreground application identifiers to full ActionRingLayout instances. This allows context-specific configurations—for example, displaying coding shortcuts when using a text editor and media controls when using a music player.
Haptic Feedback
When the haptics field is set to true, hover and activation events trigger short vibrations on devices that expose haptic feedback capabilities. This feature is handled in the openlogi-agent-core layer and respects the device-wide setting in ActionRingConfig.
Summary
- OpenLogi Actions Ring configuration centers on eight fixed slots defined in
ActionRingConfigwithincrates/openlogi-core/src/binding/action_ring.rs. - The system supports both TOML file configuration and programmatic Rust API manipulation.
- Per-application overrides allow context-specific layouts mapped by application identifier.
- Visual customization includes custom icons and labels stored in
ActionRingEntrystructures. - Haptic feedback is controlled by the
hapticsboolean flag in the device configuration. - The architecture separates concerns between core data models, Desktop UI editing (
ActionRingPanel), and overlay rendering (openlogi-overlay).
Frequently Asked Questions
How many actions can I assign to the OpenLogi Actions Ring?
The OpenLogi Actions Ring contains exactly eight fixed slots corresponding to compass directions: Top, TopRight, Right, BottomRight, Bottom, BottomLeft, Left, and TopLeft. You cannot add or remove slots, but you can leave slots empty by omitting them from the configuration or setting them to None.
Can I configure different Actions Ring layouts for specific applications?
Yes. The ActionRingConfig.per_app field allows you to map application identifiers (such as "com.apple.Safari") to complete ActionRingLayout instances. When the specified application becomes the foreground window, OpenLogi automatically switches to that layout instead of using the default configuration.
Where is the Actions Ring configuration stored in OpenLogi?
Configuration resides in a TOML file (typically config.toml) that mirrors the Rust structs via serde. The specific path follows the pattern devices."receiver:{id}:slot:{n}".action_ring within the TOML structure, allowing per-device customization alongside the global defaults found in docs/config.example.toml.
Why can't I assign the ShowActionsRing action to a slot in the ring?
The ShowActionsRing action is explicitly prohibited from being placed inside the Actions Ring to prevent infinite recursion. The validation logic in crates/openlogi-core/src/binding/action_ring.rs guards against this configuration error, ensuring the ring contains only terminal actions like Copy, Paste, or application shortcuts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →