# How to Enable Native Scroll Inversion for a Device in OpenLogi

> Learn to enable native scroll inversion in OpenLogi. Adjust device settings or update TOML config to invert scroll for improved usability.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: how-to-guide
- Published: 2026-09-11

---

**To enable native scroll inversion in OpenLogi, toggle the "Invert Scroll" switch in the device settings UI (if supported), or manually set `invert_scroll = true` in the device's TOML configuration entry; the OpenLogi agent will then write this setting directly to the device's firmware via HID++ on the next configuration reload.**

OpenLogi provides **native scroll inversion** capabilities that flip scroll direction at the firmware level rather than through software remapping. This feature is stored in per-device configuration and applied through the HID++ protocol, ensuring the setting persists across reconnections. Whether you prefer the graphical interface or direct configuration editing, enabling this feature requires device support for the `scroll_inversion` capability as reported by the hardware.

## Checking Device Support for Scroll Inversion

Before attempting to enable inversion, verify that your device supports the native HID++ scroll inversion feature. The OpenLogi desktop application queries this capability from the device's feature table during enumeration.

The support check occurs in [`crates/openlogi-desktop/src/state/scroll.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/state/scroll.rs) within the `AppState::current_scroll_inversion_supported()` method:

```rust
// crates/openlogi-desktop/src/state/scroll.rs (lines 24-29)
pub fn current_scroll_inversion_supported(&self) -> bool {
    self.current_device()
        .map(|d| d.capabilities.scroll_inversion)
        .unwrap_or(false)
}

```

This method returns `true` only when the `DeviceRecord` contains `Capabilities::scroll_inversion` in its HID++ feature table. If the device lacks this capability, the UI toggle remains disabled to prevent incompatible configuration attempts.

## Enabling Scroll Inversion via the Desktop UI

When a supported device is selected, the **Scrolling** card in the device detail view presents an "Invert Scroll" toggle. This interface element binds directly to the application state and triggers both configuration persistence and agent reload.

In [`crates/openlogi-desktop/src/app/detail.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/app/detail.rs) (lines 31-38), the toggle is implemented as follows:

```rust
Toggle::new("invert-scroll-toggle")
    .selected(state.invert_scroll)
    .disabled(!state.scroll_inversion_supported)
    .on_change(|inverted, _window, cx| {
        AppState::update(cx, |state, _cx| {
            state.commit_invert_scroll(*inverted);
        });
    })

```

When you interact with this toggle, the `commit_invert_scroll` method in [`crates/openlogi-desktop/src/state/scroll.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/state/scroll.rs) (lines 46-48) handles the persistence:

```rust
pub fn commit_invert_scroll(&mut self, inverted: bool) {
    self.config.set_invert_scroll(inverted);
    self.persist_and_reload();
}

```

This sequence updates the configuration file and triggers a full agent reload, ensuring the change applies immediately.

## Configuring Scroll Inversion Manually via TOML

Advanced users can enable native scroll inversion by editing the OpenLogi configuration file directly. This approach bypasses the UI and allows automation or batch configuration of multiple devices.

The setting resides in the per-device `LinkOverrides` structure defined in [`crates/openlogi-core/src/config/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/device.rs) (lines 104-108):

```rust
pub struct LinkOverrides {
    pub invert_scroll: Option<bool>,
    // ... additional override fields
}

```

To enable inversion manually, add or modify the device entry in your OpenLogi configuration file:

```toml

# ~/.config/openlogi/config.toml

[devices."direct:046d:c08d:unit:6be9d300"]
invert_scroll = true

```

The configuration key follows the format `direct:<vid>:<pid>:unit:<serial>`. When the agent reloads its configuration, it reads this value through `Config::set_invert_scroll` implemented in [`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs) (lines 60-73), which updates the specific device's `LinkOverrides` entry.

## How the Agent Applies Native Inversion

After configuration persistence, the OpenLogi agent translates the boolean setting into a HID++ command sent directly to the device firmware. This native approach ensures the scroll direction flips at the hardware level, eliminating the need for operating-system-level remapping.

The agent-side implementation in [`crates/openlogi-hid/src/host.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hid/src/host.rs) (lines 109-110) handles the low-level communication:

```rust
// crates/openlogi-hid/src/host.rs
pub fn set_scroll_inversion(&self, device: &Device, inverted: bool) -> Result<()> {
    openlogi_hid::set_scroll_inversion(device.handle(), inverted)
}

```

When the agent processes a configuration reload, it checks `Config::invert_scroll` for each connected device. If the value differs from the current firmware state, it invokes `device::set_scroll_inversion` to program the new setting. Because this modifies the device's internal HID++ registers, the inversion persists across power cycles and reconnections without requiring continuous software intervention.

## Summary

- **Capability verification** is required before enabling inversion; the device must report `scroll_inversion` support in its HID++ feature table via `AppState::current_scroll_inversion_supported()`.
- **UI activation** involves toggling the "Invert Scroll" switch in the Scrolling card, which calls `commit_invert_scroll()` to persist the change and reload the agent.
- **Manual configuration** allows setting `invert_scroll = true` in the device's TOML entry under `[devices."<device-key>"]`.
- **Firmware-level application** occurs when the agent calls `set_scroll_inversion()` via the HID++ backend, ensuring hardware-native persistence.

## Frequently Asked Questions

### Does native scroll inversion persist after unplugging the device?

Yes. Because OpenLogi writes the inversion flag directly to the device's HID++ registers via the `openlogi_hid::set_scroll_inversion` call, the setting survives power cycles and USB reconnections. The firmware maintains this state independently of the host computer's configuration.

### Why is the scroll inversion toggle grayed out in the UI?

The toggle disables itself when `AppState::current_scroll_inversion_supported()` returns `false`, indicating the selected device lacks the `scroll_inversion` capability in its feature table. This occurs with older hardware or devices that do not implement the relevant HID++ feature set required for native inversion control.

### Can I enable scroll inversion for devices that don't support native HID++ scroll inversion?

No. OpenLogi only supports native scroll inversion for hardware that explicitly reports the capability. The `LinkOverrides` configuration accepts the `invert_scroll` boolean, but the agent will fail to apply it if the device doesn't support the underlying HID++ command. For unsupported devices, you must use operating-system-level scroll remapping instead.

### How do I verify that the inversion was applied to the device firmware?

After toggling the setting or reloading the configuration, test the scroll direction physically. The change takes effect immediately upon successful HID++ communication in [`crates/openlogi-hid/src/host.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hid/src/host.rs). If the direction remains unchanged, check the agent logs for errors during the `set_scroll_inversion` call, which typically indicate communication failures or unsupported feature errors.