1 76193d7c 2003-09-30 devnull #include <u.h>
2 76193d7c 2003-09-30 devnull #include <libc.h>
3 76193d7c 2003-09-30 devnull #include <draw.h>
4 76193d7c 2003-09-30 devnull #include <cursor.h>
5 76193d7c 2003-09-30 devnull #include <event.h>
7 76193d7c 2003-09-30 devnull typedef struct Slave Slave;
8 76193d7c 2003-09-30 devnull typedef struct Ebuf Ebuf;
10 76193d7c 2003-09-30 devnull struct Slave
13 76193d7c 2003-09-30 devnull Ebuf *head; /* ueue of messages for this descriptor */
14 76193d7c 2003-09-30 devnull Ebuf *tail;
15 76193d7c 2003-09-30 devnull int (*fn)(int, Event*, uchar*, int);
18 76193d7c 2003-09-30 devnull struct Ebuf
20 76193d7c 2003-09-30 devnull Ebuf *next;
21 76193d7c 2003-09-30 devnull int n; /* number of bytes in buf */
22 76193d7c 2003-09-30 devnull uchar buf[EMAXMSG];
25 76193d7c 2003-09-30 devnull static Slave eslave[MAXSLAVE];
26 76193d7c 2003-09-30 devnull static int Skeyboard = -1;
27 76193d7c 2003-09-30 devnull static int Smouse = -1;
28 76193d7c 2003-09-30 devnull static int Stimer = -1;
29 76193d7c 2003-09-30 devnull static int logfid;
31 76193d7c 2003-09-30 devnull static int nslave;
32 76193d7c 2003-09-30 devnull static int parentpid;
33 76193d7c 2003-09-30 devnull static int epipe[2];
34 76193d7c 2003-09-30 devnull static int eforkslave(ulong);
35 76193d7c 2003-09-30 devnull static void extract(void);
36 76193d7c 2003-09-30 devnull static void ekill(void);
37 76193d7c 2003-09-30 devnull static int enote(void *, char *);
38 76193d7c 2003-09-30 devnull static int mousefd;
39 76193d7c 2003-09-30 devnull static int cursorfd;
43 76193d7c 2003-09-30 devnull ebread(Slave *s)
45 76193d7c 2003-09-30 devnull Ebuf *eb;
50 76193d7c 2003-09-30 devnull d = dirfstat(epipe[0]);
51 76193d7c 2003-09-30 devnull if(d == nil)
52 76193d7c 2003-09-30 devnull drawerror(display, "events: eread stat error");
53 76193d7c 2003-09-30 devnull l = d->length;
55 76193d7c 2003-09-30 devnull if(s->head && l==0)
57 76193d7c 2003-09-30 devnull extract();
59 76193d7c 2003-09-30 devnull eb = s->head;
60 76193d7c 2003-09-30 devnull s->head = s->head->next;
61 76193d7c 2003-09-30 devnull if(s->head == 0)
62 76193d7c 2003-09-30 devnull s->tail = 0;
63 76193d7c 2003-09-30 devnull return eb;
67 76193d7c 2003-09-30 devnull event(Event *e)
69 76193d7c 2003-09-30 devnull return eread(~0UL, e);
73 76193d7c 2003-09-30 devnull eread(ulong keys, Event *e)
75 76193d7c 2003-09-30 devnull Ebuf *eb;
76 76193d7c 2003-09-30 devnull int i, id;
78 76193d7c 2003-09-30 devnull if(keys == 0)
79 76193d7c 2003-09-30 devnull return 0;
81 76193d7c 2003-09-30 devnull for(i=0; i<nslave; i++)
82 76193d7c 2003-09-30 devnull if((keys & (1<<i)) && eslave[i].head){
83 76193d7c 2003-09-30 devnull id = 1<<i;
84 76193d7c 2003-09-30 devnull if(i == Smouse)
85 76193d7c 2003-09-30 devnull e->mouse = emouse();
86 76193d7c 2003-09-30 devnull else if(i == Skeyboard)
87 76193d7c 2003-09-30 devnull e->kbdc = ekbd();
88 76193d7c 2003-09-30 devnull else if(i == Stimer)
89 76193d7c 2003-09-30 devnull eslave[i].head = 0;
91 76193d7c 2003-09-30 devnull eb = ebread(&eslave[i]);
92 76193d7c 2003-09-30 devnull e->n = eb->n;
93 76193d7c 2003-09-30 devnull if(eslave[i].fn)
94 76193d7c 2003-09-30 devnull id = (*eslave[i].fn)(id, e, eb->buf, eb->n);
96 76193d7c 2003-09-30 devnull memmove(e->data, eb->buf, eb->n);
97 76193d7c 2003-09-30 devnull free(eb);
99 76193d7c 2003-09-30 devnull return id;
101 76193d7c 2003-09-30 devnull extract();
103 76193d7c 2003-09-30 devnull return 0;
107 76193d7c 2003-09-30 devnull ecanmouse(void)
109 76193d7c 2003-09-30 devnull if(Smouse < 0)
110 76193d7c 2003-09-30 devnull drawerror(display, "events: mouse not initialized");
111 76193d7c 2003-09-30 devnull return ecanread(Emouse);
115 76193d7c 2003-09-30 devnull ecankbd(void)
117 76193d7c 2003-09-30 devnull if(Skeyboard < 0)
118 76193d7c 2003-09-30 devnull drawerror(display, "events: keyboard not initialzed");
119 76193d7c 2003-09-30 devnull return ecanread(Ekeyboard);
123 76193d7c 2003-09-30 devnull ecanread(ulong keys)
127 76193d7c 2003-09-30 devnull ulong l;
129 76193d7c 2003-09-30 devnull for(;;){
130 76193d7c 2003-09-30 devnull for(i=0; i<nslave; i++)
131 76193d7c 2003-09-30 devnull if((keys & (1<<i)) && eslave[i].head)
132 76193d7c 2003-09-30 devnull return 1;
133 76193d7c 2003-09-30 devnull d = dirfstat(epipe[0]);
134 76193d7c 2003-09-30 devnull if(d == nil)
135 76193d7c 2003-09-30 devnull drawerror(display, "events: ecanread stat error");
136 76193d7c 2003-09-30 devnull l = d->length;
137 76193d7c 2003-09-30 devnull free(d);
138 76193d7c 2003-09-30 devnull if(l == 0)
139 76193d7c 2003-09-30 devnull return 0;
140 76193d7c 2003-09-30 devnull extract();
142 76193d7c 2003-09-30 devnull return -1;
146 76193d7c 2003-09-30 devnull estartfn(ulong key, int fd, int n, int (*fn)(int, Event*, uchar*, int))
148 76193d7c 2003-09-30 devnull char buf[EMAXMSG+1];
149 76193d7c 2003-09-30 devnull int i, r;
151 76193d7c 2003-09-30 devnull if(fd < 0)
152 76193d7c 2003-09-30 devnull drawerror(display, "events: bad file descriptor");
153 76193d7c 2003-09-30 devnull if(n <= 0 || n > EMAXMSG)
154 76193d7c 2003-09-30 devnull n = EMAXMSG;
155 76193d7c 2003-09-30 devnull i = eforkslave(key);
156 76193d7c 2003-09-30 devnull if(i < MAXSLAVE){
157 76193d7c 2003-09-30 devnull eslave[i].fn = fn;
158 76193d7c 2003-09-30 devnull return 1<<i;
160 76193d7c 2003-09-30 devnull buf[0] = i - MAXSLAVE;
161 76193d7c 2003-09-30 devnull while((r = read(fd, buf+1, n))>0)
162 76193d7c 2003-09-30 devnull if(write(epipe[1], buf, r+1)!=r+1)
164 76193d7c 2003-09-30 devnull buf[0] = MAXSLAVE;
165 76193d7c 2003-09-30 devnull write(epipe[1], buf, 1);
166 76193d7c 2003-09-30 devnull _exits(0);
167 76193d7c 2003-09-30 devnull return 0;
171 76193d7c 2003-09-30 devnull estart(ulong key, int fd, int n)
173 76193d7c 2003-09-30 devnull return estartfn(key, fd, n, nil);
177 76193d7c 2003-09-30 devnull etimer(ulong key, int n)
179 76193d7c 2003-09-30 devnull char t[2];
181 76193d7c 2003-09-30 devnull if(Stimer != -1)
182 76193d7c 2003-09-30 devnull drawerror(display, "events: timer started twice");
183 76193d7c 2003-09-30 devnull Stimer = eforkslave(key);
184 76193d7c 2003-09-30 devnull if(Stimer < MAXSLAVE)
185 76193d7c 2003-09-30 devnull return 1<<Stimer;
186 76193d7c 2003-09-30 devnull if(n <= 0)
187 76193d7c 2003-09-30 devnull n = 1000;
188 76193d7c 2003-09-30 devnull t[0] = t[1] = Stimer - MAXSLAVE;
190 76193d7c 2003-09-30 devnull sleep(n);
191 76193d7c 2003-09-30 devnull while(write(epipe[1], t, 2) == 2);
192 76193d7c 2003-09-30 devnull t[0] = MAXSLAVE;
193 76193d7c 2003-09-30 devnull write(epipe[1], t, 1);
194 76193d7c 2003-09-30 devnull _exits(0);
195 76193d7c 2003-09-30 devnull return 0;
198 76193d7c 2003-09-30 devnull static void
199 76193d7c 2003-09-30 devnull ekeyslave(int fd)
202 76193d7c 2003-09-30 devnull char t[3], k[10];
203 76193d7c 2003-09-30 devnull int kr, kn, w;
205 76193d7c 2003-09-30 devnull if(eforkslave(Ekeyboard) < MAXSLAVE)
208 76193d7c 2003-09-30 devnull t[0] = Skeyboard;
209 76193d7c 2003-09-30 devnull for(;;){
210 76193d7c 2003-09-30 devnull while(!fullrune(k, kn)){
211 76193d7c 2003-09-30 devnull kr = read(fd, k+kn, sizeof k - kn);
212 76193d7c 2003-09-30 devnull if(kr <= 0)
213 76193d7c 2003-09-30 devnull goto breakout;
214 76193d7c 2003-09-30 devnull kn += kr;
216 76193d7c 2003-09-30 devnull w = chartorune(&r, k);
217 76193d7c 2003-09-30 devnull kn -= w;
218 76193d7c 2003-09-30 devnull memmove(k, &k[w], kn);
219 76193d7c 2003-09-30 devnull t[1] = r;
220 76193d7c 2003-09-30 devnull t[2] = r>>8;
221 76193d7c 2003-09-30 devnull if(write(epipe[1], t, 3) != 3)
224 76193d7c 2003-09-30 devnull breakout:;
225 76193d7c 2003-09-30 devnull t[0] = MAXSLAVE;
226 76193d7c 2003-09-30 devnull write(epipe[1], t, 1);
227 76193d7c 2003-09-30 devnull _exits(0);
231 76193d7c 2003-09-30 devnull einit(ulong keys)
233 76193d7c 2003-09-30 devnull int ctl, fd;
234 76193d7c 2003-09-30 devnull char buf[256];
236 76193d7c 2003-09-30 devnull parentpid = getpid();
237 76193d7c 2003-09-30 devnull if(pipe(epipe) < 0)
238 76193d7c 2003-09-30 devnull drawerror(display, "events: einit pipe");
239 76193d7c 2003-09-30 devnull atexit(ekill);
240 76193d7c 2003-09-30 devnull atnotify(enote, 1);
241 76193d7c 2003-09-30 devnull snprint(buf, sizeof buf, "%s/mouse", display->devdir);
242 76193d7c 2003-09-30 devnull mousefd = open(buf, ORDWR|OCEXEC);
243 76193d7c 2003-09-30 devnull if(mousefd < 0)
244 76193d7c 2003-09-30 devnull drawerror(display, "einit: can't open mouse\n");
245 76193d7c 2003-09-30 devnull snprint(buf, sizeof buf, "%s/cursor", display->devdir);
246 76193d7c 2003-09-30 devnull cursorfd = open(buf, ORDWR|OCEXEC);
247 76193d7c 2003-09-30 devnull if(cursorfd < 0)
248 76193d7c 2003-09-30 devnull drawerror(display, "einit: can't open cursor\n");
249 76193d7c 2003-09-30 devnull if(keys&Ekeyboard){
250 76193d7c 2003-09-30 devnull snprint(buf, sizeof buf, "%s/cons", display->devdir);
251 76193d7c 2003-09-30 devnull fd = open(buf, OREAD);
252 76193d7c 2003-09-30 devnull if(fd < 0)
253 76193d7c 2003-09-30 devnull drawerror(display, "events: can't open console");
254 76193d7c 2003-09-30 devnull snprint(buf, sizeof buf, "%s/consctl", display->devdir);
255 76193d7c 2003-09-30 devnull ctl = open("/dev/consctl", OWRITE|OCEXEC);
256 76193d7c 2003-09-30 devnull if(ctl < 0)
257 76193d7c 2003-09-30 devnull drawerror(display, "events: can't open consctl");
258 76193d7c 2003-09-30 devnull write(ctl, "rawon", 5);
259 76193d7c 2003-09-30 devnull for(Skeyboard=0; Ekeyboard & ~(1<<Skeyboard); Skeyboard++)
261 76193d7c 2003-09-30 devnull ekeyslave(fd);
263 76193d7c 2003-09-30 devnull if(keys&Emouse){
264 76193d7c 2003-09-30 devnull estart(Emouse, mousefd, 1+4*12);
265 76193d7c 2003-09-30 devnull for(Smouse=0; Emouse & ~(1<<Smouse); Smouse++)
270 76193d7c 2003-09-30 devnull static void
271 76193d7c 2003-09-30 devnull extract(void)
273 76193d7c 2003-09-30 devnull Slave *s;
274 76193d7c 2003-09-30 devnull Ebuf *eb;
275 76193d7c 2003-09-30 devnull int i, n;
276 76193d7c 2003-09-30 devnull uchar ebuf[EMAXMSG+1];
278 76193d7c 2003-09-30 devnull /* avoid generating a message if there's nothing to show. */
279 76193d7c 2003-09-30 devnull /* this test isn't perfect, though; could do flushimage(display, 0) then call extract */
280 76193d7c 2003-09-30 devnull /* also: make sure we don't interfere if we're multiprocessing the display */
281 76193d7c 2003-09-30 devnull if(display->locking){
282 76193d7c 2003-09-30 devnull /* if locking is being done by program, this means it can't depend on automatic flush in emouse() etc. */
283 76193d7c 2003-09-30 devnull if(canqlock(&display->qlock)){
284 76193d7c 2003-09-30 devnull if(display->bufp > display->buf)
285 76193d7c 2003-09-30 devnull flushimage(display, 1);
286 76193d7c 2003-09-30 devnull unlockdisplay(display);
289 76193d7c 2003-09-30 devnull if(display->bufp > display->buf)
290 76193d7c 2003-09-30 devnull flushimage(display, 1);
292 76193d7c 2003-09-30 devnull if((n=read(epipe[0], ebuf, EMAXMSG+1)) < 0
293 76193d7c 2003-09-30 devnull || ebuf[0] >= MAXSLAVE)
294 76193d7c 2003-09-30 devnull drawerror(display, "eof on event pipe");
295 76193d7c 2003-09-30 devnull if(n == 0)
296 76193d7c 2003-09-30 devnull goto loop;
297 76193d7c 2003-09-30 devnull i = ebuf[0];
298 76193d7c 2003-09-30 devnull if(i >= nslave || n <= 1)
299 76193d7c 2003-09-30 devnull drawerror(display, "events: protocol error: short read");
300 76193d7c 2003-09-30 devnull s = &eslave[i];
301 76193d7c 2003-09-30 devnull if(i == Stimer){
302 76193d7c 2003-09-30 devnull s->head = (Ebuf *)1;
305 76193d7c 2003-09-30 devnull if(i == Skeyboard && n != 3)
306 76193d7c 2003-09-30 devnull drawerror(display, "events: protocol error: keyboard");
307 76193d7c 2003-09-30 devnull if(i == Smouse){
308 76193d7c 2003-09-30 devnull if(n < 1+1+2*12)
309 76193d7c 2003-09-30 devnull drawerror(display, "events: protocol error: mouse");
310 76193d7c 2003-09-30 devnull if(ebuf[1] == 'r')
311 76193d7c 2003-09-30 devnull eresized(1);
312 76193d7c 2003-09-30 devnull /* squash extraneous mouse events */
313 76193d7c 2003-09-30 devnull if((eb=s->tail) && memcmp(eb->buf+1+2*12, ebuf+1+1+2*12, 12)==0){
314 76193d7c 2003-09-30 devnull memmove(eb->buf, &ebuf[1], n - 1);
318 76193d7c 2003-09-30 devnull /* try to save space by only allocating as much buffer as we need */
319 76193d7c 2003-09-30 devnull eb = malloc(sizeof(*eb) - sizeof(eb->buf) + n - 1);
320 76193d7c 2003-09-30 devnull if(eb == 0)
321 76193d7c 2003-09-30 devnull drawerror(display, "events: protocol error 4");
322 76193d7c 2003-09-30 devnull eb->n = n - 1;
323 76193d7c 2003-09-30 devnull memmove(eb->buf, &ebuf[1], n - 1);
324 76193d7c 2003-09-30 devnull eb->next = 0;
325 76193d7c 2003-09-30 devnull if(s->head)
326 76193d7c 2003-09-30 devnull s->tail = s->tail->next = eb;
328 76193d7c 2003-09-30 devnull s->head = s->tail = eb;
331 76193d7c 2003-09-30 devnull static int
332 76193d7c 2003-09-30 devnull eforkslave(ulong key)
334 76193d7c 2003-09-30 devnull int i, pid;
336 76193d7c 2003-09-30 devnull for(i=0; i<MAXSLAVE; i++)
337 76193d7c 2003-09-30 devnull if((key & ~(1<<i)) == 0 && eslave[i].pid == 0){
338 76193d7c 2003-09-30 devnull if(nslave <= i)
339 76193d7c 2003-09-30 devnull nslave = i + 1;
341 76193d7c 2003-09-30 devnull * share the file descriptors so the last child
342 76193d7c 2003-09-30 devnull * out closes all connections to the window server.
344 76193d7c 2003-09-30 devnull switch(pid = rfork(RFPROC)){
346 76193d7c 2003-09-30 devnull return MAXSLAVE+i;
347 76193d7c 2003-09-30 devnull case -1:
348 76193d7c 2003-09-30 devnull fprint(2, "events: fork error\n");
349 76193d7c 2003-09-30 devnull exits("fork");
351 76193d7c 2003-09-30 devnull eslave[i].pid = pid;
352 76193d7c 2003-09-30 devnull eslave[i].head = eslave[i].tail = 0;
353 76193d7c 2003-09-30 devnull return i;
355 76193d7c 2003-09-30 devnull drawerror(display, "events: bad slave assignment");
356 76193d7c 2003-09-30 devnull return 0;
359 76193d7c 2003-09-30 devnull static int
360 76193d7c 2003-09-30 devnull enote(void *v, char *s)
362 76193d7c 2003-09-30 devnull char t[1];
363 76193d7c 2003-09-30 devnull int i, pid;
365 76193d7c 2003-09-30 devnull USED(v, s);
366 76193d7c 2003-09-30 devnull pid = getpid();
367 76193d7c 2003-09-30 devnull if(pid != parentpid){
368 76193d7c 2003-09-30 devnull for(i=0; i<nslave; i++){
369 76193d7c 2003-09-30 devnull if(pid == eslave[i].pid){
370 76193d7c 2003-09-30 devnull t[0] = MAXSLAVE;
371 76193d7c 2003-09-30 devnull write(epipe[1], t, 1);
375 76193d7c 2003-09-30 devnull return 0;
377 76193d7c 2003-09-30 devnull close(epipe[0]);
378 76193d7c 2003-09-30 devnull epipe[0] = -1;
379 76193d7c 2003-09-30 devnull close(epipe[1]);
380 76193d7c 2003-09-30 devnull epipe[1] = -1;
381 76193d7c 2003-09-30 devnull for(i=0; i<nslave; i++){
382 76193d7c 2003-09-30 devnull if(pid == eslave[i].pid)
383 76193d7c 2003-09-30 devnull continue; /* don't kill myself */
384 76193d7c 2003-09-30 devnull postnote(PNPROC, eslave[i].pid, "die");
386 76193d7c 2003-09-30 devnull return 0;
389 76193d7c 2003-09-30 devnull static void
390 76193d7c 2003-09-30 devnull ekill(void)
392 76193d7c 2003-09-30 devnull enote(0, 0);
396 76193d7c 2003-09-30 devnull emouse(void)
398 76193d7c 2003-09-30 devnull Mouse m;
399 76193d7c 2003-09-30 devnull Ebuf *eb;
400 76193d7c 2003-09-30 devnull static but[2];
403 76193d7c 2003-09-30 devnull if(Smouse < 0)
404 76193d7c 2003-09-30 devnull drawerror(display, "events: mouse not initialized");
405 76193d7c 2003-09-30 devnull eb = ebread(&eslave[Smouse]);
406 76193d7c 2003-09-30 devnull m.xy.x = atoi((char*)eb->buf+1+0*12);
407 76193d7c 2003-09-30 devnull m.xy.y = atoi((char*)eb->buf+1+1*12);
408 76193d7c 2003-09-30 devnull b = atoi((char*)eb->buf+1+2*12);
409 76193d7c 2003-09-30 devnull m.buttons = b&7;
410 76193d7c 2003-09-30 devnull m.msec = atoi((char*)eb->buf+1+3*12);
411 76193d7c 2003-09-30 devnull if (logfid)
412 76193d7c 2003-09-30 devnull fprint(logfid, "b: %d xy: %P\n", m.buttons, m.xy);
413 76193d7c 2003-09-30 devnull free(eb);
414 76193d7c 2003-09-30 devnull return m;
418 76193d7c 2003-09-30 devnull ekbd(void)
420 76193d7c 2003-09-30 devnull Ebuf *eb;
423 76193d7c 2003-09-30 devnull if(Skeyboard < 0)
424 76193d7c 2003-09-30 devnull drawerror(display, "events: keyboard not initialzed");
425 76193d7c 2003-09-30 devnull eb = ebread(&eslave[Skeyboard]);
426 76193d7c 2003-09-30 devnull c = eb->buf[0] + (eb->buf[1]<<8);
427 76193d7c 2003-09-30 devnull free(eb);
428 76193d7c 2003-09-30 devnull return c;
432 76193d7c 2003-09-30 devnull emoveto(Point pt)
434 76193d7c 2003-09-30 devnull char buf[2*12+2];
437 76193d7c 2003-09-30 devnull n = sprint(buf, "m%d %d", pt.x, pt.y);
438 76193d7c 2003-09-30 devnull write(mousefd, buf, n);
442 76193d7c 2003-09-30 devnull esetcursor(Cursor *c)
444 76193d7c 2003-09-30 devnull uchar curs[2*4+2*2*16];
446 76193d7c 2003-09-30 devnull if(c == 0)
447 76193d7c 2003-09-30 devnull write(cursorfd, curs, 0);
449 76193d7c 2003-09-30 devnull BPLONG(curs+0*4, c->offset.x);
450 76193d7c 2003-09-30 devnull BPLONG(curs+1*4, c->offset.y);
451 76193d7c 2003-09-30 devnull memmove(curs+2*4, c->clr, 2*2*16);
452 76193d7c 2003-09-30 devnull write(cursorfd, curs, sizeof curs);
457 76193d7c 2003-09-30 devnull ereadmouse(Mouse *m)
460 76193d7c 2003-09-30 devnull char buf[128];
463 76193d7c 2003-09-30 devnull n = read(mousefd, buf, sizeof(buf));
464 76193d7c 2003-09-30 devnull if(n < 0) /* probably interrupted */
465 76193d7c 2003-09-30 devnull return -1;
466 76193d7c 2003-09-30 devnull n = eatomouse(m, buf, n);
467 76193d7c 2003-09-30 devnull }while(n == 0);
468 76193d7c 2003-09-30 devnull return n;
472 76193d7c 2003-09-30 devnull eatomouse(Mouse *m, char *buf, int n)
474 76193d7c 2003-09-30 devnull if(n != 1+4*12){
475 76193d7c 2003-09-30 devnull werrstr("atomouse: bad count");
476 76193d7c 2003-09-30 devnull return -1;
479 76193d7c 2003-09-30 devnull if(buf[0] == 'r')
480 76193d7c 2003-09-30 devnull eresized(1);
481 76193d7c 2003-09-30 devnull m->xy.x = atoi(buf+1+0*12);
482 76193d7c 2003-09-30 devnull m->xy.y = atoi(buf+1+1*12);
483 76193d7c 2003-09-30 devnull m->buttons = atoi(buf+1+2*12);
484 76193d7c 2003-09-30 devnull m->msec = atoi(buf+1+3*12);
485 76193d7c 2003-09-30 devnull return n;