plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

event.c (7557B)


      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*
     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
     62 event(Event *e)
     63 {
     64 	return eread(~0UL, e);
     65 }
     66 
     67 ulong
     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
    102 ecanmouse(void)
    103 {
    104 	if(Smouse < 0)
    105 		drawerror(display, "events: mouse not initialized");
    106 	return ecanread(Emouse);
    107 }
    108 
    109 int
    110 ecankbd(void)
    111 {
    112 	if(Skeyboard < 0)
    113 		drawerror(display, "events: keyboard not initialzed");
    114 	return ecanread(Ekeyboard);
    115 }
    116 
    117 int
    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
    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
    149 estart(ulong key, int fd, int n)
    150 {
    151 	return estartfn(key, fd, n, nil);
    152 }
    153 
    154 ulong
    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
    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*
    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*
    204 startrpc(int type)
    205 {
    206 	uchar buf[512];
    207 	Wsysmsg w;
    208 
    209 	w.type = type;
    210 	if(convW2M(&w, buf, sizeof buf) == 0)
    211 		return nil;
    212 	return muxrpcstart(display->mux, buf);
    213 }
    214 
    215 static int
    216 finishrpc(Muxrpc *r, Wsysmsg *w)
    217 {
    218 	uchar *p;
    219 	void *v;
    220 	int n;
    221 
    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;
    231 }
    232 
    233 static int
    234 extract(int canblock)
    235 {
    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;
    242 
    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);
    258 		}
    259 	}else
    260 		if(display->bufp > display->buf)
    261 			flushimage(display, 1);
    262 
    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;
    285 			}
    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;
    297 			}
    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;
    306 			}
    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;
    313 		}
    314 	}
    315 
    316 	if(!canblock){
    317 		tv.tv_sec = 0;
    318 		tv.tv_usec = 0;
    319 		timeout = &tv;
    320 	}
    321 
    322 	if(select(max+1, &rset, &wset, &xset, timeout) < 0)
    323 		drawerror(display, "select failure");
    324 
    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++;
    341 			}
    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++;
    348 			}
    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++;
    355 			}
    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++;
    361 			}
    362 		}
    363 	}
    364 	return n;
    365 }
    366 
    367 static int
    368 newkey(ulong key)
    369 {
    370 	int i;
    371 
    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;
    378 		}
    379 	drawerror(display, "events: bad slave assignment");
    380 	return 0;
    381 }
    382 
    383 Mouse
    384 emouse(void)
    385 {
    386 	Mouse m;
    387 	Ebuf *eb;
    388 
    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;
    395 }
    396 
    397 int
    398 ekbd(void)
    399 {
    400 	Ebuf *eb;
    401 	int c;
    402 
    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;
    409 }
    410 
    411 void
    412 emoveto(Point pt)
    413 {
    414 	_displaymoveto(display, pt);
    415 }
    416 
    417 void
    418 esetcursor(Cursor *c)
    419 {
    420 	_displaycursor(display, c, nil);
    421 }
    422 
    423 void
    424 esetcursor2(Cursor *c, Cursor2 *c2)
    425 {
    426 	_displaycursor(display, c, c2);
    427 }
    428 
    429 int
    430 ereadmouse(Mouse *m)
    431 {
    432 	int resized;
    433 
    434 	resized = 0;
    435 	if(_displayrdmouse(display, m, &resized) < 0)
    436 		return -1;
    437 	if(resized)
    438 		eresized(1);
    439 	return 1;
    440 }