# How to Configure Short and Long Press Bindings in OpenLogi

> Learn how to configure short and long press bindings in OpenLogi using TOML. Understand button press durations and the ButtonBinding struct for custom actions.

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

---

**OpenLogi maps button presses under 500 ms to `short` actions and sustained holds of 500 ms or longer to `long` actions through TOML configuration entries parsed by the `ButtonBinding` struct in [`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs).**

OpenLogi is an open-source runtime for Logitech HID++ devices that exposes button customization through a declarative TOML interface. When you configure short and long press bindings in OpenLogi, you create distinct execution paths for quick taps versus deliberate holds, allowing a single physical button to serve dual purposes based on timing thresholds enforced by the core library.

## Understanding the 500‑Millisecond Threshold

OpenLogi’s runtime agent measures every button press duration to determine which action to dispatch:

- **Short press**: Release occurs **< 500 ms** after the press event → executes the `short` binding.
- **Long press**: Button remains held **≥ 500 ms** → executes the `long` binding once the threshold is reached.

This timing logic is implemented in the runtime agent, which interfaces with the core library (`openlogi-core`) to resolve the appropriate `ButtonBinding` entry and validate the action name against the internal catalog defined in [`crates/openlogi-core/src/action.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/action.rs).

## Configuration File Location and Structure

User-defined bindings reside in a TOML file that the `Config` struct deserializes at startup.

**Default path**: `~/.config/openlogi/config.toml`

**Reference example**: The repository provides a canonical template at [`docs/config.example.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/config.example.toml) that demonstrates valid syntax for combined short and long mappings.

The parser, located in [`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs), instantiates a `ButtonBinding` for each entry containing optional `short` and `long` string fields. Both fields accept identifiers that must exist in the action catalog (e.g., `ShowDesktop`, `MissionControl`, `VolumeUp`, `PlayPause`).

## Defining Button Bindings in TOML

Each button entry uses inline table syntax to assign actions. You may define `short`, `long`, or both; omitting a field prevents that press type from triggering any action.

```toml

# ~/.config/openlogi/config.toml

Button1 = { short = "VolumeUp" }
Button2 = { long = "LaunchTerminal" }
Button3 = { short = "PreviousTrack", long = "PlayPause" }
DpiToggle = { short = "ShowDesktop", long = "MissionControl" }

```

- **Single-action bindings**: Assign only `short` or `long` if you require only one behavior.
- **Dual-action bindings**: Provide both keys to enable context-sensitive functionality (e.g., a brief click shows the desktop, while a hold opens Mission Control).

## Complete Configuration Examples

The following snippet demonstrates the three common configuration patterns supported by the `Config` parser:

```toml

# ~/.config/openlogi/config.toml

# Example: Several buttons with short/long actions

# 1. Short-press only

SideButtonFront = { short = "Copy" }

# 2. Long-press only

SideButtonBack = { long = "Paste" }

# 3. Both actions on one button (500ms threshold determines which fires)

GestureButton = { short = "Undo", long = "Redo" }

# 4. DPI toggle with distinct behaviors

DpiToggle = { short = "ShowDesktop", long = "MissionControl" }

```

After saving the file, you must restart the OpenLogi agent or trigger a config reload via the UI for the `ButtonBinding` changes to take effect.

## Technical Implementation Details

When the runtime initializes, the `Config` struct in [`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs) deserializes each TOML entry into a Rust struct resembling:

```rust
// Conceptual representation from crates/openlogi-core/src/config.rs
struct ButtonBinding {
    short: Option<String>,
    long: Option<String>,
}

```

The runtime agent monitors hardware events and calculates press duration. Upon crossing the 500 ms boundary, it queries the corresponding `ButtonBinding` field and dispatches the action string to the OS or OpenLogi’s internal command system. Invalid action names that do not appear in [`crates/openlogi-core/src/action.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/action.rs) will fail validation during config loading.

## Summary

- OpenLogi uses a **500 ms threshold** to differentiate short (`< 500 ms`) and long (`≥ 500 ms`) press behaviors.
- Bindings are defined in **`~/.config/openlogi/config.toml`** using the syntax `ButtonName = { short = "Action", long = "Action" }`.
- The **`Config`** struct in **[`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs)** parses the TOML into **`ButtonBinding`** instances with optional `short` and `long` fields.
- Action names must match entries in the action catalog located in **[`crates/openlogi-core/src/action.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/action.rs)**.
- Changes require a **restart or UI reload** to activate.

## Frequently Asked Questions

### What is the exact timing threshold for long press detection?

The OpenLogi runtime treats any button held for **500 milliseconds or longer** as a long press. Releases occurring before this threshold execute the short press action instead. This duration is hard-coded in the runtime agent logic and is not currently user-configurable via TOML.

### Can I assign the same action to both short and long presses on one button?

Yes. The `ButtonBinding` struct accepts identical strings for both `short` and `long` fields, though this effectively disables the timing distinction. Alternatively, omitting one field leaves that press type unmapped, which is useful when you want to ignore accidental long presses or short taps.

### Where can I find the list of valid action names for my configuration?

Valid identifiers are defined in the action catalog within **[`crates/openlogi-core/src/action.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/action.rs)**. Common examples include `ShowDesktop`, `MissionControl`, `VolumeUp`, `VolumeDown`, `PlayPause`, `PreviousTrack`, and `LaunchTerminal`. Refer to this source file or the repository’s [`docs/CONFIGURATION.md`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/CONFIGURATION.md) for the complete, up-to-date list.

### Do I need to restart OpenLogi after editing the config.toml file?

Yes. The `Config` struct loads and deserializes the TOML file once at startup. After modifying `~/.config/openlogi/config.toml`, you must either restart the OpenLogi agent process or use the application’s UI reload function to re-parse the `ButtonBinding` definitions and apply new short or long press mappings.