1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
package ansi
import (
"fmt"
)
// MouseButton represents the button that was pressed during a mouse message.
type MouseButton byte
// Mouse event buttons
//
// This is based on X11 mouse button codes.
//
// 1 = left button
// 2 = middle button (pressing the scroll wheel)
// 3 = right button
// 4 = turn scroll wheel up
// 5 = turn scroll wheel down
// 6 = push scroll wheel left
// 7 = push scroll wheel right
// 8 = 4th button (aka browser backward button)
// 9 = 5th button (aka browser forward button)
// 10
// 11
//
// Other buttons are not supported.
const (
MouseNone MouseButton = iota
MouseButton1
MouseButton2
MouseButton3
MouseButton4
MouseButton5
MouseButton6
MouseButton7
MouseButton8
MouseButton9
MouseButton10
MouseButton11
MouseLeft = MouseButton1
MouseMiddle = MouseButton2
MouseRight = MouseButton3
MouseWheelUp = MouseButton4
MouseWheelDown = MouseButton5
MouseWheelLeft = MouseButton6
MouseWheelRight = MouseButton7
MouseBackward = MouseButton8
MouseForward = MouseButton9
MouseRelease = MouseNone
)
var mouseButtons = map[MouseButton]string{
MouseNone: "none",
MouseLeft: "left",
MouseMiddle: "middle",
MouseRight: "right",
MouseWheelUp: "wheelup",
MouseWheelDown: "wheeldown",
MouseWheelLeft: "wheelleft",
MouseWheelRight: "wheelright",
MouseBackward: "backward",
MouseForward: "forward",
MouseButton10: "button10",
MouseButton11: "button11",
}
// String returns a string representation of the mouse button.
func (b MouseButton) String() string {
return mouseButtons[b]
}
// EncodeMouseButton returns a byte representing a mouse button.
// The button is a bitmask of the following leftmost values:
//
// - The first two bits are the button number:
// 0 = left button, wheel up, or button no. 8 aka (backwards)
// 1 = middle button, wheel down, or button no. 9 aka (forwards)
// 2 = right button, wheel left, or button no. 10
// 3 = release event, wheel right, or button no. 11
//
// - The third bit indicates whether the shift key was pressed.
//
// - The fourth bit indicates the alt key was pressed.
//
// - The fifth bit indicates the control key was pressed.
//
// - The sixth bit indicates motion events. Combined with button number 3, i.e.
// release event, it represents a drag event.
//
// - The seventh bit indicates a wheel event.
//
// - The eighth bit indicates additional buttons.
//
// If button is [MouseNone], and motion is false, this returns a release event.
// If button is undefined, this function returns 0xff.
func EncodeMouseButton(b MouseButton, motion, shift, alt, ctrl bool) (m byte) {
// mouse bit shifts
const (
bitShift = 0b0000_0100
bitAlt = 0b0000_1000
bitCtrl = 0b0001_0000
bitMotion = 0b0010_0000
bitWheel = 0b0100_0000
bitAdd = 0b1000_0000 // additional buttons 8-11
bitsMask = 0b0000_0011
)
if b == MouseNone {
m = bitsMask
} else if b >= MouseLeft && b <= MouseRight {
m = byte(b - MouseLeft)
} else if b >= MouseWheelUp && b <= MouseWheelRight {
m = byte(b - MouseWheelUp)
m |= bitWheel
} else if b >= MouseBackward && b <= MouseButton11 {
m = byte(b - MouseBackward)
m |= bitAdd
} else {
m = 0xff // invalid button
}
if shift {
m |= bitShift
}
if alt {
m |= bitAlt
}
if ctrl {
m |= bitCtrl
}
if motion {
m |= bitMotion
}
return
}
// x10Offset is the offset for X10 mouse events.
// See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking
const x10Offset = 32
// MouseX10 returns an escape sequence representing a mouse event in X10 mode.
// Note that this requires the terminal support X10 mouse modes.
//
// CSI M Cb Cx Cy
//
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking
func MouseX10(b byte, x, y int) string {
return "\x1b[M" + string(b+x10Offset) + string(byte(x)+x10Offset+1) + string(byte(y)+x10Offset+1)
}
// MouseSgr returns an escape sequence representing a mouse event in SGR mode.
//
// CSI < Cb ; Cx ; Cy M
// CSI < Cb ; Cx ; Cy m (release)
//
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking
func MouseSgr(b byte, x, y int, release bool) string {
s := 'M'
if release {
s = 'm'
}
if x < 0 {
x = -x
}
if y < 0 {
y = -y
}
return fmt.Sprintf("\x1b[<%d;%d;%d%c", b, x+1, y+1, s)
}
|