Plan 9 from Bell Labs’s /usr/web/sources/plan9/sys/src/libdraw/event.c

Copyright © 2009 Alcatel-Lucent.
Distributed under the Lucent Public License version 1.02.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <draw.h>
#include <cursor.h>
#include <event.h>

typedef struct	Slave Slave;
typedef struct	Ebuf Ebuf;

struct Slave
{
	int	pid;
	Ebuf	*head;		/* queue of messages for this descriptor */
	Ebuf	*tail;
	int	(*fn)(int, Event*, uchar*, int);
};

struct Ebuf
{
	Ebuf	*next;
	int	n;		/* number of bytes in buf */
	uchar	buf[EMAXMSG];
};

static	Slave	eslave[MAXSLAVE];
static	int	Skeyboard = -1;
static	int	Smouse = -1;
static	int	Stimer = -1;
static	int	logfid;

static	int	nslave;
static	int	parentpid;
static	int	epipe[2];

static	int	eforkslave(ulong);
static	void	extract(void);
static	void	ekill(void);
static	int	enote(void *, char *);

static	int	mousefd;
static	int	cursorfd;

static
Ebuf*
ebread(Slave *s)
{
	Ebuf *eb;
	Dir *d;
	ulong l;

	for(;;){
		d = dirfstat(epipe[0]);
		if(d == nil)
			drawerror(display, "events: eread stat error");
		l = d->length;
		free(d);
		if(s->head && l==0)
			break;
		extract();
	}
	eb = s->head;
	s->head = s->head->next;
	if(s->head == 0)
		s->tail = 0;
	return eb;
}

ulong
event(Event *e)
{
	return eread(~0UL, e);
}

ulong
eread(ulong keys, Event *e)
{
	Ebuf *eb;
	int i, id;

	if(keys == 0)
		return 0;
	for(;;){
		for(i=0; i<nslave; i++)
			if((keys & (1<n;
					if(eslave[i].fn)
						id = (*eslave[i].fn)(id, e, eb->buf, eb->n);
					else
						memmove(e->data, eb->buf, eb->n);
					free(eb);
				}
				return id;
			}
		extract();
	}
}

int
ecanmouse(void)
{
	if(Smouse < 0)
		drawerror(display, "events: mouse not initialized");
	return ecanread(Emouse);
}

int
ecankbd(void)
{
	if(Skeyboard < 0)
		drawerror(display, "events: keyboard not initialzed");
	return ecanread(Ekeyboard);
}

int
ecanread(ulong keys)
{
	Dir *d;
	int i;
	ulong l;

	for(;;){
		for(i=0; i<nslave; i++)
			if((keys & (1<8;
		if(write(epipe[1], t, 3) != 3)
			break;
	}
breakout:;
	t[0] = MAXSLAVE;
	write(epipe[1], t, 1);
	_exits(0);
}

void
einit(ulong keys)
{
	int ctl, fd;
	char buf[256];

	parentpid = getpid();
	if(pipe(epipe) < 0)
		drawerror(display, "events: einit pipe");
	atexit(ekill);
	atnotify(enote, 1);
	snprint(buf, sizeof buf, "%s/mouse", display->devdir);
	mousefd = open(buf, ORDWR|OCEXEC);
	if(mousefd < 0)
		drawerror(display, "einit: can't open mouse\n");
	snprint(buf, sizeof buf, "%s/cursor", display->devdir);
	cursorfd = open(buf, ORDWR|OCEXEC);
	if(cursorfd < 0)
		drawerror(display, "einit: can't open cursor\n");
	if(keys&Ekeyboard){
		snprint(buf, sizeof buf, "%s/cons", display->devdir);
		fd = open(buf, OREAD);
		if(fd < 0)
			drawerror(display, "events: can't open console");
		snprint(buf, sizeof buf, "%s/consctl", display->devdir);
		ctl = open("/dev/consctl", OWRITE|OCEXEC);
		if(ctl < 0)
			drawerror(display, "events: can't open consctl");
		write(ctl, "rawon", 5);
		for(Skeyboard=0; Ekeyboard & ~(1< display->buf)
				flushimage(display, 1);
			unlockdisplay(display);
		}
	}else
		if(display->bufp > display->buf)
			flushimage(display, 1);
loop:
	if((n=read(epipe[0], ebuf, EMAXMSG+1)) < 0
	|| ebuf[0] >= MAXSLAVE)
		drawerror(display, "eof on event pipe");
	if(n == 0)
		goto loop;
	i = ebuf[0];
	if(i >= nslave || n <= 1)
		drawerror(display, "events: protocol error: short read");
	s = &eslave[i];
	if(i == Stimer){
		s->head = (Ebuf *)1;
		return;
	}
	if(i == Skeyboard && n != 3)
		drawerror(display, "events: protocol error: keyboard");
	if(i == Smouse){
		if(n < 1+1+2*12)
			drawerror(display, "events: protocol error: mouse");
		if(ebuf[1] == 'r')
			eresized(1);
		/* squash extraneous mouse events */
		if((eb=s->tail) && memcmp(eb->buf+1+2*12, ebuf+1+1+2*12, 12)==0){
			memmove(eb->buf, &ebuf[1], n - 1);
			return;
		}
	}
	/* try to save space by only allocating as much buffer as we need */
	eb = malloc(sizeof(*eb) - sizeof(eb->buf) + n - 1);
	if(eb == 0)
		drawerror(display, "events: protocol error 4");
	eb->n = n - 1;
	memmove(eb->buf, &ebuf[1], n - 1);
	eb->next = 0;
	if(s->head)
		s->tail = s->tail->next = eb;
	else
		s->head = s->tail = eb;
}

static int
eforkslave(ulong key)
{
	int i, pid;

	for(i=0; i<MAXSLAVE; i++)
		if((key & ~(1<buf[1]<<8);
	free(eb);
	return c;
}

void
emoveto(Point pt)
{
	char buf[2*12+2];
	int n;

	n = sprint(buf, "m%d %d", pt.x, pt.y);
	write(mousefd, buf, n);
}

void
esetcursor(Cursor *c)
{
	uchar curs[2*4+2*2*16];

	if(c == 0)
		write(cursorfd, curs, 0);
	else{
		BPLONG(curs+0*4, c->offset.x);
		BPLONG(curs+1*4, c->offset.y);
		memmove(curs+2*4, c->clr, 2*2*16);
		write(cursorfd, curs, sizeof curs);
	}
}

int
ereadmouse(Mouse *m)
{
	int n;
	char buf[128];

	do{
		n = read(mousefd, buf, sizeof(buf));
		if(n < 0)	/* probably interrupted */
			return -1;
		n = eatomouse(m, buf, n);
	}while(n == 0);
	return n;
}

int
eatomouse(Mouse *m, char *buf, int n)
{
	if(n != 1+4*12){
		werrstr("atomouse: bad count");
		return -1;
	}

	if(buf[0] == 'r')
		eresized(1);
	m->xy.x = atoi(buf+1+0*12);
	m->xy.y = atoi(buf+1+1*12);
	m->buttons = atoi(buf+1+2*12);
	m->msec = atoi(buf+1+3*12);
	return n;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2009 Alcatel-Lucent. All Rights Reserved.
Comments to webmaster@plan9.bell-labs.com.