Documentation
¶
Overview ¶
Package mouse carries the mouse event tuilib components actually handle, and the click-counting that turns raw presses into single and double clicks.
Components never see bubbletea's tea.MouseMsg. The app shell translates it into a mouse.Msg first, adding the one thing a component can't work out on its own: whether this press is the second of a double click. Detection needs a timestamp, a previous position, and a configurable threshold, and keeping all three in the shell means no component holds mouse state and no component needs a threshold plumbed into its Options.
A component handles mouse input by matching mouse.Msg and testing the rect it was last given:
case mouse.Msg:
if !m.rect.Hit(msg.X, msg.Y) {
return m, nil // not ours — let a sibling claim it
}
if msg.IsDoubleClick() {
return m, m.activate()
}
if msg.IsPress() {
return m, focus.Request(m)
}
Rect.Hit already rejects events aimed at a component that wasn't drawn in the current frame, so a hidden pane declines everything without needing to know it's hidden.
Index ¶
Constants ¶
const DefaultDoubleClickInterval = 500 * time.Millisecond
DefaultDoubleClickInterval is the window in which a second press in the same cell counts as a double click. 500ms is the common desktop default and forgiving enough for terminals over a slow link.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Msg ¶
type Msg struct {
tea.MouseMsg
// Clicks is 1 for a single press, 2 for the second press of a double
// click, and 0 for anything that isn't a button press (wheel, motion,
// release). It does not climb past 2 — a triple click reads as a fresh
// single click, since nothing in tuilib binds one.
Clicks int
}
Msg is a mouse event with its click count resolved. It embeds bubbletea's event, so X, Y, Action, Button and the modifier flags read through directly.
func (Msg) IsDoubleClick ¶
IsDoubleClick reports whether this press completes a double click. Rule 14 maps it to the same verb as enter — open whatever is under the cursor.
func (Msg) IsPointPress ¶ added in v0.21.0
IsPointPress reports whether this press is pointing at something — either button.
Components use it where the verb is "focus this and put the cursor here", which both buttons mean: a right-click opens a menu about the row under the pointer, so that row has to become the selection first. Only IsPress may *activate* something, which is what keeps a right-click from committing a modal button or flipping a toggle.
func (Msg) IsPress ¶
IsPress reports whether this is a left-button press. This is the event components act on: acting on press rather than release keeps clicks feeling immediate, and matches how lazygit and htop behave.
func (Msg) IsRightPress ¶ added in v0.21.0
IsRightPress reports whether this is a right-button press — the gesture that asks "what can I do to this?" and opens the action menu.
It carries no click count. Nothing in tuilib binds a right double click, and the Tracker only counts left presses, so a second right press is simply another right press.
Worth knowing before you rely on it: whether this ever arrives is the terminal's decision. Most emulators forward right presses once mouse reporting is on, but some (macOS Terminal.app) always show their own context menu instead. Right-click is therefore an accelerator on top of a keyboard path, never the only way to reach something.
func (Msg) IsWheelDown ¶
type Tracker ¶
type Tracker struct {
// contains filtered or unexported fields
}
Tracker converts tea.MouseMsg into Msg, counting rapid repeat presses in the same cell as double clicks. The app shell owns one; callers running without the shell can use one directly.
The zero Tracker uses DefaultDoubleClickInterval.
func NewTracker ¶
NewTracker returns a Tracker using the given double-click window. A non-positive interval falls back to DefaultDoubleClickInterval.
func (*Tracker) SetInterval ¶
SetInterval updates the double-click window.
func (*Tracker) Track ¶
Track resolves e into a Msg. now is passed in rather than read from the clock so the behaviour is testable.
A press counts as a double click when it lands in the same cell as the previous press and within the interval. Requiring the same cell — rather than merely a nearby one — means a fast click on one list row followed by a fast click on another reads as two separate selections, which is what the user meant.