How to Configure Per-Direction Gesture Bindings in OpenLogi: Complete TOML Guide

OpenLogi uses a plain TOML configuration file where gesture buttons map distinct actions to each swipe direction (up, down, left, right, and optional diagonals) through a gesture-direction hash map in the bindings table.

OpenLogi is an open-source input remapping tool for Logitech devices that reads all user settings from a TOML file shared between its GUI and background agent. For gesture-capable hardware, you can bind individual actions to specific swipe directions rather than treating the button as a simple on/off switch. This per-direction binding system gives precise control over multi-directional input gestures.

Understanding the Gesture-Direction Map Structure

The bindings table under each [[devices]] entry supports three configuration patterns. According to the Configuration documentation, the third pattern enables per-direction gesture bindings:

Pattern Syntax Use Case
Single action Button = "Action" Standard press-to-activate buttons
Short/long pair Button = { short = "ActionA", long = "ActionB" } Dual-function buttons with timing differentiation
Gesture-direction map Button = { up = "A", down = "B", left = "C", right = "D" } Per-direction gesture bindings with distinct actions per swipe

When a gesture button is held, OpenLogi's agent monitors pointer movement or native gesture sensor data. Upon detecting a directional swipe, it looks up the corresponding key in your map and fires that action. Unspecified directions are silently ignored.

Required TOML Schema and Device Structure

OpenLogi requires schema version 7 in your configuration file, as noted in docs/CONFIGURATION.md#L39-L40. Each device entry uses the physical key format [devices."receiver:<id>:slot:<n>"] and contains device metadata plus the bindings table.

Complete Device Entry Template

[devices."receiver:123456:slot:1"]
custom_name = "MX Master 3"
enabled     = true
dpi        = 1200
thumbwheel_sensitivity = 14

# Per-direction gesture bindings

bindings = {
    # Standard buttons

    Button1 = "Copy",
    Button2 = { short = "Back", long = "Forward" },

    # Gesture button with per-direction actions

    GestureButton = {
        up    = "VolumeUp",
        down  = "VolumeDown",
        left  = "PreviousTrack",
        right = "NextTrack"
    }
}

Supported Gesture Directions

OpenLogi recognizes eight directional inputs for gesture buttons. The four cardinal directions are required for full functionality; diagonal directions are optional but available.

Direction Key Swipe Direction
up Vertical upward
down Vertical downward
left Horizontal left
right Horizontal right
up_left (optional) Diagonal up-left
up_right (optional) Diagonal up-right
down_left (optional) Diagonal down-left
down_right (optional) Diagonal down-right

Full Eight-Direction Configuration Example

[devices."receiver:00112233:slot:2"]
custom_name = "MX Master 2S"
dpi        = 1000
thumbwheel_sensitivity = 14

bindings = {
    # CID 0xD0 gesture button with all directions mapped

    Thumbwheel = {
        up         = "ShowDesktop",
        down       = "MissionControl",
        left       = "PreviousSpace",
        right      = "NextSpace",
        up_left    = "BrightnessUp",
        up_right   = "BrightnessDown",
        down_left  = "MediaPlayPause",
        down_right = "MediaStop"
    },

    # Regular buttons for comparison

    Button3 = "PlayPause",
    Button4 = { short = "Back", long = "Forward" }
}

Partial Direction Bindings

You are not required to define all directions. Omitting a direction key disables that gesture entirely—useful when you want to prevent accidental triggers in specific orientations.

bindings = {
    GestureButton = {
        up   = "VolumeUp",
        down = "VolumeDown"
        # left and right omitted: horizontal swipes are ignored

    }
}

How Per-Direction Gestures Are Processed Internally

The gesture pipeline spans multiple crates in the OpenLogi source tree:

  1. Event Capture: [crates/openlogi-hook/src/lib.rs](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-hook/src/lib.rs) captures raw HID++ gesture events from the device hardware, as documented in [crates/openlogi-hook/AGENTS.md](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-hook/AGENTS.md).

  2. Direction Accumulation: crates/openlogi-device/src/session/gesture/ contains the swipe accumulator that tracks pointer displacement while the gesture button remains held.

  3. Action Resolution: The accumulated direction string (e.g., "up_left") is matched against your TOML map keys. The corresponding action variant—defined in the core Action enum—gets queued for execution.

  4. OS Injection: [crates/openlogi-inject/src/inject.rs](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-inject/src/inject.rs) performs the final system-level input injection.

This architecture means your TOML edits directly control the action variant passed through the entire pipeline.

Configuration File References

File Purpose
docs/CONFIGURATION.md Complete TOML schema documentation including bindings table structure
docs/config.example.toml Validated working example with per-direction gesture configurations
crates/openlogi-core/src/action.rs Action enum variants available for TOML strings

Applying Your Configuration

After editing your config.toml:

  1. Save the file with valid TOML syntax (verify with toml-test or similar if unsure)
  2. Reload through the OpenLogi GUI, or restart the background agent
  3. Test gestures on your configured device; omitted directions should produce no response

Summary

  • OpenLogi configures per-direction gesture bindings through TOML hash maps in the bindings table, not through a graphical binding interface
  • Use the pattern GestureButton = { up = "Action", down = "Action", ... } to assign distinct actions to each swipe direction
  • Eight directions are supported: four cardinal and four diagonal; undefined directions are ignored during gesture recognition
  • The configuration flows from raw HID++ capture through crates/openlogi-hook, direction accumulation in crates/openlogi-device/src/session/gesture/, and final injection via crates/openlogi-inject
  • Schema version 7 is mandatory; reference docs/config.example.toml for syntax validation

Frequently Asked Questions

What happens if I define both a single action and a gesture-direction map for the same button?

You cannot combine patterns for a single button key. Each bindings entry must use exactly one of the three forms: single string, short/long table, or direction map. The TOML parser will reject overlapping definitions. Choose the pattern that matches your button's hardware capabilities—gesture buttons should use the direction map exclusively.

Can I use mouse movement instead of the native gesture sensor for direction detection?

OpenLogi supports both native HID++ gesture events and pointer-based accumulation. The crates/openlogi-device/src/session/gesture/ module handles the abstraction; your TOML configuration remains identical regardless of detection method. The engine automatically selects the appropriate source based on device capabilities reported during initialization.

Why are my diagonal gestures not registering?

Diagonal detection requires sufficient displacement in both axes during the swipe. If your thumbwheel_sensitivity or DPI setting is too low, small diagonal movements may be categorized as purely horizontal or vertical. Increase the sensitivity value in your device configuration, or exaggerate diagonal swipe angles during testing. Verify your TOML uses the correct underscore format: up_left, not upLeft or up-left.

Where can I find the complete list of valid action strings for my gesture map?

Valid action strings are defined as enum variants in [crates/openlogi-core/src/action.rs](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-core/src/action.rs). The docs/config.example.toml file also contains extensively commented examples showing available actions. If you reference an undefined action string, the agent will log a configuration error at startup and skip that binding entry.

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 →