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;
12 extern Mouse _drawmouse;
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 };
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 };
37 static Slave eslave[MAXSLAVE];
38 static int Skeyboard = -1;
39 static int Smouse = -1;
40 static int Stimer = -1;
42 static int nslave;
43 static int newkey(ulong);
44 static int extract(int canblock);
46 static
47 Ebuf*
48 ebread(Slave *s)
49 {
50 Ebuf *eb;
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 }
61 ulong
62 event(Event *e)
63 {
64 return eread(~0UL, e);
65 }
67 ulong
68 eread(ulong keys, Event *e)
69 {
70 Ebuf *eb;
71 int i, id;
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 }
101 int
102 ecanmouse(void)
104 if(Smouse < 0)
105 drawerror(display, "events: mouse not initialized");
106 return ecanread(Emouse);
109 int
110 ecankbd(void)
112 if(Skeyboard < 0)
113 drawerror(display, "events: keyboard not initialzed");
114 return ecanread(Ekeyboard);
117 int
118 ecanread(ulong keys)
120 int i;
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;
129 return -1;
132 ulong
133 estartfn(ulong key, int fd, int n, int (*fn)(int, Event*, uchar*, int))
135 int i;
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;
148 ulong
149 estart(ulong key, int fd, int n)
151 return estartfn(key, fd, n, nil);
154 ulong
155 etimer(ulong key, int n)
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;
167 void
168 einit(ulong keys)
170 if(keys&Ekeyboard){
171 for(Skeyboard=0; Ekeyboard & ~(1<<Skeyboard); Skeyboard++)
173 eslave[Skeyboard].inuse = 1;
174 if(nslave <= Skeyboard)
175 nslave = Skeyboard+1;
177 if(keys&Emouse){
178 for(Smouse=0; Emouse & ~(1<<Smouse); Smouse++)
180 eslave[Smouse].inuse = 1;
181 if(nslave <= Smouse)
182 nslave = Smouse+1;
186 static Ebuf*
187 newebuf(Slave *s, int n)
189 Ebuf *eb;
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;
203 static Muxrpc*
204 startrpc(int type)
206 uchar buf[512];
207 Wsysmsg w;
209 w.type = type;
210 if(convW2M(&w, buf, sizeof buf) == 0)
211 return nil;
212 return muxrpcstart(display->mux, buf);
215 static int
216 finishrpc(Muxrpc *r, Wsysmsg *w)
218 uchar *p;
219 void *v;
220 int n;
222 if(!muxrpccanfinish(r, &v))
223 return 0;
224 p = v;
225 if(p == nil) /* eof on connection */
226 exit(0);
227 GET(p, n);
228 convM2W(p, n, w);
229 free(p);
230 return 1;
233 static int
234 extract(int canblock)
236 Ebuf *eb;
237 int i, n, max;
238 fd_set rset, wset, xset;
239 struct timeval tv, *timeout;
240 Wsysmsg w;
241 vlong t0;
243 /*
244 * Flush draw buffer before waiting for responses.
245 * Avoid doing so if buffer is empty.
246 * Also make sure that we don't interfere with app-specific locking.
247 */
248 if(display->locking){
249 /*
250 * if locking is being done by program,
251 * this means it can't depend on automatic
252 * flush in emouse() etc.
253 */
254 if(canqlock(&display->qlock)){
255 if(display->bufp > display->buf)
256 flushimage(display, 1);
257 unlockdisplay(display);
259 }else
260 if(display->bufp > display->buf)
261 flushimage(display, 1);
263 /*
264 * Set up for select.
265 */
266 FD_ZERO(&rset);
267 FD_ZERO(&wset);
268 FD_ZERO(&xset);
269 max = -1;
270 timeout = nil;
271 for(i=0; i<nslave; i++){
272 if(!eslave[i].inuse)
273 continue;
274 if(i == Smouse){
275 if(eslave[i].rpc == nil)
276 eslave[i].rpc = startrpc(Trdmouse);
277 if(eslave[i].rpc){
278 /* if ready, don't block in select */
279 if(eslave[i].rpc->p)
280 canblock = 0;
281 FD_SET(display->srvfd, &rset);
282 FD_SET(display->srvfd, &xset);
283 if(display->srvfd > max)
284 max = display->srvfd;
286 }else if(i == Skeyboard){
287 if(eslave[i].rpc == nil)
288 eslave[i].rpc = startrpc(Trdkbd4);
289 if(eslave[i].rpc){
290 /* if ready, don't block in select */
291 if(eslave[i].rpc->p)
292 canblock = 0;
293 FD_SET(display->srvfd, &rset);
294 FD_SET(display->srvfd, &xset);
295 if(display->srvfd > max)
296 max = display->srvfd;
298 }else if(i == Stimer){
299 t0 = nsec();
300 if(t0 >= eslave[i].nexttick){
301 tv.tv_sec = 0;
302 tv.tv_usec = 0;
303 }else{
304 tv.tv_sec = (eslave[i].nexttick-t0)/1000000000;
305 tv.tv_usec = (eslave[i].nexttick-t0)%1000000000 / 1000;
307 timeout = &tv;
308 }else{
309 FD_SET(eslave[i].fd, &rset);
310 FD_SET(eslave[i].fd, &xset);
311 if(eslave[i].fd > max)
312 max = eslave[i].fd;
316 if(!canblock){
317 tv.tv_sec = 0;
318 tv.tv_usec = 0;
319 timeout = &tv;
322 if(select(max+1, &rset, &wset, &xset, timeout) < 0)
323 drawerror(display, "select failure");
325 /*
326 * Look to see what can proceed.
327 */
328 n = 0;
329 for(i=0; i<nslave; i++){
330 if(!eslave[i].inuse)
331 continue;
332 if(i == Smouse){
333 if(finishrpc(eslave[i].rpc, &w)){
334 eslave[i].rpc = nil;
335 eb = newebuf(&eslave[i], sizeof(Mouse));
336 _drawmouse = w.mouse;
337 eb->u.mouse = w.mouse;
338 if(w.resized)
339 eresized(1);
340 n++;
342 }else if(i == Skeyboard){
343 if(finishrpc(eslave[i].rpc, &w)){
344 eslave[i].rpc = nil;
345 eb = newebuf(&eslave[i], sizeof(Rune)+2); /* +8: alignment */
346 eb->u.rune = w.rune;
347 n++;
349 }else if(i == Stimer){
350 t0 = nsec();
351 while(t0 > eslave[i].nexttick){
352 eslave[i].nexttick += eslave[i].n*1000000LL;
353 eslave[i].head = (Ebuf*)1;
354 n++;
356 }else{
357 if(FD_ISSET(eslave[i].fd, &rset)){
358 eb = newebuf(&eslave[i], eslave[i].n);
359 eb->n = read(eslave[i].fd, eb->u.buf, eslave[i].n);
360 n++;
364 return n;
367 static int
368 newkey(ulong key)
370 int i;
372 for(i=0; i<MAXSLAVE; i++)
373 if((key & ~(1<<i)) == 0 && eslave[i].inuse == 0){
374 if(nslave <= i)
375 nslave = i + 1;
376 eslave[i].inuse = 1;
377 return i;
379 drawerror(display, "events: bad slave assignment");
380 return 0;
383 Mouse
384 emouse(void)
386 Mouse m;
387 Ebuf *eb;
389 if(Smouse < 0)
390 drawerror(display, "events: mouse not initialized");
391 eb = ebread(&eslave[Smouse]);
392 m = eb->u.mouse;
393 free(eb);
394 return m;
397 int
398 ekbd(void)
400 Ebuf *eb;
401 int c;
403 if(Skeyboard < 0)
404 drawerror(display, "events: keyboard not initialzed");
405 eb = ebread(&eslave[Skeyboard]);
406 c = eb->u.rune;
407 free(eb);
408 return c;
411 void
412 emoveto(Point pt)
414 _displaymoveto(display, pt);
417 void
418 esetcursor(Cursor *c)
420 _displaycursor(display, c, nil);
423 void
424 esetcursor2(Cursor *c, Cursor2 *c2)
426 _displaycursor(display, c, c2);
429 int
430 ereadmouse(Mouse *m)
432 int resized;
434 resized = 0;
435 if(_displayrdmouse(display, m, &resized) < 0)
436 return -1;
437 if(resized)
438 eresized(1);
439 return 1;