MingaEditor.State.Mouse (Minga v0.1.0)

Copy Markdown View Source

Mouse interaction state: drag tracking, anchor position, separator resize, multi-click detection, and hover tracking.

Multi-click detection

The TUI always sends click_count: 1 because libvaxis doesn't track multi-clicks. The BEAM detects double/triple-clicks by comparing press timestamps and positions. GUI frontends send the native click count directly, so BEAM detection is skipped when click_count > 1.

Two presses within @double_click_ms milliseconds at the same position (within @click_distance cells) increment the click count. The count resets on motion, timeout, or a click at a different position.

Summary

Functions

Clears hover state and cancels any pending timer.

Returns the double-click timing window in milliseconds (for testing).

Records a mouse press and computes the effective click count.

Returns true if a separator resize drag is active.

Sets the hover position and starts a debounce timer.

Begins a content drag from the given buffer position.

Begins a separator resize drag in the given direction at the given position.

Ends an active drag, clearing the anchor.

Ends a separator resize drag.

Updates the separator position during an active resize drag.

Types

t()

@type t() :: %MingaEditor.State.Mouse{
  anchor: {non_neg_integer(), non_neg_integer()} | nil,
  click_count: non_neg_integer(),
  drag_click_count: pos_integer(),
  dragging: boolean(),
  hover_pos: {integer(), integer()} | nil,
  hover_timer: reference() | nil,
  last_press_pos: {integer(), integer()} | nil,
  last_press_time: integer() | nil,
  resize_dragging:
    {MingaEditor.WindowTree.direction() | :agent_separator, non_neg_integer()}
    | nil
}

Functions

clear_hover(mouse)

@spec clear_hover(t()) :: t()

Clears hover state and cancels any pending timer.

double_click_ms()

@spec double_click_ms() :: pos_integer()

Returns the double-click timing window in milliseconds (for testing).

record_press(mouse, row, col, native_click_count)

@spec record_press(t(), integer(), integer(), pos_integer()) :: t()

Records a mouse press and computes the effective click count.

If native_click_count > 1, uses that directly (GUI frontend). Otherwise, detects multi-clicks by timing and position (TUI fallback).

Returns the updated mouse state with click_count set.

resizing?(mouse)

@spec resizing?(t()) :: boolean()

Returns true if a separator resize drag is active.

set_hover(mouse, row, col, opts \\ [])

@spec set_hover(t(), integer(), integer(), keyword()) :: t()

Sets the hover position and starts a debounce timer.

start_drag(mouse, anchor)

@spec start_drag(
  t(),
  {non_neg_integer(), non_neg_integer()}
) :: t()

Begins a content drag from the given buffer position.

start_resize(mouse, direction, position)

@spec start_resize(
  t(),
  MingaEditor.WindowTree.direction() | :agent_separator,
  non_neg_integer()
) :: t()

Begins a separator resize drag in the given direction at the given position.

stop_drag(mouse)

@spec stop_drag(t()) :: t()

Ends an active drag, clearing the anchor.

stop_resize(mouse)

@spec stop_resize(t()) :: t()

Ends a separator resize drag.

update_resize(mouse, direction, new_position)

@spec update_resize(
  t(),
  MingaEditor.WindowTree.direction() | :agent_separator,
  non_neg_integer()
) ::
  t()

Updates the separator position during an active resize drag.