How the OpenLogi Actions Ring Overlay Renders and Provides Cursor-Centered Interaction

The OpenLogi Actions Ring is implemented as a lightweight, standalone IPC client binary that renders a transparent GP UI window always centered on the cursor, with edge-aware positioning and click-away dismissal.

OpenLogi's Actions Ring provides a quick-access radial menu for workflow automation. Understanding how this overlay renders and maintains cursor-centered positioning reveals the architecture behind its seamless user experience. This article examines the implementation in the AprilNEA/OpenLogi repository, tracing from IPC invocation through GPUI window creation to final dismissal.

Process Lifecycle and IPC Architecture

The overlay binary (openlogi-overlay) operates as a dedicated subprocess that communicates with the main agent via inter-process communication.

In crates/openlogi-overlay/src/main.rs, the entry point establishes three critical responsibilities:

  • Singleton enforcement: Claims the overlay role through a system mutex, ensuring only one ring instance runs at a time
  • Tracing initialization: Sets up structured logging for debugging overlay behavior
  • IPC channel creation: Spawns bidirectional communication for receiving invocations and sending commands back to the agent
// From crates/openlogi-overlay/src/main.rs
let Ipc { mut invocations, commands } = spawn_ipc();
cx.spawn(async move {
    while let Some(observed) = invocations.recv().await {
        let invocation = observed.unwrap();
        cx.update(|cx| {
            // Clean up existing windows before showing new ring
            for handle in cx.windows() {
                let _ = handle.update(cx, |_, w, _| w.remove_window());
            }
            let options = ring_window_options(cx);
            cx.open_window(options, |_, cx| {
                cx.new(|_| RingView::new(invocation, commands.clone(), &live_session))
            });
        });
    }
});

The IPC protocol uses two core types defined in crates/openlogi-ipc/src/ipc.rs: ActionRingInvocation (incoming, containing the actions to display) and OverlayCommand (outgoing, including Activate, Hover, and Cancel variants).

Cursor-Centered Window Positioning

The ring_window_options function in crates/openlogi-overlay/src/ring.rs implements the core positioning logic that keeps the ring centered on the cursor while respecting display boundaries.

Step 1: Capture Global Cursor Position

The overlay queries the cursor location through the hook subsystem:

let cursor = openlogi_hook::cursor_position();  // Global screen coordinates

Step 2: Resolve Display Context

The function determines which display contains the cursor, with platform-specific resolution:

let native_display = cursor
    .as_ref()
    .and_then(|c| platform::display_containing(c.x, c.y));

On macOS, this delegates to platform::display_containing; other platforms iterate the GPUI display list.

Step 3: Compute and Clamp Origin

The desired window origin centers the ring on the cursor, then clamps to visible bounds:

let origin = display_bounds.map_or(center, |b| clamp_window_origin(center, size, b));

The clamp_window_origin helper ensures the ring never renders partially off-screen, adjusting the position when the cursor is near display edges.

The resulting WindowOptions configure a borderless, transparent popup:

WindowOptions {
    window_bounds: Some(WindowBounds::Windowed(Bounds::new(origin, size))),
    kind: WindowKind::PopUp,
    focus: false,                                  // Non-focusable
    window_background: WindowBackgroundAppearance::Transparent,
    app_id: Some("openlogi-action-ring".to_string()),
    ..Default::default()
}

Rendering the Ring Interface

The RingView struct in crates/openlogi-overlay/src/ring.rs implements the GPUI Render trait to draw the radial interface.

Slot Layout and Geometry

Eight action slots are positioned using polar coordinates calculated from ActionRingSlot::placement:

// Each slot rendered by slot_element with position from ring geometry
fn slot_element(
    slot: ActionRingSlot,
    commands: OverlayCommandSender,
    live_session: &LiveOverlaySession,
) -> impl gpui::IntoElement {
    // Position calculation from slot.placement
}

Slots display SVG icons from crates/openlogi-ui/src/action_icons.rs and respond to:

  • Hover: Background color change + Hover command sent to agent
  • Click: Activate command sent + window closed

Central Cancel Button

A cancel control occupies the ring's center, triggering the Cancel command when clicked:

// Center "×" button implementation
div()
    .child(Icon::new(IconName::X))
    .on_click(|_, _, cx| {
        commands.send(OverlayCommand::Cancel);
        cx.remove_window();
    })

The visual styling draws from openlogi_ui::color constants, using dark panel backgrounds with accent highlights.

Click-Away Dismissal Implementation

To dismiss the ring when clicking outside its bounds, the overlay implements global input monitoring on macOS:

// In crates/openlogi-overlay/src/platform.rs
pub fn watch_clicks_outside<F>(callback: F) -> impl Drop
where
    F: Fn() + 'static,
{
    // NSEvent monitor for mouse-down outside window
}

This monitor invokes a closure that sends Cancel and removes the window. Non-macOS platforms rely on in-window dismissal paths: center-click cancel, slot activation, or timeout expiration.

Platform-Specific Window Policies

The macOS-specific crates/openlogi-overlay/src/platform.rs ensures the transparent overlay integrates cleanly with the desktop environment:

  • Non-activating: Window never appears in Dock or Command-Tab switcher
  • Shadow removal: Native window shadow disabled for true transparency
  • Click-through transparency: Mouse events pass through transparent regions appropriately

These policies prevent the ephemeral overlay from disrupting normal window management.

Summary

  • The Actions Ring is a dedicated IPC client binary (openlogi-overlay) that receives session data from the agent
  • Cursor-centered positioning combines global cursor query with display-aware edge clamping in ring_window_options
  • Transparent GPUI window uses WindowKind::PopUp with Transparent background for seamless overlay
  • Radial rendering via RingView positions eight slots using geometric placement and handles hover/activate/cancel interactions
  • Click-away dismissal on macOS uses global mouse-down monitoring; other platforms use in-window controls
  • Platform integration ensures the overlay remains invisible to window management while capturing intended input

Frequently Asked Questions

How does the Actions Ring stay centered when the cursor is near screen edges?

The clamp_window_origin helper in crates/openlogi-overlay/src/ring.rs adjusts the window origin when the centered position would place part of the ring off-screen. It takes the desired center point, ring size, and display bounds, then returns a shifted origin that keeps the entire ring visible. This ensures the interface remains fully interactive regardless of cursor position.

What happens if the user tries to open multiple Action Rings simultaneously?

The overlay enforces singleton behavior through a system mutex claimed at startup in main.rs. Only one openlogi-overlay process can run at a time, preventing duplicate rings. The agent coordinates with this singleton; if a new invocation arrives while a ring is visible, the existing window is closed before the new one opens.

Why does the overlay use a separate binary instead of rendering within the main agent?

Separation provides isolation and responsiveness. The overlay's minimal footprint reduces impact on agent performance, while the IPC boundary allows privilege separation—the agent runs with broader system access while the overlay handles untrusted display input. This architecture also enables future platform-specific overlay optimizations without agent modifications.

How are action icons loaded and rendered in the ring slots?

Icons are SVG assets defined in crates/openlogi-ui/src/action_icons.rs, exposed through the IconName enum and Icon component. The slot_element function in ring.rs instantiates these as GPUI elements with hover-state styling, positioning each according to its angular slot placement in the radial layout.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →