v0.6.0 mouse: every wheel direction and side button named; tui: a scrollbar the pointer drives
* mouse: the wheel's four directions and the side buttons parseSGRMouse read a report's low two bits alone, so a wheel tilted left or right (66, 67) reported as WheelDown, and a mouse's back and forward buttons (128, 129) as a left or middle press. It now decodes by bank: bits 0-1 number a button within the main three and none, the wheel's four directions (bit 6), or buttons 8 to 11 (bit 7). WheelLeft and WheelRight join MouseButton after Forward, so every existing value keeps its number; Back and Forward are reported for buttons 8 and 9; buttons 10 and 11, and a report with both bank bits set, are dropped as KeyNone. A wheel step is a press with no release in every direction. * tui: ScrollThumb and ScrollDrag ScrollThumb is the thumb ScrollBarStyled draws, its first row and height, exported so an application hit-tests the bar it drew. ScrollDrag drives a bar by the pointer, rows counted from the track's top: a press on the thumb takes hold where it lands, a press on the track moves the thumb's middle there and takes hold, and each drag keeps the held row under the pointer, clamped at the track's ends, at the nearest offset when there are fewer offsets than rows. Each call returns the offset to show. A table of SGR reports covers each bank and drops the buttons past 9; a property test over every track of 3 to 10 rows and content up to 30 checks each press and drag against the thumb ScrollThumb draws.
This commit is contained in:
1 parent
d4cc9f2407
commit
bc22a9bf00
7 files changed
+215
-60
No files matched your search
@@ -623,7 +623,8 @@ func (r *inputReader) parseControl(b byte) Event {
|
||||
}
|
||||
|
||||
// parseSGRMouse parses mouse SGR sequences, ESC [ < Btn ; X ; Y M/m, from
|
||||
// the parameters and final byte; a malformed one is dropped as KeyNone
|
||||
// the parameters and final byte; a malformed one, or a button past 9, is
|
||||
// dropped as KeyNone
|
||||
func parseSGRMouse(params []byte, final byte) Event {
|
||||
btn, x, y, ok := parseSGRParams(params)
|
||||
if !ok {
|
||||
@@ -632,48 +633,34 @@ func parseSGRMouse(params []byte, final byte) Event {
|
||||
|
||||
ev := Event{Type: EventMouse, MouseX: x - 1, MouseY: y - 1} // Convert to 0-indexed
|
||||
|
||||
// Decode button and action
|
||||
// Bits 0-1: button (0=left, 1=middle, 2=right, 3=release)
|
||||
// Bit 5 (32): motion
|
||||
// Bit 6 (64): scroll
|
||||
buttonID := btn & 0x03
|
||||
isMotion := btn&32 != 0
|
||||
isScroll := btn&64 != 0
|
||||
// Bits 0-1 number a button within its bank: the main three and none, the
|
||||
// wheel's four directions (bit 6), or buttons 8 to 11 (bit 7); bit 5 is motion
|
||||
id := btn & 0x03
|
||||
switch btn & (64 | 128) {
|
||||
case 0:
|
||||
ev.MouseBtn = [...]MouseButton{MouseBtnLeft, MouseBtnMiddle, MouseBtnRight, MouseBtnNone}[id]
|
||||
case 64:
|
||||
ev.MouseBtn = [...]MouseButton{MouseBtnWheelUp, MouseBtnWheelDown, MouseBtnWheelLeft, MouseBtnWheelRight}[id]
|
||||
case 128:
|
||||
if id > 1 {
|
||||
return Event{Type: EventKey, Key: KeyNone}
|
||||
}
|
||||
ev.MouseBtn = MouseBtnBack + MouseButton(id)
|
||||
default:
|
||||
return Event{Type: EventKey, Key: KeyNone}
|
||||
}
|
||||
|
||||
if isScroll {
|
||||
// Scroll: buttonID 0=up, 1=down
|
||||
if buttonID == 0 {
|
||||
ev.MouseBtn = MouseBtnWheelUp
|
||||
} else {
|
||||
ev.MouseBtn = MouseBtnWheelDown
|
||||
}
|
||||
ev.MouseAction = MouseActionPress // Scroll is instantaneous
|
||||
} else {
|
||||
// Regular button
|
||||
switch buttonID {
|
||||
case 0:
|
||||
ev.MouseBtn = MouseBtnLeft
|
||||
case 1:
|
||||
ev.MouseBtn = MouseBtnMiddle
|
||||
case 2:
|
||||
ev.MouseBtn = MouseBtnRight
|
||||
case 3:
|
||||
ev.MouseBtn = MouseBtnNone // Release with no specific button
|
||||
}
|
||||
|
||||
if final == 'M' {
|
||||
if isMotion {
|
||||
if ev.MouseBtn != MouseBtnNone {
|
||||
ev.MouseAction = MouseActionDrag
|
||||
} else {
|
||||
ev.MouseAction = MouseActionMove
|
||||
}
|
||||
} else {
|
||||
ev.MouseAction = MouseActionPress
|
||||
}
|
||||
} else {
|
||||
ev.MouseAction = MouseActionRelease
|
||||
}
|
||||
switch {
|
||||
case btn&64 != 0:
|
||||
ev.MouseAction = MouseActionPress // A wheel step is its press
|
||||
case final == 'm':
|
||||
ev.MouseAction = MouseActionRelease
|
||||
case btn&32 == 0:
|
||||
ev.MouseAction = MouseActionPress
|
||||
case ev.MouseBtn != MouseBtnNone:
|
||||
ev.MouseAction = MouseActionDrag
|
||||
default:
|
||||
ev.MouseAction = MouseActionMove
|
||||
}
|
||||
|
||||
// Extract modifiers from button byte
|
||||
|
||||
Reference in new issue
Block a user