Blob


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