1 #include <u.h>
2 #include <sys/select.h>
3 #include <libc.h>
4 #include <draw.h>
5 #include <cursor.h>
6 #include <event.h>
7 #include <mux.h>
8 #include <drawfcall.h>
9 
10 typedef struct	Slave Slave;
11 typedef struct	Ebuf Ebuf;
12 extern Mouse _drawmouse;
13 
14 struct Slave
15 {
16 	int	inuse;
17 	Ebuf	*head;		/* queue of messages for this descriptor */
18 	Ebuf	*tail;
19 	int	(*fn)(int, Event*, uchar*, int);
20 	Muxrpc *rpc;
21 	vlong nexttick;
22 	int fd;
23 	int n;
24 };
25 
26 struct Ebuf
27 {
28 	Ebuf	*next;
29 	int	n;		/* number of bytes in buf */
30 	union {
31 		uchar	buf[EMAXMSG];
32 		Rune	rune;
33 		Mouse	mouse;
34 	} u;
35 };
36 
37 static	Slave	eslave[MAXSLAVE];
38 static	int	Skeyboard = -1;
39 static	int	Smouse = -1;
40 static	int	Stimer = -1;
41 
42 static	int	nslave;
43 static	int	newkey(ulong);
44 static	int	extract(int canblock);
45 
46 static
47 Ebuf*
ebread(Slave * s)48 ebread(Slave *s)
49 {
50 	Ebuf *eb;
51 
52 	while(!s->head)
53 		extract(1);
54 	eb = s->head;
55 	s->head = s->head->next;
56 	if(s->head == 0)
57 		s->tail = 0;
58 	return eb;
59 }
60 
61 ulong
event(Event * e)62 event(Event *e)
63 {
64 	return eread(~0UL, e);
65 }
66 
67 ulong
eread(ulong keys,Event * e)68 eread(ulong keys, Event *e)
69 {
70 	Ebuf *eb;
71 	int i, id;
72 
73 	if(keys == 0)
74 		return 0;
75 	for(;;){
76 		for(i=0; i<nslave; i++)
77 			if((keys & (1<<i)) && eslave[i].head){
78 				id = 1<<i;
79 				if(i == Smouse)
80 					e->mouse = emouse();
81 				else if(i == Skeyboard)
82 					e->kbdc = ekbd();
83 				else if(i == Stimer)
84 					eslave[i].head = 0;
85 				else{
86 					eb = ebread(&eslave[i]);
87 					e->n = eb->n;
88 					if(eslave[i].fn)
89 						id = (*eslave[i].fn)(id, e, eb->u.buf, eb->n);
90 					else
91 						memmove(e->data, eb->u.buf, eb->n);
92 					free(eb);
93 				}
94 				return id;
95 			}
96 		extract(1);
97 	}
98 	return 0;
99 }
100 
101 int
ecanmouse(void)102 ecanmouse(void)
103 {
104 	if(Smouse < 0)
105 		drawerror(display, "events: mouse not initialized");
106 	return ecanread(Emouse);
107 }
108 
109 int
ecankbd(void)110 ecankbd(void)
111 {
112 	if(Skeyboard < 0)
113 		drawerror(display, "events: keyboard not initialzed");
114 	return ecanread(Ekeyboard);
115 }
116 
117 int
ecanread(ulong keys)118 ecanread(ulong keys)
119 {
120 	int i;
121 
122 	for(;;){
123 		for(i=0; i<nslave; i++)
124 			if((keys & (1<<i)) && eslave[i].head)
125 				return 1;
126 		if(!extract(0))
127 			return 0;
128 	}
129 	return -1;
130 }
131 
132 ulong
estartfn(ulong key,int fd,int n,int (* fn)(int,Event *,uchar *,int))133 estartfn(ulong key, int fd, int n, int (*fn)(int, Event*, uchar*, int))
134 {
135 	int i;
136 
137 	if(fd < 0)
138 		drawerror(display, "events: bad file descriptor");
139 	if(n <= 0 || n > EMAXMSG)
140 		n = EMAXMSG;
141 	i = newkey(key);
142 	eslave[i].fn = fn;
143 	eslave[i].fd = fd;
144 	eslave[i].n = n;
145 	return 1<<i;
146 }
147 
148 ulong
estart(ulong key,int fd,int n)149 estart(ulong key, int fd, int n)
150 {
151 	return estartfn(key, fd, n, nil);
152 }
153 
154 ulong
etimer(ulong key,int n)155 etimer(ulong key, int n)
156 {
157 	if(Stimer != -1)
158 		drawerror(display, "events: timer started twice");
159 	Stimer = newkey(key);
160 	if(n <= 0)
161 		n = 1000;
162 	eslave[Stimer].n = n;
163 	eslave[Stimer].nexttick = nsec()+n*1000000LL;
164 	return 1<<Stimer;
165 }
166 
167 void
einit(ulong keys)168 einit(ulong keys)
169 {
170 	if(keys&Ekeyboard){
171 		for(Skeyboard=0; Ekeyboard & ~(1<<Skeyboard); Skeyboard++)
172 			;
173 		eslave[Skeyboard].inuse = 1;
174 		if(nslave <= Skeyboard)
175 			nslave = Skeyboard+1;
176 	}
177 	if(keys&Emouse){
178 		for(Smouse=0; Emouse & ~(1<<Smouse); Smouse++)
179 			;
180 		eslave[Smouse].inuse = 1;
181 		if(nslave <= Smouse)
182 			nslave = Smouse+1;
183 	}
184 }
185 
186 static Ebuf*
newebuf(Slave * s,int n)187 newebuf(Slave *s, int n)
188 {
189 	Ebuf *eb;
190 
191 	eb = malloc(sizeof(*eb) - sizeof(eb->u.buf) + n);
192 	if(eb == nil)
193 		drawerror(display, "events: out of memory");
194 	eb->n = n;
195 	eb->next = 0;
196 	if(s->head)
197 		s->tail = s->tail->next = eb;
198 	else
199 		s->head = s->tail = eb;
200 	return eb;
201 }
202 
203 static Muxrpc*
startrpc(int type)204 startrpc(int type)
205 {
206 	uchar buf[100];
207 	Wsysmsg w;
208 
209 	w.type = type;
210 	convW2M(&w, buf, sizeof buf);
211 	return muxrpcstart(display->mux, buf);
212 }
213 
214 static int
finishrpc(Muxrpc * r,Wsysmsg * w)215 finishrpc(Muxrpc *r, Wsysmsg *w)
216 {
217 	uchar *p;
218 	void *v;
219 	int n;
220 
221 	if(!muxrpccanfinish(r, &v))
222 		return 0;
223 	p = v;
224 	if(p == nil)	/* eof on connection */
225 		exit(0);
226 	GET(p, n);
227 	convM2W(p, n, w);
228 	free(p);
229 	return 1;
230 }
231 
232 static int
extract(int canblock)233 extract(int canblock)
234 {
235 	Ebuf *eb;
236 	int i, n, max;
237 	fd_set rset, wset, xset;
238 	struct timeval tv, *timeout;
239 	Wsysmsg w;
240 	vlong t0;
241 
242 	/*
243 	 * Flush draw buffer before waiting for responses.
244 	 * Avoid doing so if buffer is empty.
245 	 * Also make sure that we don't interfere with app-specific locking.
246 	 */
247 	if(display->locking){
248 		/*
249 		 * if locking is being done by program,
250 		 * this means it can't depend on automatic
251 		 * flush in emouse() etc.
252 		 */
253 		if(canqlock(&display->qlock)){
254 			if(display->bufp > display->buf)
255 				flushimage(display, 1);
256 			unlockdisplay(display);
257 		}
258 	}else
259 		if(display->bufp > display->buf)
260 			flushimage(display, 1);
261 
262 	/*
263 	 * Set up for select.
264 	 */
265 	FD_ZERO(&rset);
266 	FD_ZERO(&wset);
267 	FD_ZERO(&xset);
268 	max = -1;
269 	timeout = nil;
270 	for(i=0; i<nslave; i++){
271 		if(!eslave[i].inuse)
272 			continue;
273 		if(i == Smouse){
274 			if(eslave[i].rpc == nil)
275 				eslave[i].rpc = startrpc(Trdmouse);
276 			if(eslave[i].rpc){
277 				/* if ready, don't block in select */
278 				if(eslave[i].rpc->p)
279 					canblock = 0;
280 				FD_SET(display->srvfd, &rset);
281 				FD_SET(display->srvfd, &xset);
282 				if(display->srvfd > max)
283 					max = display->srvfd;
284 			}
285 		}else if(i == Skeyboard){
286 			if(eslave[i].rpc == nil)
287 				eslave[i].rpc = startrpc(Trdkbd4);
288 			if(eslave[i].rpc){
289 				/* if ready, don't block in select */
290 				if(eslave[i].rpc->p)
291 					canblock = 0;
292 				FD_SET(display->srvfd, &rset);
293 				FD_SET(display->srvfd, &xset);
294 				if(display->srvfd > max)
295 					max = display->srvfd;
296 			}
297 		}else if(i == Stimer){
298 			t0 = nsec();
299 			if(t0 >= eslave[i].nexttick){
300 				tv.tv_sec = 0;
301 				tv.tv_usec = 0;
302 			}else{
303 				tv.tv_sec = (eslave[i].nexttick-t0)/1000000000;
304 				tv.tv_usec = (eslave[i].nexttick-t0)%1000000000 / 1000;
305 			}
306 			timeout = &tv;
307 		}else{
308 			FD_SET(eslave[i].fd, &rset);
309 			FD_SET(eslave[i].fd, &xset);
310 			if(eslave[i].fd > max)
311 				max = eslave[i].fd;
312 		}
313 	}
314 
315 	if(!canblock){
316 		tv.tv_sec = 0;
317 		tv.tv_usec = 0;
318 		timeout = &tv;
319 	}
320 
321 	if(select(max+1, &rset, &wset, &xset, timeout) < 0)
322 		drawerror(display, "select failure");
323 
324 	/*
325 	 * Look to see what can proceed.
326 	 */
327 	n = 0;
328 	for(i=0; i<nslave; i++){
329 		if(!eslave[i].inuse)
330 			continue;
331 		if(i == Smouse){
332 			if(finishrpc(eslave[i].rpc, &w)){
333 				eslave[i].rpc = nil;
334 				eb = newebuf(&eslave[i], sizeof(Mouse));
335 				_drawmouse = w.mouse;
336 				eb->u.mouse = w.mouse;
337 				if(w.resized)
338 					eresized(1);
339 				n++;
340 			}
341 		}else if(i == Skeyboard){
342 			if(finishrpc(eslave[i].rpc, &w)){
343 				eslave[i].rpc = nil;
344 				eb = newebuf(&eslave[i], sizeof(Rune)+2);	/* +8: alignment */
345 				eb->u.rune = w.rune;
346 				n++;
347 			}
348 		}else if(i == Stimer){
349 			t0 = nsec();
350 			while(t0 > eslave[i].nexttick){
351 				eslave[i].nexttick += eslave[i].n*1000000LL;
352 				eslave[i].head = (Ebuf*)1;
353 				n++;
354 			}
355 		}else{
356 			if(FD_ISSET(eslave[i].fd, &rset)){
357 				eb = newebuf(&eslave[i], eslave[i].n);
358 				eb->n = read(eslave[i].fd, eb->u.buf, eslave[i].n);
359 				n++;
360 			}
361 		}
362 	}
363 	return n;
364 }
365 
366 static int
newkey(ulong key)367 newkey(ulong key)
368 {
369 	int i;
370 
371 	for(i=0; i<MAXSLAVE; i++)
372 		if((key & ~(1<<i)) == 0 && eslave[i].inuse == 0){
373 			if(nslave <= i)
374 				nslave = i + 1;
375 			eslave[i].inuse = 1;
376 			return i;
377 		}
378 	drawerror(display, "events: bad slave assignment");
379 	return 0;
380 }
381 
382 Mouse
emouse(void)383 emouse(void)
384 {
385 	Mouse m;
386 	Ebuf *eb;
387 
388 	if(Smouse < 0)
389 		drawerror(display, "events: mouse not initialized");
390 	eb = ebread(&eslave[Smouse]);
391 	m = eb->u.mouse;
392 	free(eb);
393 	return m;
394 }
395 
396 int
ekbd(void)397 ekbd(void)
398 {
399 	Ebuf *eb;
400 	int c;
401 
402 	if(Skeyboard < 0)
403 		drawerror(display, "events: keyboard not initialzed");
404 	eb = ebread(&eslave[Skeyboard]);
405 	c = eb->u.rune;
406 	free(eb);
407 	return c;
408 }
409 
410 void
emoveto(Point pt)411 emoveto(Point pt)
412 {
413 	_displaymoveto(display, pt);
414 }
415 
416 void
esetcursor(Cursor * c)417 esetcursor(Cursor *c)
418 {
419 	_displaycursor(display, c, nil);
420 }
421 
422 void
esetcursor2(Cursor * c,Cursor2 * c2)423 esetcursor2(Cursor *c, Cursor2 *c2)
424 {
425 	_displaycursor(display, c, c2);
426 }
427 
428 int
ereadmouse(Mouse * m)429 ereadmouse(Mouse *m)
430 {
431 	int resized;
432 
433 	resized = 0;
434 	if(_displayrdmouse(display, m, &resized) < 0)
435 		return -1;
436 	if(resized)
437 		eresized(1);
438 	return 1;
439 }
440