# How to Configure Per-Direction Gesture Bindings in OpenLogi

> Learn to configure per-direction gesture bindings in OpenLogi. Map swipes and clicks to specific actions using TOML tables under bindings.GestureButton for personalized control.

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

---

**OpenLogi maps the gesture button to five distinct actions—Up, Down, Left, Right (swipes), and Click (press without movement)—allowing per-direction configuration via TOML tables under `bindings.GestureButton`.**

OpenLogi is an open-source input customization framework that treats the gesture button as a multi-directional input device. Configuring per-direction gesture bindings requires editing device-specific TOML configuration files to map each swipe direction to system actions. This article breaks down the configuration syntax and the internal Rust implementation that processes these bindings according to the OpenLogi source code.

## TOML Configuration Syntax for Gesture Bindings

Per-direction gesture bindings are defined in a device's configuration section using a dedicated `GestureButton` table. Each direction represents a key mapping to an action string, as documented in **[`docs/config.example.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/config.example.toml)**.

```toml
[devices."receiver:aabbccdd:slot:1".bindings.GestureButton]
Click = "MissionControl"
Up    = "MissionControl"
Down  = "AppExpose"
Left  = "PreviousDesktop"
Right = "NextDesktop"

```

The configuration supports standard TOML syntax for device-specific overrides. For example, to customize gestures for an MX Master mouse:

```toml
[devices."unit:6be9d300".bindings.GestureButton]
Up    = "MissionControl"
Down  = "ShowDesktop"
Left  = "PrevTab"
Right = "NextTab"
Click = "AppExpose"

```

## Internal Architecture and Defaults

The system models the five gesture slots using the `GestureDirection` enum and provides automatic fallback values.

### The GestureDirection Enum

The canonical representation of gesture directions is defined in **[`crates/openlogi-core/src/binding/gesture.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/gesture.rs)**. The `GestureDirection` enum provides the ordering, labels, and translation keys for all five possible inputs: **Up**, **Down**, **Left**, **Right**, and **Click**.

### Default Gesture Bindings

When a user omits a direction from their configuration, OpenLogi supplies sensible defaults via the `default_gesture_binding` function in **[`crates/openlogi-core/src/binding/defaults.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/defaults.rs)**. The following table shows the fallback actions assigned when a gesture button is first promoted to a gesture binding:

| Direction | Default Action |
|-----------|----------------|
| Up | `Action::MissionControl` |
| Down | `Action::ShowDesktop` |
| Left | `Action::PrevTab` |
| Right | `Action::NextTab` |
| Click | `Action::AppExpose` |

The full default binding map is seeded via `default_binding_for` in the same file, ensuring that new gesture configurations inherit these values immediately.

### Config Parsing and Merging

During configuration loading, the raw gesture map (`raw.gesture_bindings`) is restructured under `ButtonId::GestureButton` in **[`crates/openlogi-core/src/config/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/device.rs)**. The parser handles backward compatibility by merging gesture maps with legacy `button_bindings` entries. Critically, the logic ensures that a legacy single `GestureButton` entry does **not** resolve to a `Binding::Single`, preserving the multi-directional nature of the input.

## Runtime Projection

At runtime, the system extracts the active per-direction map through the `oshook_gestures_for` helper function in **[`crates/openlogi-core/src/bindings.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/bindings.rs)** (lines 29-38). This function filters the binding collection to return only `Binding::Gesture` entries for a given device and application context. The resulting map translates raw XY swipe events from the hardware into the configured `Action` variants defined in the user's TOML file.

## Summary

- **Five Directions**: OpenLogi recognizes Up, Down, Left, Right swipes and a Click (non-swipe press) as distinct gesture inputs.
- **TOML Syntax**: Configure bindings under `[devices."id".bindings.GestureButton]` with direction keys mapping to action strings.
- **Default Fallbacks**: Unspecified directions automatically populate with values from `default_gesture_binding` in [`defaults.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/defaults.rs).
- **Internal Types**: The `GestureDirection` enum in [`gesture.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/gesture.rs) provides the canonical type system for these inputs.
- **Runtime Resolution**: The `oshook_gestures_for` function extracts per-device, per-application gesture maps for event translation.

## Frequently Asked Questions

### What are the five configurable gesture directions in OpenLogi?

OpenLogi supports **Up**, **Down**, **Left**, **Right** (representing swipe movements), and **Click** (representing a press without directional movement). These are defined in the `GestureDirection` enum located in [`crates/openlogi-core/src/binding/gesture.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/gesture.rs).

### Where are default gesture bindings defined in the OpenLogi source code?

Default bindings are defined in the `default_gesture_binding` function within **[`crates/openlogi-core/src/binding/defaults.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/defaults.rs)**. This function returns `Action::MissionControl` for Up, `Action::ShowDesktop` for Down, `Action::PrevTab` for Left, `Action::NextTab` for Right, and `Action::AppExpose` for Click.

### How does OpenLogi prevent legacy single-button entries from interfering with gesture configuration?

During config parsing in [`crates/openlogi-core/src/config/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/device.rs), the system explicitly merges raw gesture maps while ensuring that legacy single `GestureButton` entries do not resolve to `Binding::Single`. This preserves the multi-directional structure required for gesture processing.

### Can gesture bindings be configured per-application in OpenLogi?

Yes. The `oshook_gestures_for` function in [`crates/openlogi-core/src/bindings.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/bindings.rs) extracts gesture maps for specific device and application contexts, allowing the runtime to apply different per-direction gesture bindings depending on the active application.