# OpenLogi Input Injection Methods: Cross-Platform OS-Level Event Synthesis

> Explore OpenLogi input injection methods for cross-platform OS-level event synthesis. Inject events on macOS Linux and Windows with this powerful tool.

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

---

**OpenLogi performs OS-level input injection through the `openlogi-inject` crate, translating high-level `Action` enums into native platform events using CoreGraphics on macOS, uinput on Linux, and Win32 `SendInput` on Windows.**

The AprilNEA/OpenLogi repository implements sophisticated input injection methods that allow applications to synthesize keyboard, mouse, and system actions across macOS, Linux, and Windows. At the core of this capability lies the `openlogi-inject` crate, which exposes a unified API for dispatching platform-native events from a high-level abstraction. Understanding these OpenLogi input injection methods reveals how the system achieves reliable cross-platform automation without requiring separate OS-specific daemons.

## Architecture of the Injection Pipeline

The injection system follows a three-stage pipeline that abstracts platform differences while preserving native performance characteristics.

### Public API Entry Point

The primary interface is `openlogi_inject::execute(&Action)`, defined in [`crates/openlogi-inject/src/inject.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject.rs). This function receives a high-level `Action` enum (originating from `openlogi_core::binding`) and routes it to platform-specific implementations using conditional compilation (`#[cfg]`).

```rust
use openlogi_core::binding::{Action, Shortcut};
use openlogi_inject::execute;

// Dispatch a Copy shortcut (Cmd-C on macOS, Ctrl-C on Linux/Windows)
let action = Action::from(Shortcut::Copy);
execute(&action);

```

*Source:* [[`inject.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/inject.rs)](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-inject/src/inject.rs)

### Action-to-Effect Classification

Each platform implementation classifies the incoming `Action` into a specific `Effect` variant:

- **Click** – Mouse button press/release events
- **Shortcut** – Chorded key combinations with modifiers
- **Key** – Individual keystrokes
- **Scroll** – Wheel or trackpad scroll deltas
- **Media** – Media control keys (play, pause, volume)
- **Native** – Window manager actions (Mission Control, Show Desktop)
- **Script** – AppleScript, shell commands, or workflow execution
- **Text** – Unicode text input (macOS only)

## Platform-Specific Implementation Details

### macOS Input Synthesis via CoreGraphics

The macOS implementation in [`crates/openlogi-inject/src/inject/macos.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject/macos.rs) utilizes the **core-graphics** crate to construct `CGEvent` objects. These events are posted to the system using `CGEventPost(kCGHIDEventTap, …)`, ensuring they enter the event stream at the HID (Human Interface Device) layer where physical inputs are processed.

For window manager integration, the code leverages private SPIs (System Programming Interfaces) to trigger Mission Control, Show Desktop, and other macOS-specific actions that lack public APIs. Unicode text input is handled through dedicated text injection paths separate from raw key events.

*Source:* [[`macos.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/macos.rs)](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-inject/src/inject/macos.rs)

### Linux Virtual Input Device Management

The Linux implementation in [`crates/openlogi-inject/src/inject/linux.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject/linux.rs) creates a shared **uinput** virtual device that is lazily initialized on first use. This approach avoids requiring root privileges for device creation at startup while maintaining persistent access for subsequent injections.

Keyboard synthesis maps logical keys to Linux input event codes (`KEY_*`) through the `evdev::uinput::VirtualDevice` interface. Mouse clicks utilize `BTN_LEFT`, `BTN_RIGHT`, and `BTN_MIDDLE` codes, while scroll events emit relative axis events (`REL_WHEEL`, `REL_HWHEEL`) with quantized delta values.

System-level actions such as screen locking or suspension are performed over D-Bus by communicating with the `logind` service, ensuring compatibility with systemd-based distributions without requiring direct ACPI calls.

*Source:* [[`linux.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/linux.rs)](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-inject/src/inject/linux.rs)

### Windows SendInput API Integration

The Windows implementation in [`crates/openlogi-inject/src/inject/windows.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject/windows.rs) calls the Win32 `SendInput` API (exposed through the **windows-sys** crate) to synthesize input events. Keyboard shortcuts are emitted as virtual-key codes (VK_*) with proper scan codes and extended-key flags.

Mouse clicks utilize `MOUSEEVENTF_LEFTDOWN`, `MOUSEEVENTF_RIGHTDOWN`, and related flags, while scroll events employ `MOUSEEVENTF_WHEEL` for vertical and `MOUSEEVENTF_HWHEEL` for horizontal scrolling. The implementation handles hi-dpi cursor coordinates by applying system metrics scaling.

Native window manager actions map to common Windows shortcuts—for example, translating "Show Desktop" to `Win + D` and "Mission Control" to `Win + Tab`—providing consistent behavior across platforms where direct API equivalents exist.

*Source:* [[`windows.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/windows.rs)](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-inject/src/inject/windows.rs)

## Supporting Infrastructure

### Global Held-Key Tracking

To handle complex chorded shortcuts correctly, the system maintains a global state called `HELD_OUTPUT` (wrapped in `LazyLock<Mutex<HeldOutput>>`). This structure tracks reference counts for modifier keys (Cmd, Ctrl, Alt, Shift) across overlapping actions, ensuring that modifier press/release sequences remain balanced even when multiple actions share common modifiers.

When injecting a shortcut like `Cmd-Shift-T`, the tracker prevents premature release of `Cmd` if another active action still requires it, eliminating race conditions in rapid-fire input sequences.

### Scroll Quantization

High-resolution scroll inputs from modern trackpads and mice require platform-specific handling. The implementation maintains separate `ScrollQuantizer` instances for each platform to smooth delta accumulation, converting floating-point scroll distances into the integer tick counts expected by `CGEvent` (macOS), `REL_WHEEL` events (Linux), and `MOUSEEVENTF_WHEEL` (Windows).

### Non-Blocking Script Execution

The `dispatch_script` helper spawns dedicated threads to execute AppleScript (macOS), shell commands, or workflow steps. This architecture prevents long-running scripts from blocking the critical input-tap thread, maintaining low latency for hardware button remapping while allowing complex automation sequences to proceed asynchronously.

## Practical Implementation Examples

Injecting mouse clicks follows the same pattern as keyboard shortcuts, utilizing the `Action` enum's `From` implementation for `MouseButton`:

```rust
use openlogi_core::binding::{Action, MouseButton};
use openlogi_inject::execute;

// Inject a left-click at the current cursor position
let click = Action::from(MouseButton::Left);
execute(&click);

```

*Source:* [[`inject_action.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/inject_action.rs)](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-inject/examples/inject_action.rs)

For system-native actions like revealing the desktop, the code uses the `NativeAction` enum:

```rust
use openlogi_core::binding::{Action, NativeAction};
use openlogi_inject::execute;

// Trigger the platform's "Show Desktop" action
let show_desktop = Action::from(NativeAction::ShowDesktop);
execute(&show_desktop);

```

*Source:* Same example file above.

## Summary

- **Unified Entry Point** – The `execute(&Action)` function in [`crates/openlogi-inject/src/inject.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-inject/src/inject.rs) provides a single API for all platforms, routing to OS-specific backends via compile-time configuration.
- **Native OS Integration** – macOS uses `CGEventPost` with CoreGraphics; Linux utilizes uinput/evdev virtual devices; Windows employs the `SendInput` Win32 API.
- **Modifier Safety** – The `HELD_OUTPUT` global state with reference counting ensures correct modifier key press/release ordering across complex chorded shortcuts.
- **Graceful Degradation** – Unsupported features (such as `TypeText` on Linux/Windows) log warnings rather than panicking, allowing cross-platform workflows to degrade safely.

## Frequently Asked Questions

### How does OpenLogi handle modifier keys differently across operating systems?

OpenLogi normalizes modifier behavior through the `HELD_OUTPUT` tracking system while respecting platform conventions. On macOS, the system maps logical "Command" to physical keys, while Linux and Windows use "Ctrl" for equivalent shortcuts, handled automatically during the `Action` to `Effect` classification phase.

### What happens if I try to inject text on Linux or Windows?

The `TypeText` effect currently only implements full Unicode input support on macOS via CoreGraphics text events. On Linux and Windows, attempting to inject raw text will log an unsupported feature warning rather than crashing, as these platforms require alternative input method integration not yet implemented in the current codebase.

### Why does the Linux implementation use uinput instead of X11 or Wayland protocols?

The uinput subsystem operates below the display server layer, making the injection method agnostic to whether the user runs X11, Wayland, or a raw TTY session. This approach avoids dependencies on specific display server extensions and works in embedded or headless environments where D-Bus system actions remain available.

### Can OpenLogi inject inputs while the system is locked?

On Windows and Linux, certain injections (particularly `SendInput` and uinput events) will fail or queue until unlock because the OS input stacks restrict event processing during secure attention sequences. macOS permits some `CGEventPost` injections to pass through depending on the `kCGHIDEventTap` destination and current security policy, though Mission Control and similar native actions require an unlocked session.