11package termeverything
22
3+ import (
4+ "strconv"
5+ "strings"
6+ )
7+
38type PointerEvent interface {
49 isPointerEvent ()
510 isXkbdCode ()
@@ -24,8 +29,9 @@ func (p *PointerMove) GetModifiers() int {
2429}
2530
2631type PointerButtonPress struct {
27- Modifiers int
28- Button LINUX_BUTTON_CODES
32+ Modifiers int
33+ NeedToReleaseOtherButtons bool
34+ Button LINUX_BUTTON_CODES
2935}
3036
3137func (* PointerButtonPress ) isPointerEvent () {}
@@ -44,7 +50,9 @@ func (p *PointerButtonPress) GetModifiers() int {
4450 * button is being released
4551 */
4652type PointerButtonRelease struct {
47- Modifiers int
53+ Button LINUX_BUTTON_CODES
54+ NeedsButtonGuessing bool
55+ Modifiers int
4856}
4957
5058func (* PointerButtonRelease ) isPointerEvent () {}
@@ -84,6 +92,164 @@ func MouseModifiers(code, base int) int {
8492 return modifiers
8593}
8694
95+ func ParseMouseCode (code string ) XkbdCode {
96+ parts := strings .Split (code , ";" )
97+ if len (parts ) != 3 {
98+ return nil
99+ }
100+ buttonPart := parts [0 ]
101+ colPart := parts [1 ]
102+ rowAndTermPart := parts [2 ]
103+ pressRelease := rowAndTermPart [len (rowAndTermPart )- 1 ]
104+ rowPart := rowAndTermPart [:len (rowAndTermPart )- 1 ]
105+
106+ button , err := strconv .Atoi (buttonPart )
107+ if err != nil {
108+ return nil
109+ }
110+ col , err := strconv .Atoi (colPart )
111+ if err != nil {
112+ return nil
113+ }
114+ col = col - 1
115+ row , err := strconv .Atoi (rowPart )
116+ if err != nil {
117+ return nil
118+ }
119+ row = row - 1
120+ press := false
121+ switch pressRelease {
122+ case 'M' :
123+ press = true
124+ case 'm' :
125+ press = false
126+ default :
127+ return nil
128+ }
129+
130+ d := button + 32
131+ /**
132+ * Mouse time!
133+ */
134+ switch d {
135+
136+ case 67 , 75 , 83 , 91 :
137+ modifiers := MouseModifiers (d , 67 )
138+ return & PointerMove {
139+ Row : row ,
140+ Col : col ,
141+ Modifiers : modifiers ,
142+ }
143+ case 64 , 72 , 80 , 88 :
144+ /**
145+ * This is pointer moving while
146+ * holding left mouse button down
147+ *
148+ * so far it has always followed
149+ * a button down event,
150+ * so I'm just sending a pointer move
151+ * rather than a button followed by a move
152+ */
153+ modifiers := MouseModifiers (d , 64 )
154+ return & PointerMove {
155+ Row : row ,
156+ Col : col ,
157+ Modifiers : modifiers ,
158+ }
159+ case 65 , 73 , 81 , 89 :
160+ /**
161+ * Move while holding middle mouse button down
162+ */
163+ modifiers := MouseModifiers (d , 65 )
164+ return & PointerMove {
165+ Row : row ,
166+ Col : col ,
167+ Modifiers : modifiers ,
168+ }
169+ case 66 , 74 , 82 , 90 :
170+ /**
171+ * Move while holding right mouse button down
172+ */
173+ modifiers := MouseModifiers (d , 66 )
174+ return & PointerMove {
175+ Row : row ,
176+ Col : col ,
177+ Modifiers : modifiers ,
178+ }
179+
180+ // Mouse button left down
181+ case 32 , 40 , 48 , 56 :
182+ if press {
183+ return & PointerButtonPress {
184+ Button : BTN_LEFT ,
185+ NeedToReleaseOtherButtons : false ,
186+ Modifiers : MouseModifiers (d , 32 ),
187+ }
188+ }
189+ return & PointerButtonRelease {
190+ Button : BTN_LEFT ,
191+ Modifiers : MouseModifiers (d , 32 ),
192+ }
193+ // Mouse button middle down
194+ case 33 , 41 , 49 , 57 :
195+ if press {
196+ return & PointerButtonPress {
197+ Button : BTN_MIDDLE ,
198+ NeedToReleaseOtherButtons : false ,
199+ Modifiers : MouseModifiers (d , 33 ),
200+ }
201+ }
202+ return & PointerButtonRelease {
203+ Button : BTN_MIDDLE ,
204+ Modifiers : MouseModifiers (d , 33 ),
205+ }
206+ // Mouse button right down
207+ case 34 , 42 , 50 , 58 :
208+ if press {
209+ return & PointerButtonPress {
210+ Button : BTN_RIGHT ,
211+ NeedToReleaseOtherButtons : false ,
212+ Modifiers : MouseModifiers (d , 34 ),
213+ }
214+ }
215+ return & PointerButtonRelease {
216+ Button : BTN_RIGHT ,
217+ Modifiers : MouseModifiers (d , 34 ),
218+ }
219+ // Mouse wheel up
220+ case 96 , 104 , 112 , 120 :
221+ return & PointerWheel {
222+ Up : true ,
223+ Modifiers : MouseModifiers (d , 96 ),
224+ }
225+ // Mouse wheel down
226+ case 97 , 105 , 113 , 121 :
227+ return & PointerWheel {
228+ Up : false ,
229+ Modifiers : MouseModifiers (d , 97 ),
230+ }
231+ }
232+ return nil
233+ }
234+
235+ func ParseSGRMouseSequences (data []byte ) []XkbdCode {
236+ codes := strings .Split (string (data ), "\x1b [<" )
237+ if len (codes ) < 2 {
238+ return nil
239+ }
240+ codes = codes [1 :] // First split is empty string before first ESC[<
241+ out := make ([]XkbdCode , 0 )
242+ for _ , code := range codes {
243+
244+ buttonCode := ParseMouseCode (code )
245+ if buttonCode == nil {
246+ continue
247+ }
248+ out = append (out , buttonCode )
249+ }
250+ return out
251+ }
252+
87253func PointerCode (data []byte ) PointerEvent {
88254 if ! (len (data ) >= 3 && data [0 ] == 27 && data [1 ] == 91 && data [2 ] == 77 ) {
89255 return nil
@@ -135,25 +301,29 @@ func PointerCode(data []byte) PointerEvent {
135301 // Mouse button left down
136302 case 32 , 40 , 48 , 56 :
137303 return & PointerButtonPress {
138- Button : BTN_LEFT ,
139- Modifiers : MouseModifiers (d , 32 ),
304+ Button : BTN_LEFT ,
305+ NeedToReleaseOtherButtons : true ,
306+ Modifiers : MouseModifiers (d , 32 ),
140307 }
141308 // Mouse button middle down
142309 case 33 , 41 , 49 , 57 :
143310 return & PointerButtonPress {
144- Button : BTN_MIDDLE ,
145- Modifiers : MouseModifiers (d , 33 ),
311+ Button : BTN_MIDDLE ,
312+ NeedToReleaseOtherButtons : true ,
313+ Modifiers : MouseModifiers (d , 33 ),
146314 }
147315 // Mouse button right down
148316 case 34 , 42 , 50 , 58 :
149317 return & PointerButtonPress {
150- Button : BTN_RIGHT ,
151- Modifiers : MouseModifiers (d , 34 ),
318+ Button : BTN_RIGHT ,
319+ NeedToReleaseOtherButtons : true ,
320+ Modifiers : MouseModifiers (d , 34 ),
152321 }
153322 // Mouse button up (cannot be sure which button)
154323 case 35 , 43 , 51 , 59 :
155324 return & PointerButtonRelease {
156- Modifiers : MouseModifiers (d , 35 ),
325+ NeedsButtonGuessing : true ,
326+ Modifiers : MouseModifiers (d , 35 ),
157327 }
158328 // Mouse wheel up
159329 case 96 , 104 , 112 , 120 :
0 commit comments