xref: /plan9/sys/src/libdraw/event.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include <u.h>
2*7dd7cddfSDavid du Colombier #include <libc.h>
3*7dd7cddfSDavid du Colombier #include <draw.h>
4*7dd7cddfSDavid du Colombier #include <cursor.h>
5*7dd7cddfSDavid du Colombier #include <event.h>
6*7dd7cddfSDavid du Colombier 
7*7dd7cddfSDavid du Colombier typedef struct	Slave Slave;
8*7dd7cddfSDavid du Colombier typedef struct	Ebuf Ebuf;
9*7dd7cddfSDavid du Colombier 
10*7dd7cddfSDavid du Colombier struct Slave
11*7dd7cddfSDavid du Colombier {
12*7dd7cddfSDavid du Colombier 	int	pid;
13*7dd7cddfSDavid du Colombier 	Ebuf	*head;		/* queue of messages for this descriptor */
14*7dd7cddfSDavid du Colombier 	Ebuf	*tail;
15*7dd7cddfSDavid du Colombier 	int	(*fn)(int, Event*, uchar*, int);
16*7dd7cddfSDavid du Colombier };
17*7dd7cddfSDavid du Colombier 
18*7dd7cddfSDavid du Colombier struct Ebuf
19*7dd7cddfSDavid du Colombier {
20*7dd7cddfSDavid du Colombier 	Ebuf	*next;
21*7dd7cddfSDavid du Colombier 	int	n;		/* number of bytes in buf */
22*7dd7cddfSDavid du Colombier 	uchar	buf[EMAXMSG];
23*7dd7cddfSDavid du Colombier };
24*7dd7cddfSDavid du Colombier 
25*7dd7cddfSDavid du Colombier static	Slave	eslave[MAXSLAVE];
26*7dd7cddfSDavid du Colombier static	int	Skeyboard = -1;
27*7dd7cddfSDavid du Colombier static	int	Smouse = -1;
28*7dd7cddfSDavid du Colombier static	int	Stimer = -1;
29*7dd7cddfSDavid du Colombier static	int	logfid;
30*7dd7cddfSDavid du Colombier 
31*7dd7cddfSDavid du Colombier static	int	nslave;
32*7dd7cddfSDavid du Colombier static	int	parentpid;
33*7dd7cddfSDavid du Colombier static	int	epipe[2];
34*7dd7cddfSDavid du Colombier static	int	eforkslave(ulong);
35*7dd7cddfSDavid du Colombier static	void	extract(void);
36*7dd7cddfSDavid du Colombier static	void	ekill(void);
37*7dd7cddfSDavid du Colombier static	int	enote(void *, char *);
38*7dd7cddfSDavid du Colombier static	int	mousefd;
39*7dd7cddfSDavid du Colombier static	int	cursorfd;
40*7dd7cddfSDavid du Colombier 
41*7dd7cddfSDavid du Colombier static
42*7dd7cddfSDavid du Colombier Ebuf*
43*7dd7cddfSDavid du Colombier ebread(Slave *s)
44*7dd7cddfSDavid du Colombier {
45*7dd7cddfSDavid du Colombier 	Ebuf *eb;
46*7dd7cddfSDavid du Colombier 	Dir d;
47*7dd7cddfSDavid du Colombier 
48*7dd7cddfSDavid du Colombier 	for(;;){
49*7dd7cddfSDavid du Colombier 		if(dirfstat(epipe[0], &d) < 0)
50*7dd7cddfSDavid du Colombier 			drawerror(display, "events: eread stat error");
51*7dd7cddfSDavid du Colombier 		if(s->head && d.length == 0)
52*7dd7cddfSDavid du Colombier 			break;
53*7dd7cddfSDavid du Colombier 		extract();
54*7dd7cddfSDavid du Colombier 	}
55*7dd7cddfSDavid du Colombier 	eb = s->head;
56*7dd7cddfSDavid du Colombier 	s->head = s->head->next;
57*7dd7cddfSDavid du Colombier 	if(s->head == 0)
58*7dd7cddfSDavid du Colombier 		s->tail = 0;
59*7dd7cddfSDavid du Colombier 	return eb;
60*7dd7cddfSDavid du Colombier }
61*7dd7cddfSDavid du Colombier 
62*7dd7cddfSDavid du Colombier ulong
63*7dd7cddfSDavid du Colombier event(Event *e)
64*7dd7cddfSDavid du Colombier {
65*7dd7cddfSDavid du Colombier 	return eread(~0UL, e);
66*7dd7cddfSDavid du Colombier }
67*7dd7cddfSDavid du Colombier 
68*7dd7cddfSDavid du Colombier ulong
69*7dd7cddfSDavid du Colombier eread(ulong keys, Event *e)
70*7dd7cddfSDavid du Colombier {
71*7dd7cddfSDavid du Colombier 	Ebuf *eb;
72*7dd7cddfSDavid du Colombier 	int i, id;
73*7dd7cddfSDavid du Colombier 
74*7dd7cddfSDavid du Colombier 	if(keys == 0)
75*7dd7cddfSDavid du Colombier 		return 0;
76*7dd7cddfSDavid du Colombier 	for(;;){
77*7dd7cddfSDavid du Colombier 		for(i=0; i<nslave; i++)
78*7dd7cddfSDavid du Colombier 			if((keys & (1<<i)) && eslave[i].head){
79*7dd7cddfSDavid du Colombier 				id = 1<<i;
80*7dd7cddfSDavid du Colombier 				if(i == Smouse)
81*7dd7cddfSDavid du Colombier 					e->mouse = emouse();
82*7dd7cddfSDavid du Colombier 				else if(i == Skeyboard)
83*7dd7cddfSDavid du Colombier 					e->kbdc = ekbd();
84*7dd7cddfSDavid du Colombier 				else if(i == Stimer)
85*7dd7cddfSDavid du Colombier 					eslave[i].head = 0;
86*7dd7cddfSDavid du Colombier 				else{
87*7dd7cddfSDavid du Colombier 					eb = ebread(&eslave[i]);
88*7dd7cddfSDavid du Colombier 					e->n = eb->n;
89*7dd7cddfSDavid du Colombier 					if(eslave[i].fn)
90*7dd7cddfSDavid du Colombier 						id = (*eslave[i].fn)(id, e, eb->buf, eb->n);
91*7dd7cddfSDavid du Colombier 					else
92*7dd7cddfSDavid du Colombier 						memmove(e->data, eb->buf, eb->n);
93*7dd7cddfSDavid du Colombier 					free(eb);
94*7dd7cddfSDavid du Colombier 				}
95*7dd7cddfSDavid du Colombier 				return id;
96*7dd7cddfSDavid du Colombier 			}
97*7dd7cddfSDavid du Colombier 		extract();
98*7dd7cddfSDavid du Colombier 	}
99*7dd7cddfSDavid du Colombier 	return 0;
100*7dd7cddfSDavid du Colombier }
101*7dd7cddfSDavid du Colombier 
102*7dd7cddfSDavid du Colombier int
103*7dd7cddfSDavid du Colombier ecanmouse(void)
104*7dd7cddfSDavid du Colombier {
105*7dd7cddfSDavid du Colombier 	if(Smouse < 0)
106*7dd7cddfSDavid du Colombier 		drawerror(display, "events: mouse not initialized");
107*7dd7cddfSDavid du Colombier 	return ecanread(Emouse);
108*7dd7cddfSDavid du Colombier }
109*7dd7cddfSDavid du Colombier 
110*7dd7cddfSDavid du Colombier int
111*7dd7cddfSDavid du Colombier ecankbd(void)
112*7dd7cddfSDavid du Colombier {
113*7dd7cddfSDavid du Colombier 	if(Skeyboard < 0)
114*7dd7cddfSDavid du Colombier 		drawerror(display, "events: keyboard not initialzed");
115*7dd7cddfSDavid du Colombier 	return ecanread(Ekeyboard);
116*7dd7cddfSDavid du Colombier }
117*7dd7cddfSDavid du Colombier 
118*7dd7cddfSDavid du Colombier int
119*7dd7cddfSDavid du Colombier ecanread(ulong keys)
120*7dd7cddfSDavid du Colombier {
121*7dd7cddfSDavid du Colombier 	Dir d;
122*7dd7cddfSDavid du Colombier 	int i;
123*7dd7cddfSDavid du Colombier 
124*7dd7cddfSDavid du Colombier 	for(;;){
125*7dd7cddfSDavid du Colombier 		for(i=0; i<nslave; i++)
126*7dd7cddfSDavid du Colombier 			if((keys & (1<<i)) && eslave[i].head)
127*7dd7cddfSDavid du Colombier 				return 1;
128*7dd7cddfSDavid du Colombier 		if(dirfstat(epipe[0], &d) < 0)
129*7dd7cddfSDavid du Colombier 			drawerror(display, "events: ecanread stat error");
130*7dd7cddfSDavid du Colombier 		if(d.length == 0)
131*7dd7cddfSDavid du Colombier 			return 0;
132*7dd7cddfSDavid du Colombier 		extract();
133*7dd7cddfSDavid du Colombier 	}
134*7dd7cddfSDavid du Colombier 	return -1;
135*7dd7cddfSDavid du Colombier }
136*7dd7cddfSDavid du Colombier 
137*7dd7cddfSDavid du Colombier ulong
138*7dd7cddfSDavid du Colombier estartfn(ulong key, int fd, int n, int (*fn)(int, Event*, uchar*, int))
139*7dd7cddfSDavid du Colombier {
140*7dd7cddfSDavid du Colombier 	char buf[EMAXMSG+1];
141*7dd7cddfSDavid du Colombier 	int i, r;
142*7dd7cddfSDavid du Colombier 
143*7dd7cddfSDavid du Colombier 	if(fd < 0)
144*7dd7cddfSDavid du Colombier 		drawerror(display, "events: bad file descriptor");
145*7dd7cddfSDavid du Colombier 	if(n <= 0 || n > EMAXMSG)
146*7dd7cddfSDavid du Colombier 		n = EMAXMSG;
147*7dd7cddfSDavid du Colombier 	i = eforkslave(key);
148*7dd7cddfSDavid du Colombier 	if(i < MAXSLAVE){
149*7dd7cddfSDavid du Colombier 		eslave[i].fn = fn;
150*7dd7cddfSDavid du Colombier 		return 1<<i;
151*7dd7cddfSDavid du Colombier 	}
152*7dd7cddfSDavid du Colombier 	buf[0] = i - MAXSLAVE;
153*7dd7cddfSDavid du Colombier 	while((r = read(fd, buf+1, n))>0)
154*7dd7cddfSDavid du Colombier 		if(write(epipe[1], buf, r+1)!=r+1)
155*7dd7cddfSDavid du Colombier 			break;
156*7dd7cddfSDavid du Colombier 	buf[0] = MAXSLAVE;
157*7dd7cddfSDavid du Colombier 	write(epipe[1], buf, 1);
158*7dd7cddfSDavid du Colombier 	_exits(0);
159*7dd7cddfSDavid du Colombier 	return 0;
160*7dd7cddfSDavid du Colombier }
161*7dd7cddfSDavid du Colombier 
162*7dd7cddfSDavid du Colombier ulong
163*7dd7cddfSDavid du Colombier estart(ulong key, int fd, int n)
164*7dd7cddfSDavid du Colombier {
165*7dd7cddfSDavid du Colombier 	return estartfn(key, fd, n, nil);
166*7dd7cddfSDavid du Colombier }
167*7dd7cddfSDavid du Colombier 
168*7dd7cddfSDavid du Colombier ulong
169*7dd7cddfSDavid du Colombier etimer(ulong key, int n)
170*7dd7cddfSDavid du Colombier {
171*7dd7cddfSDavid du Colombier 	char t[2];
172*7dd7cddfSDavid du Colombier 
173*7dd7cddfSDavid du Colombier 	if(Stimer != -1)
174*7dd7cddfSDavid du Colombier 		drawerror(display, "events: timer started twice");
175*7dd7cddfSDavid du Colombier 	Stimer = eforkslave(key);
176*7dd7cddfSDavid du Colombier 	if(Stimer < MAXSLAVE)
177*7dd7cddfSDavid du Colombier 		return 1<<Stimer;
178*7dd7cddfSDavid du Colombier 	if(n <= 0)
179*7dd7cddfSDavid du Colombier 		n = 1000;
180*7dd7cddfSDavid du Colombier 	t[0] = t[1] = Stimer - MAXSLAVE;
181*7dd7cddfSDavid du Colombier 	do
182*7dd7cddfSDavid du Colombier 		sleep(n);
183*7dd7cddfSDavid du Colombier 	while(write(epipe[1], t, 2) == 2);
184*7dd7cddfSDavid du Colombier 	t[0] = MAXSLAVE;
185*7dd7cddfSDavid du Colombier 	write(epipe[1], t, 1);
186*7dd7cddfSDavid du Colombier 	_exits(0);
187*7dd7cddfSDavid du Colombier 	return 0;
188*7dd7cddfSDavid du Colombier }
189*7dd7cddfSDavid du Colombier 
190*7dd7cddfSDavid du Colombier static void
191*7dd7cddfSDavid du Colombier ekeyslave(int fd)
192*7dd7cddfSDavid du Colombier {
193*7dd7cddfSDavid du Colombier 	Rune r;
194*7dd7cddfSDavid du Colombier 	char t[3], k[10];
195*7dd7cddfSDavid du Colombier 	int kr, kn, w;
196*7dd7cddfSDavid du Colombier 
197*7dd7cddfSDavid du Colombier 	if(eforkslave(Ekeyboard) < MAXSLAVE)
198*7dd7cddfSDavid du Colombier 		return;
199*7dd7cddfSDavid du Colombier 	kn = 0;
200*7dd7cddfSDavid du Colombier 	t[0] = Skeyboard;
201*7dd7cddfSDavid du Colombier 	for(;;){
202*7dd7cddfSDavid du Colombier 		while(!fullrune(k, kn)){
203*7dd7cddfSDavid du Colombier 			kr = read(fd, k+kn, sizeof k - kn);
204*7dd7cddfSDavid du Colombier 			if(kr <= 0){
205*7dd7cddfSDavid du Colombier 				t[0] = MAXSLAVE;
206*7dd7cddfSDavid du Colombier 				write(epipe[1], t, 1);
207*7dd7cddfSDavid du Colombier 				_exits(0);
208*7dd7cddfSDavid du Colombier 			}
209*7dd7cddfSDavid du Colombier 			kn += kr;
210*7dd7cddfSDavid du Colombier 		}
211*7dd7cddfSDavid du Colombier 		w = chartorune(&r, k);
212*7dd7cddfSDavid du Colombier 		kn -= w;
213*7dd7cddfSDavid du Colombier 		memmove(k, &k[w], kn);
214*7dd7cddfSDavid du Colombier 		t[1] = r;
215*7dd7cddfSDavid du Colombier 		t[2] = r>>8;
216*7dd7cddfSDavid du Colombier 		write(epipe[1], t, 3);
217*7dd7cddfSDavid du Colombier 	}
218*7dd7cddfSDavid du Colombier }
219*7dd7cddfSDavid du Colombier 
220*7dd7cddfSDavid du Colombier void
221*7dd7cddfSDavid du Colombier einit(ulong keys)
222*7dd7cddfSDavid du Colombier {
223*7dd7cddfSDavid du Colombier 	int ctl, fd;
224*7dd7cddfSDavid du Colombier 	char buf[256];
225*7dd7cddfSDavid du Colombier 
226*7dd7cddfSDavid du Colombier 	parentpid = getpid();
227*7dd7cddfSDavid du Colombier 	if(pipe(epipe) < 0)
228*7dd7cddfSDavid du Colombier 		drawerror(display, "events: einit pipe");
229*7dd7cddfSDavid du Colombier 	atexit(ekill);
230*7dd7cddfSDavid du Colombier 	atnotify(enote, 1);
231*7dd7cddfSDavid du Colombier 	snprint(buf, sizeof buf, "%s/mouse", display->devdir);
232*7dd7cddfSDavid du Colombier 	mousefd = open(buf, ORDWR|OCEXEC);
233*7dd7cddfSDavid du Colombier 	if(mousefd < 0)
234*7dd7cddfSDavid du Colombier 		drawerror(display, "einit: can't open mouse\n");
235*7dd7cddfSDavid du Colombier 	snprint(buf, sizeof buf, "%s/cursor", display->devdir);
236*7dd7cddfSDavid du Colombier 	cursorfd = open(buf, ORDWR|OCEXEC);
237*7dd7cddfSDavid du Colombier 	if(cursorfd < 0)
238*7dd7cddfSDavid du Colombier 		drawerror(display, "einit: can't open cursor\n");
239*7dd7cddfSDavid du Colombier 	if(keys&Ekeyboard){
240*7dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%s/cons", display->devdir);
241*7dd7cddfSDavid du Colombier 		fd = open(buf, OREAD);
242*7dd7cddfSDavid du Colombier 		if(fd < 0)
243*7dd7cddfSDavid du Colombier 			drawerror(display, "events: can't open console");
244*7dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%s/consctl", display->devdir);
245*7dd7cddfSDavid du Colombier 		ctl = open("/dev/consctl", OWRITE|OCEXEC);
246*7dd7cddfSDavid du Colombier 		if(ctl < 0)
247*7dd7cddfSDavid du Colombier 			drawerror(display, "events: can't open consctl");
248*7dd7cddfSDavid du Colombier 		write(ctl, "rawon", 5);
249*7dd7cddfSDavid du Colombier 		for(Skeyboard=0; Ekeyboard & ~(1<<Skeyboard); Skeyboard++)
250*7dd7cddfSDavid du Colombier 			;
251*7dd7cddfSDavid du Colombier 		ekeyslave(fd);
252*7dd7cddfSDavid du Colombier 	}
253*7dd7cddfSDavid du Colombier 	if(keys&Emouse){
254*7dd7cddfSDavid du Colombier 		estart(Emouse, mousefd, 1+4*12);
255*7dd7cddfSDavid du Colombier 		for(Smouse=0; Emouse & ~(1<<Smouse); Smouse++)
256*7dd7cddfSDavid du Colombier 			;
257*7dd7cddfSDavid du Colombier 	}
258*7dd7cddfSDavid du Colombier }
259*7dd7cddfSDavid du Colombier 
260*7dd7cddfSDavid du Colombier static void
261*7dd7cddfSDavid du Colombier extract(void)
262*7dd7cddfSDavid du Colombier {
263*7dd7cddfSDavid du Colombier 	Slave *s;
264*7dd7cddfSDavid du Colombier 	Ebuf *eb;
265*7dd7cddfSDavid du Colombier 	int i, n;
266*7dd7cddfSDavid du Colombier 	uchar ebuf[EMAXMSG+1];
267*7dd7cddfSDavid du Colombier 
268*7dd7cddfSDavid du Colombier 	/* avoid generating a message if there's nothing to show. */
269*7dd7cddfSDavid du Colombier 	/* this test isn't perfect, though; could do flushimage(display, 0) then call extract */
270*7dd7cddfSDavid du Colombier 	/* also: make sure we don't interfere if we're multiprocessing the display */
271*7dd7cddfSDavid du Colombier 	if(display->locking){
272*7dd7cddfSDavid du Colombier 		/* if locking is being done by program, this means it can't depend on automatic flush in emouse() etc. */
273*7dd7cddfSDavid du Colombier 		if(canqlock(&display->qlock)){
274*7dd7cddfSDavid du Colombier 			if(display->bufp > display->buf)
275*7dd7cddfSDavid du Colombier 				flushimage(display, 1);
276*7dd7cddfSDavid du Colombier 			unlockdisplay(display);
277*7dd7cddfSDavid du Colombier 		}
278*7dd7cddfSDavid du Colombier 	}else
279*7dd7cddfSDavid du Colombier 		if(display->bufp > display->buf)
280*7dd7cddfSDavid du Colombier 			flushimage(display, 1);
281*7dd7cddfSDavid du Colombier loop:
282*7dd7cddfSDavid du Colombier 	if((n=read(epipe[0], ebuf, EMAXMSG+1)) < 0
283*7dd7cddfSDavid du Colombier 	|| ebuf[0] >= MAXSLAVE)
284*7dd7cddfSDavid du Colombier 		drawerror(display, "eof on event pipe");
285*7dd7cddfSDavid du Colombier 	if(n == 0)
286*7dd7cddfSDavid du Colombier 		goto loop;
287*7dd7cddfSDavid du Colombier 	i = ebuf[0];
288*7dd7cddfSDavid du Colombier 	if(i >= nslave || n <= 1)
289*7dd7cddfSDavid du Colombier 		drawerror(display, "events: protocol error: short read");
290*7dd7cddfSDavid du Colombier 	s = &eslave[i];
291*7dd7cddfSDavid du Colombier 	if(i == Stimer){
292*7dd7cddfSDavid du Colombier 		s->head = (Ebuf *)1;
293*7dd7cddfSDavid du Colombier 		return;
294*7dd7cddfSDavid du Colombier 	}
295*7dd7cddfSDavid du Colombier 	if(i == Skeyboard && n != 3)
296*7dd7cddfSDavid du Colombier 		drawerror(display, "events: protocol error: keyboard");
297*7dd7cddfSDavid du Colombier 	if(i == Smouse){
298*7dd7cddfSDavid du Colombier 		if(n < 1+1+2*12)
299*7dd7cddfSDavid du Colombier 			drawerror(display, "events: protocol error: mouse");
300*7dd7cddfSDavid du Colombier 		if(ebuf[1] == 'r')
301*7dd7cddfSDavid du Colombier 			eresized(1);
302*7dd7cddfSDavid du Colombier 		/* squash extraneous mouse events */
303*7dd7cddfSDavid du Colombier 		if((eb=s->tail) && memcmp(eb->buf+1+2*12, ebuf+1+1+2*12, 12)==0){
304*7dd7cddfSDavid du Colombier 			memmove(eb->buf, &ebuf[1], n - 1);
305*7dd7cddfSDavid du Colombier 			return;
306*7dd7cddfSDavid du Colombier 		}
307*7dd7cddfSDavid du Colombier 	}
308*7dd7cddfSDavid du Colombier 	/* try to save space by only allocating as much buffer as we need */
309*7dd7cddfSDavid du Colombier 	eb = malloc(sizeof(*eb) - sizeof(eb->buf) + n - 1);
310*7dd7cddfSDavid du Colombier 	if(eb == 0)
311*7dd7cddfSDavid du Colombier 		drawerror(display, "events: protocol error 4");
312*7dd7cddfSDavid du Colombier 	eb->n = n - 1;
313*7dd7cddfSDavid du Colombier 	memmove(eb->buf, &ebuf[1], n - 1);
314*7dd7cddfSDavid du Colombier 	eb->next = 0;
315*7dd7cddfSDavid du Colombier 	if(s->head)
316*7dd7cddfSDavid du Colombier 		s->tail = s->tail->next = eb;
317*7dd7cddfSDavid du Colombier 	else
318*7dd7cddfSDavid du Colombier 		s->head = s->tail = eb;
319*7dd7cddfSDavid du Colombier }
320*7dd7cddfSDavid du Colombier 
321*7dd7cddfSDavid du Colombier static int
322*7dd7cddfSDavid du Colombier eforkslave(ulong key)
323*7dd7cddfSDavid du Colombier {
324*7dd7cddfSDavid du Colombier 	int i, pid;
325*7dd7cddfSDavid du Colombier 
326*7dd7cddfSDavid du Colombier 	for(i=0; i<MAXSLAVE; i++)
327*7dd7cddfSDavid du Colombier 		if((key & ~(1<<i)) == 0 && eslave[i].pid == 0){
328*7dd7cddfSDavid du Colombier 			if(nslave <= i)
329*7dd7cddfSDavid du Colombier 				nslave = i + 1;
330*7dd7cddfSDavid du Colombier 			/*
331*7dd7cddfSDavid du Colombier 			 * share the file descriptors so the last child
332*7dd7cddfSDavid du Colombier 			 * out closes all connections to the window server.
333*7dd7cddfSDavid du Colombier 			 */
334*7dd7cddfSDavid du Colombier 			switch(pid = rfork(RFPROC)){
335*7dd7cddfSDavid du Colombier 			case 0:
336*7dd7cddfSDavid du Colombier 				return MAXSLAVE+i;
337*7dd7cddfSDavid du Colombier 			case -1:
338*7dd7cddfSDavid du Colombier 				fprint(2, "events: fork error\n");
339*7dd7cddfSDavid du Colombier 				exits("fork");
340*7dd7cddfSDavid du Colombier 			}
341*7dd7cddfSDavid du Colombier 			eslave[i].pid = pid;
342*7dd7cddfSDavid du Colombier 			eslave[i].head = eslave[i].tail = 0;
343*7dd7cddfSDavid du Colombier 			return i;
344*7dd7cddfSDavid du Colombier 		}
345*7dd7cddfSDavid du Colombier 	drawerror(display, "events: bad slave assignment");
346*7dd7cddfSDavid du Colombier 	return 0;
347*7dd7cddfSDavid du Colombier }
348*7dd7cddfSDavid du Colombier 
349*7dd7cddfSDavid du Colombier static int
350*7dd7cddfSDavid du Colombier enote(void *v, char *s)
351*7dd7cddfSDavid du Colombier {
352*7dd7cddfSDavid du Colombier 	int i, pid;
353*7dd7cddfSDavid du Colombier 
354*7dd7cddfSDavid du Colombier 	USED(v, s);
355*7dd7cddfSDavid du Colombier 	pid = getpid();
356*7dd7cddfSDavid du Colombier 	if(pid != parentpid)
357*7dd7cddfSDavid du Colombier 		return 1;
358*7dd7cddfSDavid du Colombier 	for(i=0; i<nslave; i++){
359*7dd7cddfSDavid du Colombier 		if(pid == eslave[i].pid)
360*7dd7cddfSDavid du Colombier 			continue;	/* don't kill myself */
361*7dd7cddfSDavid du Colombier 		postnote(PNPROC, eslave[i].pid, "die");
362*7dd7cddfSDavid du Colombier 	}
363*7dd7cddfSDavid du Colombier 	close(epipe[0]);
364*7dd7cddfSDavid du Colombier 	close(epipe[1]);
365*7dd7cddfSDavid du Colombier 	return 0;
366*7dd7cddfSDavid du Colombier }
367*7dd7cddfSDavid du Colombier 
368*7dd7cddfSDavid du Colombier static void
369*7dd7cddfSDavid du Colombier ekill(void)
370*7dd7cddfSDavid du Colombier {
371*7dd7cddfSDavid du Colombier 	enote(0, 0);
372*7dd7cddfSDavid du Colombier }
373*7dd7cddfSDavid du Colombier 
374*7dd7cddfSDavid du Colombier Mouse
375*7dd7cddfSDavid du Colombier emouse(void)
376*7dd7cddfSDavid du Colombier {
377*7dd7cddfSDavid du Colombier 	Mouse m;
378*7dd7cddfSDavid du Colombier 	Ebuf *eb;
379*7dd7cddfSDavid du Colombier 	static but[2];
380*7dd7cddfSDavid du Colombier 	int b;
381*7dd7cddfSDavid du Colombier 
382*7dd7cddfSDavid du Colombier 	if(Smouse < 0)
383*7dd7cddfSDavid du Colombier 		drawerror(display, "events: mouse not initialized");
384*7dd7cddfSDavid du Colombier 	eb = ebread(&eslave[Smouse]);
385*7dd7cddfSDavid du Colombier 	m.xy.x = atoi((char*)eb->buf+1+0*12);
386*7dd7cddfSDavid du Colombier 	m.xy.y = atoi((char*)eb->buf+1+1*12);
387*7dd7cddfSDavid du Colombier 	b = atoi((char*)eb->buf+1+2*12);
388*7dd7cddfSDavid du Colombier 	m.buttons = b&7;
389*7dd7cddfSDavid du Colombier 	m.msec = atoi((char*)eb->buf+1+3*12);
390*7dd7cddfSDavid du Colombier 	if (logfid)
391*7dd7cddfSDavid du Colombier 		fprint(logfid, "b: %d xy: %P\n", m.buttons, m.xy);
392*7dd7cddfSDavid du Colombier 	free(eb);
393*7dd7cddfSDavid du Colombier 	return m;
394*7dd7cddfSDavid du Colombier }
395*7dd7cddfSDavid du Colombier 
396*7dd7cddfSDavid du Colombier int
397*7dd7cddfSDavid du Colombier ekbd(void)
398*7dd7cddfSDavid du Colombier {
399*7dd7cddfSDavid du Colombier 	Ebuf *eb;
400*7dd7cddfSDavid du Colombier 	int c;
401*7dd7cddfSDavid du Colombier 
402*7dd7cddfSDavid du Colombier 	if(Skeyboard < 0)
403*7dd7cddfSDavid du Colombier 		drawerror(display, "events: keyboard not initialzed");
404*7dd7cddfSDavid du Colombier 	eb = ebread(&eslave[Skeyboard]);
405*7dd7cddfSDavid du Colombier 	c = eb->buf[0] + (eb->buf[1]<<8);
406*7dd7cddfSDavid du Colombier 	free(eb);
407*7dd7cddfSDavid du Colombier 	return c;
408*7dd7cddfSDavid du Colombier }
409*7dd7cddfSDavid du Colombier 
410*7dd7cddfSDavid du Colombier void
411*7dd7cddfSDavid du Colombier emoveto(Point pt)
412*7dd7cddfSDavid du Colombier {
413*7dd7cddfSDavid du Colombier 	char buf[2*12+2];
414*7dd7cddfSDavid du Colombier 	int n;
415*7dd7cddfSDavid du Colombier 
416*7dd7cddfSDavid du Colombier 	n = sprint(buf, "m%d %d", pt.x, pt.y);
417*7dd7cddfSDavid du Colombier 	write(mousefd, buf, n);
418*7dd7cddfSDavid du Colombier }
419*7dd7cddfSDavid du Colombier 
420*7dd7cddfSDavid du Colombier void
421*7dd7cddfSDavid du Colombier esetcursor(Cursor *c)
422*7dd7cddfSDavid du Colombier {
423*7dd7cddfSDavid du Colombier 	uchar curs[2*4+2*2*16];
424*7dd7cddfSDavid du Colombier 
425*7dd7cddfSDavid du Colombier 	if(c == 0)
426*7dd7cddfSDavid du Colombier 		write(cursorfd, curs, 0);
427*7dd7cddfSDavid du Colombier 	else{
428*7dd7cddfSDavid du Colombier 		BPLONG(curs+0*4, c->offset.x);
429*7dd7cddfSDavid du Colombier 		BPLONG(curs+1*4, c->offset.y);
430*7dd7cddfSDavid du Colombier 		memmove(curs+2*4, c->clr, 2*2*16);
431*7dd7cddfSDavid du Colombier 		write(cursorfd, curs, sizeof curs);
432*7dd7cddfSDavid du Colombier 	}
433*7dd7cddfSDavid du Colombier }
434*7dd7cddfSDavid du Colombier 
435*7dd7cddfSDavid du Colombier int
436*7dd7cddfSDavid du Colombier ereadmouse(Mouse *m)
437*7dd7cddfSDavid du Colombier {
438*7dd7cddfSDavid du Colombier 	int n;
439*7dd7cddfSDavid du Colombier 	char buf[128];
440*7dd7cddfSDavid du Colombier 
441*7dd7cddfSDavid du Colombier 	do{
442*7dd7cddfSDavid du Colombier 		n = read(mousefd, buf, sizeof(buf));
443*7dd7cddfSDavid du Colombier 		if(n < 0)	/* probably interrupted */
444*7dd7cddfSDavid du Colombier 			return -1;
445*7dd7cddfSDavid du Colombier 		n = eatomouse(m, buf, n);
446*7dd7cddfSDavid du Colombier 	}while(n == 0);
447*7dd7cddfSDavid du Colombier 	return n;
448*7dd7cddfSDavid du Colombier }
449*7dd7cddfSDavid du Colombier 
450*7dd7cddfSDavid du Colombier int
451*7dd7cddfSDavid du Colombier eatomouse(Mouse *m, char *buf, int n)
452*7dd7cddfSDavid du Colombier {
453*7dd7cddfSDavid du Colombier 	if(n != 1+4*12){
454*7dd7cddfSDavid du Colombier 		werrstr("atomouse: bad count");
455*7dd7cddfSDavid du Colombier 		return -1;
456*7dd7cddfSDavid du Colombier 	}
457*7dd7cddfSDavid du Colombier 
458*7dd7cddfSDavid du Colombier 	if(buf[0] == 'r')
459*7dd7cddfSDavid du Colombier 		eresized(1);
460*7dd7cddfSDavid du Colombier 	m->xy.x =  atoi(buf+1+0*12);
461*7dd7cddfSDavid du Colombier 	m->xy.y =  atoi(buf+1+1*12);
462*7dd7cddfSDavid du Colombier 	m->buttons =  atoi(buf+1+2*12);
463*7dd7cddfSDavid du Colombier 	m->msec =  atoi(buf+1+3*12);
464*7dd7cddfSDavid du Colombier 	return n;
465*7dd7cddfSDavid du Colombier }
466