# Understanding the Actions Ring in OpenLogi: A Complete Guide to Eight-Slot Layouts

> Master OpenLogi's Actions Ring with this guide. Learn to leverage its eight-slot layout for instant action execution, customizable via TOML or APIs.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: deep-dive
- Published: 2026-09-06

---

**The Actions Ring is OpenLogi's host-side radial UI that displays eight fixed positions for instant action execution, with layouts defined by the `ActionRingLayout` type and customizable per application through TOML configuration or runtime APIs.**

OpenLogi is an open-source automation platform for Logitech input devices that provides advanced gesture and button remapping. The **Actions Ring** serves as the primary circular overlay menu that appears when device-specific triggers invoke the `ShowActionsRing` command, allowing users to execute bound actions from eight directional slots.

## What Is the Actions Ring in OpenLogi?

The Actions Ring functions as a context-aware radial menu that renders on the host machine when activated. When a user triggers `ShowActionsRing`—typically via a remapped mouse button or gesture—the overlay appears centered on the active device location. The agent then monitors directional input to determine which of the eight slots the user selects, executing the corresponding bound action immediately.

This UI component bridges hardware input with software automation, providing tactile visual feedback through the eight-slot architecture defined in the core binding system.

## The Eight-Slot Layout Architecture

OpenLogi implements the ring layout through strict type definitions in [`crates/openlogi-core/src/binding/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/action_ring.rs). The eight-slot system uses fixed geometric positions to ensure muscle memory and predictable interaction patterns.

### ActionRingSlot Enum Positions

The `ActionRingSlot` enum defines eight clockwise positions starting from the top, as implemented in lines 20-40 of the core binding file:

- **Top** — 12 o'clock position
- **TopRight** — Diagonal between top and right
- **Right** — 3 o'clock position  
- **BottomRight** — Diagonal between right and bottom
- **Bottom** — 6 o'clock position
- **BottomLeft** — Diagonal between bottom and left
- **Left** — 9 o'clock position
- **TopLeft** — Diagonal between left and top

These variant names remain stable across the TOML configuration schema and Rust APIs, ensuring backward compatibility for user configurations.

### Default Layout Configuration

When no custom configuration exists for a device, OpenLogi supplies a built-in default layout through `ActionRingLayout::default` (lines 64-73). The default mapping assigns common clipboard and editing actions to cardinal directions:

```rust
use openlogi_core::binding::{ActionRingLayout, ActionRingSlot, Action};

let default = ActionRingLayout::default();
assert_eq!(default.slots[&ActionRingSlot::Top].action(), &Action::Cut);
assert_eq!(default.slots[&ActionRingSlot::Right].action(), &Action::Paste);

```

The default implementation ensures immediate usability while allowing complete customization through the configuration system.

## Configuring Actions Ring Layouts

OpenLogi provides multiple interfaces for modifying ring layouts: runtime GUI APIs for interactive editing and persistent TOML configuration for static definitions.

### Runtime Editing via AppState

The desktop GUI frontend exposes layout manipulation through helper methods in [`crates/openlogi-desktop/src/state/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/state/action_ring.rs). These APIs enable dynamic modification without restarting the application:

- **`current_action_ring_layout()`** — Retrieves the effective layout for the active device and foreground application
- **`commit_action_ring_slot(slot, action)`** — Updates or clears a specific slot binding
- **`commit_action_ring_icon(slot, icon)`** — Assigns visual icons to slots for better recognition
- **`set_editing_action_ring_app(app)`** — Switches to application-specific layout editing mode

These methods interact with the underlying `ActionRingConfig` structure while providing immediate visual feedback in the overlay renderer at [`crates/openlogi-overlay/src/ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-overlay/src/ring.rs).

### Persistence and Per-Application Overrides

The `ActionRingConfig` struct (lines 89-105) stores both default layouts and per-application overrides. When the foreground application matches a key in the `per_app` map, its layout supersedes the default through the `effective_layout` method (lines 28-33):

```toml
[devices."logitech-m570".action_ring]
enabled = true
haptics = true

[devices."logitech-m570".action_ring.default.slots]
Top = { action = "Copy", icon = "Keyboard" }
Right = { action = "Paste" }

[devices."logitech-m570".action_ring.per_app."com.apple.Safari".slots]
Top = { action = "NewTab" }

```

Empty slots are omitted from the TOML table, causing the ring to skip rendering those positions or display them as disabled depending on the skin configuration.

## Practical Implementation Examples

### Creating Custom Layouts in Rust

For plugin developers or advanced users, `ActionRingLayout` provides methods to programmatically construct configurations:

```rust
use openlogi_core::binding::{
    ActionRingLayout, ActionRingSlot, ActionRingEntry, RingAction, Action,
};

let mut layout = ActionRingLayout::default();

// Replace the "Top" slot with a custom shortcut
let custom = RingAction::new(Action::CustomShortcut("Cmd+N".into()))
    .expect("custom shortcut is a valid ring action");
layout.set_action(ActionRingSlot::Top, Some(custom));

// Add a custom icon to the "Right" slot
layout.set_icon(ActionRingSlot::Right, Some(openlogi_core::binding::ActionRingIcon::Keyboard));

```

### Modifying Layouts via the GUI API

Application-specific overrides can be configured at runtime through the desktop state management:

```rust
// Assuming `app_state` is an `AppState` instance
app_state.set_editing_action_ring_app(Some("com.apple.Safari".to_string()));
app_state.commit_action_ring_slot(ActionRingSlot::Bottom, None); // clear Bottom slot
app_state.commit_action_ring_icon(
    ActionRingSlot::Bottom,
    Some(openlogi_core::binding::ActionRingIcon::Mouse),
);

```

This approach enables context-sensitive automation where the Actions Ring presents different options in Safari versus Xcode, without requiring configuration file edits.

## Summary

- The **Actions Ring** provides an eight-slot radial overlay (`Top`, `TopRight`, `Right`, `BottomRight`, `Bottom`, `BottomLeft`, `Left`, `TopLeft`) for executing bound actions in OpenLogi.
- Layouts are defined by **`ActionRingLayout`** in [`crates/openlogi-core/src/binding/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/action_ring.rs), with defaults defined at lines 64-73.
- **Per-application overrides** are supported through `ActionRingConfig` (lines 89-105), resolved via the `effective_layout` method.
- Runtime modifications use **`AppState`** methods in [`crates/openlogi-desktop/src/state/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/state/action_ring.rs).
- The overlay renderer at [`crates/openlogi-overlay/src/ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-overlay/src/ring.rs) handles the visual presentation and input detection.

## Frequently Asked Questions

### How do I enable the Actions Ring for my Logitech device?

Configure the `action_ring.enabled` key to `true` in your device's TOML configuration section. You must also map a physical button or gesture to the `ShowActionsRing` action through the standard binding system. When triggered, the ring overlay renders at the cursor position displaying the eight configured slots.

### Can I have different Actions Ring layouts for different applications?

Yes, OpenLogi supports per-application layouts through the `per_app` map in `ActionRingConfig`. Set the application bundle identifier (macOS) or process name as the key, then define slot overrides specific to that context. The `effective_layout` method automatically selects the appropriate configuration based on the currently focused window.

### What happens if I leave an Actions Ring slot empty?

Empty slots—represented by `None` in Rust or omitted entries in TOML—render as disabled positions in the overlay. The ring still maintains the eight-slot geometric structure for consistency, but empty slots do not respond to selection input and typically display with reduced opacity or specific disabled styling depending on the active theme.

### Which source files control the Actions Ring behavior?

The core data structures reside in [`crates/openlogi-core/src/binding/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/action_ring.rs) (lines 1-105+), containing `ActionRingSlot`, `ActionRingLayout`, and `ActionRingConfig`. The desktop GUI integration lives in [`crates/openlogi-desktop/src/state/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/state/action_ring.rs), while the visual overlay implementation is located in [`crates/openlogi-overlay/src/ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-overlay/src/ring.rs).