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 | "use strict" ;
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | var net = require( 'net' ) ;
|
38 | var NextGenEvents = require( 'nextgen-events' ) ;
|
39 | var termkit = require( './termkit.js' ) ;
|
40 |
|
41 | var gpm = {} ;
|
42 | module.exports = gpm ;
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 | var gpmMagic = Buffer.allocUnsafe( 4 ) ;
|
55 | gpmMagic.writeUInt32LE( 0x47706D4C , 0 ) ;
|
56 |
|
57 |
|
58 |
|
59 |
|
60 | gpm.connectStructureBuffer = function connectStructureBuffer( gpmConnect ) {
|
61 | var buffer = Buffer.allocUnsafe( 16 ) ;
|
62 |
|
63 | if ( gpmConnect.eventMask === undefined ) { gpmConnect.eventMask = 65535 ; }
|
64 | if ( gpmConnect.defaultMask === undefined ) { gpmConnect.defaultMask = 0 ; }
|
65 | if ( gpmConnect.minMod === undefined ) { gpmConnect.minMod = 0 ; }
|
66 | if ( gpmConnect.maxMod === undefined ) { gpmConnect.maxMod = 65535 ; }
|
67 |
|
68 |
|
69 | buffer.writeUInt16LE( gpmConnect.eventMask , 0 ) ;
|
70 | buffer.writeUInt16LE( gpmConnect.defaultMask , 2 ) ;
|
71 | buffer.writeUInt16LE( gpmConnect.minMod , 4 ) ;
|
72 | buffer.writeUInt16LE( gpmConnect.maxMod , 6 ) ;
|
73 | buffer.writeUInt32LE( gpmConnect.pid , 8 ) ;
|
74 | buffer.writeUInt32LE( gpmConnect.vc , 12 ) ;
|
75 |
|
76 |
|
77 |
|
78 | return buffer ;
|
79 | } ;
|
80 |
|
81 |
|
82 |
|
83 |
|
84 | gpm.eventStructure = function eventStructure( buffer ) {
|
85 | var event = {} ;
|
86 |
|
87 |
|
88 | event.buttons = buffer.readUInt8( 0 ) ;
|
89 | event.modifiers = buffer.readUInt8( 1 ) ;
|
90 |
|
91 | event.vc = buffer.readUInt16LE( 2 ) ;
|
92 |
|
93 | event.dx = buffer.readInt16LE( 4 ) ;
|
94 | event.dy = buffer.readInt16LE( 6 ) ;
|
95 | event.x = buffer.readInt16LE( 8 ) ;
|
96 | event.y = buffer.readInt16LE( 10 ) ;
|
97 |
|
98 | event.eType = buffer.readUInt32LE( 12 ) ;
|
99 |
|
100 | event.clicks = buffer.readUInt32LE( 16 ) ;
|
101 |
|
102 | event.margin = buffer.readUInt32LE( 20 ) ;
|
103 |
|
104 | event.wdx = buffer.readInt16LE( 24 ) ;
|
105 | event.wdy = buffer.readInt16LE( 26 ) ;
|
106 |
|
107 |
|
108 |
|
109 | return event ;
|
110 | } ;
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 | gpm.MOVE = 1 ;
|
117 | gpm.DRAG = 2 ;
|
118 | gpm.DOWN = 4 ;
|
119 | gpm.UP = 8 ;
|
120 |
|
121 | gpm.SINGLE = 16 ;
|
122 | gpm.DOUBLE = 32 ;
|
123 | gpm.TRIPLE = 64 ;
|
124 |
|
125 | gpm.MFLAG = 128 ;
|
126 | gpm.HARD = 256 ;
|
127 |
|
128 | gpm.ENTER = 512 ;
|
129 | gpm.LEAVE = 1024 ;
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 | gpm.TOP = 1 ;
|
136 | gpm.BOT = 2 ;
|
137 | gpm.LFT = 4 ;
|
138 | gpm.RGT = 8 ;
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 | gpm.Handler = function Handler() { throw new Error( '[terminal] Cannot create a gpm.Handler object directly, use gpm.createHandler() instead' ) ; } ;
|
149 | gpm.Handler.prototype = Object.create( NextGenEvents.prototype ) ;
|
150 | gpm.Handler.prototype.constructor = gpm.Handler ;
|
151 |
|
152 |
|
153 |
|
154 |
|
155 | gpm.createHandler = function createHandler( options ) {
|
156 | if ( ! options || typeof options !== 'object' ) { options = {} ; }
|
157 |
|
158 | if ( options.raw === undefined ) { options.raw = true ; }
|
159 | if ( options.stdin === undefined ) { options.stdin = 0 ; }
|
160 | if ( options.mode === undefined ) { options.mode = 'motion' ; }
|
161 |
|
162 | var connectMode = { pid: process.pid } ;
|
163 |
|
164 | connectMode.defaultMask =
|
165 | gpm.MOVE | gpm.DRAG | gpm.DOWN | gpm.UP | gpm.SINGLE | gpm.DOUBLE | gpm.TRIPLE | gpm.MFLAG | gpm.HARD ;
|
166 |
|
167 | switch ( options.mode ) {
|
168 | case 'button' :
|
169 | connectMode.eventMask = gpm.DOWN | gpm.UP ;
|
170 | break ;
|
171 | case 'drag' :
|
172 | connectMode.eventMask = gpm.DRAG | gpm.DOWN | gpm.UP ;
|
173 | break ;
|
174 | case 'motion' :
|
175 | default :
|
176 | connectMode.eventMask = gpm.MOVE | gpm.DRAG | gpm.DOWN | gpm.UP ;
|
177 | break ;
|
178 | }
|
179 |
|
180 | var handler = Object.create( gpm.Handler.prototype ) ;
|
181 |
|
182 |
|
183 | var tty = termkit.tty.getPath( options.stdin ) ;
|
184 |
|
185 |
|
186 |
|
187 |
|
188 | connectMode.vc = tty.index || 0 ;
|
189 |
|
190 | handler.socket = new net.Socket() ;
|
191 | var gpmConnect = gpm.connectStructureBuffer( connectMode ) ;
|
192 |
|
193 | handler.socket.connect( '/dev/gpmctl' , () => {
|
194 |
|
195 | handler.socket.write( gpmConnect ) ;
|
196 | } ) ;
|
197 |
|
198 |
|
199 | handler.socket.on( 'error' , ( error ) => { handler.emit( 'error' , error ) ; handler.close() ; } ) ;
|
200 | handler.socket.on( 'end' , () => { handler.emit( 'end' ) ; } ) ;
|
201 | handler.socket.on( 'close' , () => { handler.emit( 'close' ) ; handler.close() ; } ) ;
|
202 |
|
203 | handler.socket.on( 'data' , ( buffer ) => {
|
204 |
|
205 |
|
206 | var rawEvent = gpm.eventStructure( buffer ) ;
|
207 |
|
208 | if ( options.raw ) { handler.emit( 'mouse' , rawEvent ) ; return ; }
|
209 |
|
210 | var terminalKitEvent = gpm.raw2terminalKitEvent( rawEvent ) ;
|
211 | handler.emit( 'mouse' , terminalKitEvent[ 0 ] , terminalKitEvent[ 1 ] ) ;
|
212 | } ) ;
|
213 |
|
214 | return handler ;
|
215 | } ;
|
216 |
|
217 |
|
218 |
|
219 |
|
220 | gpm.Handler.prototype.close = function handlerClose() {
|
221 | if ( this.socket ) {
|
222 | this.socket.destroy() ;
|
223 | this.socket = undefined ;
|
224 | }
|
225 | } ;
|
226 |
|
227 |
|
228 |
|
229 |
|
230 | gpm.raw2terminalKitEvent = function raw2terminalKitEvent( event ) {
|
231 | var name ;
|
232 |
|
233 | var terminalKitEvent = {
|
234 | shift: !! ( event.modifiers & 1 ) ,
|
235 |
|
236 | ctrl: !! ( event.modifiers & 4 ) ,
|
237 | alt: !! ( event.modifiers & 8 ) ,
|
238 | x: event.x ,
|
239 | y: event.y
|
240 | } ;
|
241 |
|
242 | if ( event.eType & gpm.DOWN ) {
|
243 | name = 'MOUSE_LEFT_BUTTON_PRESSED' ;
|
244 | }
|
245 | else if ( event.eType & gpm.UP ) {
|
246 | name = 'MOUSE_LEFT_BUTTON_RELEASED' ;
|
247 | }
|
248 | else if ( event.eType & gpm.MOVE || event.eType & gpm.DRAG ) {
|
249 | name = 'MOUSE_MOTION' ;
|
250 | }
|
251 | else {
|
252 | name = 'MOUSE_UNKNOWN' ;
|
253 | }
|
254 |
|
255 | return [ name , terminalKitEvent ] ;
|
256 | } ;
|
257 |
|
258 |
|