feat(B.4b): InputDispatcher detects double-clicks
Visual test of the B.4b handler revealed the dispatcher never fired SelectDblLeft. OnMouseDown was only looking up Press and Hold activations — DoubleClick bindings in KeyBindings.cs were effectively dead code. Adds 500ms-threshold double-click detection: tracks last-mouse-down button + Environment.TickCount64 timestamp; a same-button press within the threshold additionally fires ActivationType.DoubleClick for the matching binding (Press still fires normally for the second click). Clears the pair-state after firing so a triple-click doesn't produce a second DoubleClick. Tests cover same-button within threshold, beyond threshold (no fire), different-button (no fire), and triple-click (fresh pair required). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
89d82e1b76
commit
242ce706ef
2 changed files with 142 additions and 0 deletions
|
|
@ -38,6 +38,14 @@ public sealed class InputDispatcher
|
|||
private readonly Stack<InputScope> _scopes = new();
|
||||
private readonly HashSet<KeyChord> _heldHoldChords = new();
|
||||
|
||||
// Double-click detection. _lastMouseDownButton == null means no recent press.
|
||||
// _lastMouseDownTickMs is Environment.TickCount64 at the time of that press.
|
||||
// A subsequent mouse-down on the same button within DoubleClickThresholdMs
|
||||
// additionally fires ActivationType.DoubleClick for the matching binding.
|
||||
private MouseButton? _lastMouseDownButton;
|
||||
private long _lastMouseDownTickMs;
|
||||
private const long DoubleClickThresholdMs = 500;
|
||||
|
||||
/// <summary>K.3 modal-rebind hook: when non-null, the next non-modifier
|
||||
/// chord is reported via this callback INSTEAD of firing actions. Esc
|
||||
/// cancels (callback receives <c>default(KeyChord)</c>).</summary>
|
||||
|
|
@ -325,6 +333,24 @@ public sealed class InputDispatcher
|
|||
Fired?.Invoke(hold.Value.Action, ActivationType.Press);
|
||||
_heldHoldChords.Add(chord);
|
||||
}
|
||||
|
||||
// Double-click recognition. Same button within DoubleClickThresholdMs
|
||||
// -> additionally fire ActivationType.DoubleClick for any matching
|
||||
// binding. Press has already fired for the second click (same as a
|
||||
// single click); DoubleClick is the *additional* signal.
|
||||
long nowMs = Environment.TickCount64;
|
||||
if (_lastMouseDownButton == button
|
||||
&& nowMs - _lastMouseDownTickMs <= DoubleClickThresholdMs)
|
||||
{
|
||||
var dbl = _bindings.Find(chord, ActivationType.DoubleClick);
|
||||
if (dbl is not null) Fired?.Invoke(dbl.Value.Action, ActivationType.DoubleClick);
|
||||
_lastMouseDownButton = null; // consumed; require fresh pair for next
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastMouseDownButton = button;
|
||||
_lastMouseDownTickMs = nowMs;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseUp(MouseButton button, ModifierMask mods)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue