NAME
====

Selkie::App::Internal::Dispatch - internal input dispatch role for Selkie::App

DESCRIPTION
===========

Implementation detail composed by `Selkie::App`. Use `Selkie::App.on-key`, `Selkie::App.event-supply`, and widget `handle-event` methods from application code.

### method suppress-duplicate-press

```raku
method suppress-duplicate-press(
    $target,
    Int:D $btn where { ... },
    Int:D $y,
    Int:D $x
) returns Bool
```

True when this press should be dropped as a duplicate of the last accepted press: same button, same cell, inside the window. Widgets that expose `debounce-ms` choose their own window (0 disables); everything else gets the DUPLICATE-PRESS-MS floor, so a driver double-fire can't reach ANY widget twice — including click-count consumers, where the duplicate would otherwise register as a phantom double-click. The window is keyed on the cell rather than the widget: a duplicate that lands after the first press already changed the layout (committed a dropdown, opened a modal) is still the same physical click and still gets dropped.

### method is-wheel-id

```raku
method is-wheel-id(
    Int $id where { ... }
) returns Bool
```

Wheel events ride the button encoding (4 = up, 5 = down) but are not clicks — see the wheel note in `!dispatch-mouse`.

