OpenLogi Input Injection Methods: Cross-Platform OS-Level Event Synthesis
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. This function receives a high-level Action enum (originating from openlogi_core::binding) and routes it to platform-specific implementations using conditional compilation (#[cfg]).
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/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 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/master/crates/openlogi-inject/src/inject/macos.rs)
Linux Virtual Input Device Management
The Linux implementation in 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/master/crates/openlogi-inject/src/inject/linux.rs)
Windows SendInput API Integration
The Windows implementation in 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/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:
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/master/crates/openlogi-inject/examples/inject_action.rs)
For system-native actions like revealing the desktop, the code uses the NativeAction enum:
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 incrates/openlogi-inject/src/inject.rsprovides a single API for all platforms, routing to OS-specific backends via compile-time configuration. - Native OS Integration – macOS uses
CGEventPostwith CoreGraphics; Linux utilizes uinput/evdev virtual devices; Windows employs theSendInputWin32 API. - Modifier Safety – The
HELD_OUTPUTglobal state with reference counting ensures correct modifier key press/release ordering across complex chorded shortcuts. - Graceful Degradation – Unsupported features (such as
TypeTexton 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.
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 →