Skip to content

Add separate longclick retrigger delay#86

Closed
eternicode wants to merge 1 commit intoLennartHennigs:masterfrom
eternicode:longclick-retrigger-delay
Closed

Add separate longclick retrigger delay#86
eternicode wants to merge 1 commit intoLennartHennigs:masterfrom
eternicode:longclick-retrigger-delay

Conversation

@eternicode
Copy link

Objective

I was trying to implement a standard interaction pattern with long press:

  • User presses button
  • Press action is executed immediately
  • User continues pressing through long press delay (eg, 500ms)
  • Long press action is executed
  • Much shorter delay (eg, 100ms) is applied while button remains pressed
  • Long press action is repeated at shorter interval while button is held

Classic example would be long-pressing to quickly navigate a long list of items.

I had attempted this with (simplified and slightly pseudocode):

btn.setPressedHandler(pressAction);
btn.setLongClickDetectedHandler(
    [this](Button2 &btn) {
        btn.setLongClickTime(100);
        pressAction(btn);
    }
);
btn.setLongClickHandler([this](Button2 &btn) {
    btn.setLongClickTime(500);
});
btn.setLongClickDetectedRetriggerable(true);
btn.setLongClickTime(500);

but this approach consistently caused the first 3-5 long click actions to execute with ~30ms delay. The exact timing is probably dependent on other factors, but the threshold was adjusted downward when setLongClickTime(100) was called, so these 3-5 initial repeats were effectively immediately executed while the timer caught up to the adjusted longclick_counter multiplier math.

The MR produces cleaner behavior with cleaner code:

btn.setPressedHandler(pressAction);
btn.setLongClickDetectedHandler(pressAction);
btn.setLongClickTime(500);
btn.setLongClickDetectedRetriggerable(true, 100);

Considerations

I tried to come up with a clean way to avoid the has_longclick_retrigger_ms variable. Cleanest way would be to have an invalid value for longclick_retrigger_ms, ie -1, but uint to accommodate milliseconds precludes that option. Could default it to longclick_time_ms's value at init and sync the two when they have the same value, but that felt like too much magic. Explicit flagging felt best.


void Button2::setLongClickDetectedRetriggerable(bool retriggerable) {
longclick_retriggerable = retriggerable;
has_longclick_retrigger_ms = false;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, i like your idea, not sure if the "has_longclick_retrigger_ms" is really needed you could just check if "longclick_retrigger_ms" has a value.

LennartHennigs added a commit that referenced this pull request Mar 17, 2026
Decouples the initial long-press threshold from the continuous retrigger
interval, taking the API style of PR #86 with the cleaner implementation
approach of PR #90.

- New overload: setLongClickDetectedRetriggerable(bool, unsigned int retrigger_ms)
- New getter: getLongClickInterval()
- bool-only overload delegates to the two-arg overload (resets interval to 0)
- _checkForLongClick: first fire at longclick_time_ms, subsequent fires
  every retrigger_ms (falls back to longclick_time_ms if not set, preserving
  backward compatibility)
- reset() now clears longclick_retriggerable and longclick_interval_ms
- New example: LongpressRetriggerInterval
- New tests: getLongClickInterval getter, retrigger timing with custom interval
- test_helpers: pressAndHold() helper extracted; click() delegates to it

Closes #86, Closes #90

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@LennartHennigs
Copy link
Owner

Thanks for this PR! The bundled API approach here (setLongClickDetectedRetriggerable(bool, unsigned int)) inspired the solution that was ultimately implemented.

I've opened #91 as a hybrid — it takes your API style from this PR and combines it with the cleaner sentinel-based implementation from #90 (no extra bool flag, unsigned long types throughout). Would love your review if you have a moment!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants