# What Is the openlogi‑inject Crate? Platform‑Specific Input Event Synthesis in OpenLogi

> Discover the openlogi-inject crate, OpenLogi's platform-specific layer for synthesizing OS input events like keyboard strokes and mouse clicks from high-level actions. Keep your code platform-agnostic.

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

---

**The openlogi‑inject crate is the platform‑specific input event synthesis layer of OpenLogi, responsible for converting high‑level `Action` definitions into real OS input events—keyboard strokes, mouse clicks, scroll wheels, and system commands—while keeping the rest of the codebase completely platform‑agnostic.**

This crate serves as the I/O boundary of the OpenLogi system. It receives abstract actions from *openlogi‑core* and translates them into concrete input events using native platform APIs: `CGEvent` on macOS, `uinput` on Linux, and `SendInput` on Windows.

## Core Responsibilities of openlogi‑inject

The crate implements several specialized functions that isolate OS‑specific complexity from the main logic:

### Main Dispatch: `execute(&Action)`

The primary entry point `execute()` lives in [`crates/openlogi-inject/src/inject.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject.rs). It uses a `cfg_select!` macro to dispatch to the appropriate backend:

- `macos::execute` – macOS implementation
- `linux::execute` – Linux uinput implementation  
- `windows::execute` – Windows SendInput implementation

This design allows *openlogi‑core* to define actions without any `#[cfg]` conditional compilation clutter.

### Keyboard Chord Handling

Complex modifier combinations require careful state management to handle concurrent usage correctly:

- **`press_hold(&KeyCombo)`** – Creates a synthetic held chord that stays active until the returned `HeldChord` is dropped
- **`HeldChord`** – Implements reference‑counting for shared modifier keys across concurrent chords, ensuring modifiers release only when no chord still needs them
- **Shared state `HELD_OUTPUT`** – Tracks which output keys are currently held to prevent double‑presses or premature releases

### Scroll Event Injection

The crate handles both discrete and smooth scrolling:

| Function | Purpose |
|----------|---------|
| `post_scroll(ScrollDelta)` | Injects immediate scroll events |
| `post_smooth_scroll(ScrollDelta, SmoothScrollPhase)` | Handles animated scroll sequences across multiple frames |
| `ScrollQuantizer` | Preserves high‑resolution deltas when quantizing for platforms that use wheel ticks |

On macOS, scroll events use pixel‑precise `CGEvent` values. Linux and Windows receive quantized wheel tick values.

### Synthetic Event Tagging

To prevent feedback loops where OpenLogi's own input hook captures events it just injected, the crate marks synthesized events with `SYNTHETIC_EVENT_USER_DATA`. The input hook checks this marker and ignores tagged events.

### Browser Navigation Helper (macOS)

`ax_navigate_browser(pid, forward)` uses the macOS Accessibility API to programmatically click the "Back" or "Forward" toolbar buttons of the front‑most browser application.

### Linux Debugging Support

`action_device_path()` returns the filesystem path of the `uinput` device node created for injection. This enables debugging with tools like `evtest` or direct monitoring via `/dev/input/`.

### HID to Windows Keycode Translation

`hid_usage_to_windows` converts USB‑HID usage IDs to Windows virtual‑key codes, handling the mapping layer between standard HID identifiers and Windows‑specific representations.

## Architectural Flow

The data flow through openlogi‑inject follows a clean separation pattern:

1. **Core** creates an `Action` (e.g., `KeyCombo::parse("Ctrl+Shift+A")`)
2. Core calls `openlogi_inject::execute(&action)`
3. `execute` selects the correct backend via `cfg_select!`
4. Backend synthesizes platform‑specific events
5. For keyboard chords, backend coordinates via `HELD_OUTPUT` shared state
6. Scroll gestures pass through `ScrollQuantizer` for frame‑accurate delivery

This keeps injection logic **purely I/O** while the agent, UI, and hook components focus on state management and user interaction.

## Code Examples

### Execute a Simple Action

```rust
use openlogi_core::binding::Action;
use openlogi_inject::execute;

let action: Action = "OpenApplication:/Applications/Calculator.app"
    .parse()
    .unwrap();

execute(&action);  // Dispatches to macOS, Linux, or Windows backend

```

### Hold a Modifier Chord

```rust
use openlogi_inject::press_hold;

let combo = "Ctrl+Shift+Z".parse().unwrap();
let held = press_hold(&combo);  // Synthesizes key-down events

// ... while physical key remains pressed ...

// When `held` drops, key-up events emit automatically

```

### Inject Scroll Events

```rust
use openlogi_inject::{post_scroll, post_smooth_scroll, SmoothScrollPhase};
use openlogi_core::scroll::ScrollDelta;

// Discrete scroll
post_scroll(ScrollDelta::wheel_ticks(0.0, 1.0));  // One tick down

// Smooth scroll animation
let delta = ScrollDelta::wheel_ticks(0.0, 0.125);
post_smooth_scroll(delta, SmoothScrollPhase::Began);
post_smooth_scroll(delta, SmoothScrollPhase::Changed);
post_smooth_scroll(delta, SmoothScrollPhase::Ended);

```

### Linux Device Path Diagnostic

```rust
#[cfg(target_os = "linux")]
fn show_device_path() {
    if let Some(path) = openlogi_inject::action_device_path() {
        println!("Injector uinput device: {}", path.display());
    }
}

```

## Key Source Files

| File | Role |
|------|------|
| [`crates/openlogi-inject/src/lib.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/lib.rs) | Public API entry point, re‑exports `execute`, `press_hold`, `post_scroll`, etc. |
| [`crates/openlogi-inject/src/inject.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject.rs) | Core injection logic, platform dispatch, and shared state management |
| [`crates/openlogi-inject/src/inject/macos.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject/macos.rs) | macOS implementation using `CGEvent` and Accessibility APIs |
| [`crates/openlogi-inject/src/inject/linux.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject/linux.rs) | Linux implementation via `uinput` virtual device |
| [`crates/openlogi-inject/src/inject/windows.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject/windows.rs) | Windows implementation using `SendInput` |
| [`crates/openlogi-inject/examples/inject_action.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/examples/inject_action.rs) | Stand‑alone CLI example demonstrating injector usage |

## Summary

- **openlogi‑inject** is the sole I/O layer of OpenLogi, translating platform‑neutral `Action` types into native OS input events
- **Platform isolation** is achieved through `cfg_select!` dispatch, keeping `#[cfg]` macros out of the core codebase
- **Keyboard chords** use reference‑counted `HeldChord` and `HELD_OUTPUT` state for safe concurrent modifier sharing
- **Scroll injection** supports both discrete events and smooth‑scroll animations with resolution preservation
- **Synthetic event tagging** via `SYNTHETIC_EVENT_USER_DATA` prevents input hook feedback loops
- **macOS-specific** Accessibility API integration enables browser navigation automation
- **Linux-specific** `action_device_path()` aids debugging with standard input tools

## Frequently Asked Questions

### How does openlogi‑inject choose which platform backend to use?

The crate uses a `cfg_select!` macro at compile time in [`crates/openlogi-inject/src/inject.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject.rs) to select the appropriate implementation. This resolves to `macos::execute`, `linux::execute`, or `windows::execute` based on the target triple, with no runtime overhead.

### Why is keyboard chord handling so complex in openlogi‑inject?

Multiple chords may share modifier keys (e.g., `Ctrl+A` and `Ctrl+B` both hold `Ctrl`). The `HeldChord` type and `HELD_OUTPUT` shared state implement reference counting so that `Ctrl` releases only when the last chord needing it drops. This prevents stuck keys or premature modifier release during concurrent operations.

### Can I use openlogi‑inject independently of the full OpenLogi system?

Yes. The [`crates/openlogi-inject/examples/inject_action.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/examples/inject_action.rs) example demonstrates standalone usage. The crate depends only on *openlogi‑core* for `Action` and `ScrollDelta` types, making it suitable for any Rust project needing cross‑platform input synthesis.