# OpenLogi Long-Press and Short-Press Binding Semantics: The 500ms SOOM Threshold Model

> Understand OpenLogi long-press vs short-press binding semantics. Learn how the 500ms SOOM threshold model differentiates button press durations for precise control.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: internals
- Published: 2026-08-26

---

**OpenLogi distinguishes between short-press and long-press bindings using a 500ms threshold where short-press actions fire immediately upon button activation while long-press actions only dispatch after the button is held longer than the configured `LONG_PRESS_THRESHOLD`.**

OpenLogi implements a sophisticated input handling system called the SOOM (Smart Shift) threshold model that allows a single physical button to trigger different logical actions based on press duration. Understanding the **long-press and short-press binding semantics** is essential for configuring advanced workflows that distinguish between quick taps and deliberate holds. The system uses the `LONG_PRESS_THRESHOLD` defined in the core binding module to determine which action executes.

## The SOOM Threshold Model Fundamentals

The SOOM threshold model enables a single physical button to expose two distinct logical actions through temporal differentiation.

- **Short-press bindings** dispatch immediately when the button is pressed (or released for toggle-type actions), requiring no additional timing checks.
- **Long-press bindings** only activate after the button is held continuously for longer than the 500ms threshold, preventing accidental triggers from brief contacts.

When a button-down event occurs, OpenLogi's input layer records the timestamp and monitors elapsed time on each subsequent tick. If the button releases before exceeding the threshold, the system processes any configured short-press binding and discards the long-press candidate.

## Short-Press Binding Implementation

Short-press represents the default binding mode in OpenLogi, optimized for responsiveness and immediate feedback.

According to the OpenLogi source code in [`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs), short-press actions commit to the state machine without wrapping in duration-tracking types. These bindings execute as soon as the input layer registers the button event, making them ideal for high-frequency operations like copy, undo, or paste that must respond instantly to user input.

The dispatch logic bypasses the threshold checking mechanism entirely, ensuring zero latency beyond the hardware's native report rate.

## Long-Press Binding Implementation

Long-press bindings introduce deliberate latency to prevent accidental activation of secondary functions.

### The LONG_PRESS_THRESHOLD Constant

The threshold value resides in [`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs) at line 43, where `LONG_PRESS_THRESHOLD` defines the default 500ms duration that distinguishes long-press from short-press events. This constant is wrapped by the `LongPressBinding` type defined in [`crates/openlogi-core/src/value.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/value.rs).

When the input subsystem receives a button event, it calculates elapsed time against this threshold. Once the duration exceeds 500ms, the `LongPressBinding` becomes active and dispatches the associated action to the device or GUI.

### Fallback Behavior

If the user releases the button before the 500ms threshold elapses, OpenLogi discards the long-press binding and falls back to any configured short-press binding for that button. This creates a hierarchical input system where brief interactions trigger primary actions while sustained holds access secondary functions like custom scripts or mode switches.

## Practical Code Implementation

The binding system distinguishes these modes through type wrapping and module organization.

```rust
use openlogi_core::binding::{Action, LongPressBinding, LONG_PRESS_THRESHOLD};

// Short-press binding: fires immediately on button press
state.commit_binding(ButtonId::Back, Action::Undo);

// Long-press binding: fires only after exceeding the 500ms threshold
state.commit_binding(
    ButtonId::Back,
    Action::LongPress(LongPressBinding::new(Action::Copy)),
);

```

In this example, quickly pressing the **Back** button triggers `Undo` immediately. Holding **Back** for longer than `LONG_PRESS_THRESHOLD` (500ms) suppresses the undo action and instead triggers `Copy`.

## Key Source Files and Architecture

Understanding the file organization clarifies how these semantics propagate through the system:

- **[`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs)** – Defines `LONG_PRESS_THRESHOLD` at line 43 and exports the core binding types including `LongPressBinding`.
- **[`crates/openlogi-core/src/value.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/value.rs)** – Contains the concrete implementation of `LongPressBinding` and the threshold value storage.
- **[`crates/openlogi-device/src/session/gesture.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/session/gesture.rs)** – Implements gesture recognition logic that respects press-duration semantics for wheel-based actions while holding buttons.
- **[`crates/openlogi-desktop/src/state/bindings.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/state/bindings.rs)** – Manages per-application and global binding tables that store both short-press and long-press entries, handling the dispatch logic based on elapsed time calculations.

## Summary

- **Short-press bindings** in OpenLogi fire immediately upon button activation without checking timing thresholds, making them suitable for primary, high-frequency actions.
- **Long-press bindings** wrap actions in the `LongPressBinding` type and only execute after the button is held longer than the 500ms `LONG_PRESS_THRESHOLD` defined in [`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs).
- The input layer timestamps button-down events and monitors elapsed time; if the button releases before the threshold, the system falls back to short-press behavior.
- This SOOM threshold model allows single buttons to multiplex two distinct actions based purely on press duration, implemented across the core, device, and desktop crates.

## Frequently Asked Questions

### What is the default long-press threshold in OpenLogi?

OpenLogi uses a default **500ms threshold** defined by the `LONG_PRESS_THRESHOLD` constant located at line 43 of [`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs). This value determines how long a button must be held to trigger a long-press binding instead of a short-press action.

### How does OpenLogi handle conflicting short-press and long-press bindings on the same button?

OpenLogi processes these bindings hierarchically. When a button is pressed, the system waits to see if the hold duration exceeds `LONG_PRESS_THRESHOLD`. If the user releases the button before 500ms elapse, the long-press binding is discarded and the short-press binding fires. If the threshold is exceeded, the long-press binding activates and the short-press action is suppressed.

### Where is the long-press timing logic implemented in the source code?

The timing logic spans multiple crates. The threshold constant and `LongPressBinding` wrapper are defined in [`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs) and [`crates/openlogi-core/src/value.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/value.rs). The actual dispatch and fallback logic is implemented in [`crates/openlogi-desktop/src/state/bindings.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/state/bindings.rs), while gesture-specific timing is handled in [`crates/openlogi-device/src/session/gesture.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/session/gesture.rs).

### Can the long-press threshold duration be customized?

Yes, the threshold is configurable through the `LONG_PRESS_THRESHOLD` constant. Developers can modify this value in [`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs) to adjust the sensitivity of long-press detection, though the default 500ms provides a balanced trade-off between responsiveness and accidental trigger prevention for most use cases.