/*
 * Window system protocol server.
 * Use select and a single proc and single stack
 * to avoid aggravating the X11 library, which is
 * subtle and quick to anger.
 */

// #define SHOWEVENT

#include <u.h>
#include <sys/select.h>
#include <errno.h>
#ifdef SHOWEVENT
#include <stdio.h>
#endif
#include "x11-inc.h"

#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#include <memlayer.h>
#include <keyboard.h>
#include <mouse.h>
#include <cursor.h>
#include <drawfcall.h>
#include "x11-memdraw.h"
#include "devdraw.h"

#undef time

#define MouseMask (\
	ButtonPressMask|\
	ButtonReleaseMask|\
	PointerMotionMask|\
	Button1MotionMask|\
	Button2MotionMask|\
	Button3MotionMask)

#define Mask MouseMask|ExposureMask|StructureNotifyMask|KeyPressMask|EnterWindowMask|LeaveWindowMask|FocusChangeMask

typedef struct Kbdbuf Kbdbuf;
typedef struct Mousebuf Mousebuf;
typedef struct Fdbuf Fdbuf;
typedef struct Tagbuf Tagbuf;

struct Kbdbuf
{
	Rune r[32];
	int ri;
	int wi;
	int stall;
};

struct Mousebuf
{
	Mouse m[32];
	int ri;
	int wi;
	int stall;
	int resized;
};

struct Tagbuf
{
	int t[32];
	int ri;
	int wi;
};

struct Fdbuf
{
	uchar buf[2*MAXWMSG];
	uchar *rp;
	uchar *wp;
	uchar *ep;
};

Kbdbuf kbd;
Mousebuf mouse;
Fdbuf fdin;
Fdbuf fdout;
Tagbuf kbdtags;
Tagbuf mousetags;

void fdslide(Fdbuf*);
void runmsg(Wsysmsg*);
void replymsg(Wsysmsg*);
void runxevent(XEvent*);
void matchkbd(void);
void matchmouse(void);
int fdnoblock(int);

int chatty;
int drawsleep;
int fullscreen;

Rectangle windowrect;
Rectangle screenrect;

void
usage(void)
{
	fprint(2, "usage: devdraw (don't run directly)\n");
	exits("usage");
}

void
bell(void *v, char *msg)
{
	if(strcmp(msg, "alarm") == 0)
		drawsleep = drawsleep ? 0 : 1000;
	noted(NCONT);
}

void
main(int argc, char **argv)
{
	int n, top, firstx;
	fd_set rd, wr, xx;
	Wsysmsg m;
	XEvent event;

	/*
	 * Move the protocol off stdin/stdout so that
	 * any inadvertent prints don't screw things up.
	 */
	dup(0, 3);
	dup(1, 4);
	close(0);
	close(1);
	open("/dev/null", OREAD);
	open("/dev/null", OWRITE);

	/* reopens stdout if debugging */
	runxevent(0);

	fmtinstall('W', drawfcallfmt);

	ARGBEGIN{
	case 'D':
		chatty++;
		break;
	default:
		usage();
	}ARGEND

	/*
	 * Ignore arguments.  They're only for good ps -a listings.
	 */
	
	notify(bell);

	fdin.rp = fdin.wp = fdin.buf;
	fdin.ep = fdin.buf+sizeof fdin.buf;
	
	fdout.rp = fdout.wp = fdout.buf;
	fdout.ep = fdout.buf+sizeof fdout.buf;

	fdnoblock(3);
	fdnoblock(4);

	firstx = 1;
	_x.fd = -1;
	for(;;){
		/* set up file descriptors */
		FD_ZERO(&rd);
		FD_ZERO(&wr);
		FD_ZERO(&xx);
		/*
		 * Don't read unless there's room *and* we haven't
		 * already filled the output buffer too much.
		 */
		if(fdout.wp < fdout.buf+MAXWMSG && fdin.wp < fdin.ep)
			FD_SET(3, &rd);
		if(fdout.wp > fdout.rp)
			FD_SET(4, &wr);
		FD_SET(3, &xx);
		FD_SET(4, &xx);
		top = 4;
		if(_x.fd >= 0){
			if(firstx){
				firstx = 0;
				XSelectInput(_x.display, _x.drawable, Mask);
			}
			FD_SET(_x.fd, &rd);
			FD_SET(_x.fd, &xx);
			XFlush(_x.display);
			if(_x.fd > top)
				top = _x.fd;
		}

		if(chatty)
			fprint(2, "select %d...\n", top+1);
		/* wait for something to happen */
	    again:
		if(select(top+1, &rd, &wr, &xx, NULL) < 0){
			if(errno == EINTR)
				goto again;
			if(chatty)
				fprint(2, "select failure\n");
			exits(0);
		}
		if(chatty)
			fprint(2, "got select...\n");

		{
			/* read what we can */
			n = 1;
			while(fdin.wp < fdin.ep && (n = read(3, fdin.wp, fdin.ep-fdin.wp)) > 0)
				fdin.wp += n;
			if(n == 0){
				if(chatty)
					fprint(2, "eof\n");
				exits(0);
			}
			if(n < 0 && errno != EAGAIN)
				sysfatal("reading wsys msg: %r");

			/* pick off messages one by one */
			while((n = convM2W(fdin.rp, fdin.wp-fdin.rp, &m)) > 0){
				/* fprint(2, "<- %W\n", &m); */
				runmsg(&m);
				fdin.rp += n;
			}
			
			/* slide data to beginning of buf */
			fdslide(&fdin);
		}
		{
			/* write what we can */
			n = 1;
			while(fdout.rp < fdout.wp && (n = write(4, fdout.rp, fdout.wp-fdout.rp)) > 0)
				fdout.rp += n;
			if(n == 0)
				sysfatal("short write writing wsys");
			if(n < 0 && errno != EAGAIN)
				sysfatal("writing wsys msg: %r");

			/* slide data to beginning of buf */
			fdslide(&fdout);
		}
		{
			/*
			 * Read an X message if we can.
			 * (XPending actually calls select to make sure
			 * the display's fd is readable and then reads
			 * in any waiting data before declaring whether
			 * there are events on the queue.)
			 */
			while(XPending(_x.display)){
				XNextEvent(_x.display, &event);
				runxevent(&event);
			}
		}
	}
}

int
fdnoblock(int fd)
{
	return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
}

void
fdslide(Fdbuf *fb)
{
	int n;

	n = fb->wp - fb->rp;
	if(n > 0)
		memmove(fb->buf, fb->rp, n);
	fb->rp = fb->buf;
	fb->wp = fb->rp+n;
}

void
replyerror(Wsysmsg *m)
{
	char err[256];
	
	rerrstr(err, sizeof err);
	m->type = Rerror;
	m->error = err;
	replymsg(m);
}



/* 
 * Handle a single wsysmsg. 
 * Might queue for later (kbd, mouse read)
 */
void
runmsg(Wsysmsg *m)
{
	uchar buf[65536];
	int n;
	Memimage *i;
	
	switch(m->type){
	case Tinit:
		memimageinit();
		i = _xattach(m->label, m->winsize);
		_initdisplaymemimage(i);
		replymsg(m);
		break;

	case Trdmouse:
		mousetags.t[mousetags.wi++] = m->tag;
		if(mousetags.wi == nelem(mousetags.t))
			mousetags.wi = 0;
		if(mousetags.wi == mousetags.ri)
			sysfatal("too many queued mouse reads");
		/* fprint(2, "mouse unstall\n"); */
		mouse.stall = 0;
		matchmouse();
		break;

	case Trdkbd:
		kbdtags.t[kbdtags.wi++] = m->tag;
		if(kbdtags.wi == nelem(kbdtags.t))
			kbdtags.wi = 0;
		if(kbdtags.wi == kbdtags.ri)
			sysfatal("too many queued keyboard reads");
		kbd.stall = 0;
		matchkbd();
		break;

	case Tmoveto:
		_xmoveto(m->mouse.xy);
		replymsg(m);
		break;

	case Tcursor:
		if(m->arrowcursor)
			_xsetcursor(nil);
		else
			_xsetcursor(&m->cursor);
		replymsg(m);
		break;
			
	case Tbouncemouse:
		_xbouncemouse(&m->mouse);
		replymsg(m);
		break;

	case Tlabel:
		_xsetlabel(m->label);
		replymsg(m);
		break;

	case Trdsnarf:
		m->snarf = _xgetsnarf();
		replymsg(m);
		free(m->snarf);
		break;

	case Twrsnarf:
		_xputsnarf(m->snarf);
		replymsg(m);
		break;

	case Trddraw:
		n = m->count;
		if(n > sizeof buf)
			n = sizeof buf;
		n = _drawmsgread(buf, n);
		if(n < 0)
			replyerror(m);
		else{
			m->count = n;
			m->data = buf;
			replymsg(m);
		}
		break;

	case Twrdraw:
		if(_drawmsgwrite(m->data, m->count) < 0)
			replyerror(m);
		else
			replymsg(m);
		break;
	
	case Ttop:
		_xtopwindow();
		replymsg(m);
		break;
	
	case Tresize:
		_xresizewindow(m->rect);
		replymsg(m);
		break;
	}
}

/*
 * Reply to m.
 */
void
replymsg(Wsysmsg *m)
{
	int n;

	/* T -> R msg */
	if(m->type%2 == 0)
		m->type++;
		
	/* fprint(2, "-> %W\n", m); */
	/* copy to output buffer */
	n = sizeW2M(m);
	if(fdout.wp+n > fdout.ep)
		sysfatal("out of space for reply message");
	convW2M(m, fdout.wp, n);
	fdout.wp += n;
}

/*
 * Match queued kbd reads with queued kbd characters.
 */
void
matchkbd(void)
{
	Wsysmsg m;
	
	if(kbd.stall)
		return;
	while(kbd.ri != kbd.wi && kbdtags.ri != kbdtags.wi){
		m.type = Rrdkbd;
		m.tag = kbdtags.t[kbdtags.ri++];
		if(kbdtags.ri == nelem(kbdtags.t))
			kbdtags.ri = 0;
		m.rune = kbd.r[kbd.ri++];
		if(kbd.ri == nelem(kbd.r))
			kbd.ri = 0;
		replymsg(&m);
	}
}

/*
 * Match queued mouse reads with queued mouse events.
 */
void
matchmouse(void)
{
	Wsysmsg m;
	
	while(mouse.ri != mouse.wi && mousetags.ri != mousetags.wi){
		m.type = Rrdmouse;
		m.tag = mousetags.t[mousetags.ri++];
		if(mousetags.ri == nelem(mousetags.t))
			mousetags.ri = 0;
		m.mouse = mouse.m[mouse.ri];
		m.resized = mouse.resized;
		/*
		if(m.resized)
			fprint(2, "sending resize\n");
		*/
		mouse.resized = 0;
		mouse.ri++;
		if(mouse.ri == nelem(mouse.m))
			mouse.ri = 0;
		replymsg(&m);
	}
}

/*
 * Handle an incoming X event.
 */
void
runxevent(XEvent *xev)
{
	int c;
	KeySym k;
	static Mouse m;

#ifdef SHOWEVENT
	static int first = 1;
	if(first){
		dup(create("/tmp/devdraw.out", OWRITE, 0666), 1);
		setbuf(stdout, 0);
		first = 0;
	}
#endif

	if(xev == 0)
		return;

#ifdef SHOWEVENT
	print("\n");
	ShowEvent(xev);
#endif

	switch(xev->type){
	case Expose:
		_xexpose(xev);
		break;
	
	case DestroyNotify:
		if(_xdestroy(xev))
			exits(0);
		break;

	case ConfigureNotify:
		if(_xconfigure(xev)){
			mouse.resized = 1;
			_xreplacescreenimage();
			goto addmouse;
		}
		break;

	case ButtonPress:
	case ButtonRelease:
	case MotionNotify:
		if(mouse.stall)
			return;
		if(_xtoplan9mouse(xev, &m) < 0)
			return;
	addmouse:
		mouse.m[mouse.wi] = m;
		mouse.wi++;
		if(mouse.wi == nelem(mouse.m))
			mouse.wi = 0;
		if(mouse.wi == mouse.ri){
			mouse.stall = 1;
			mouse.ri = 0;
			mouse.wi = 1;
			mouse.m[0] = m;
			/* fprint(2, "mouse stall\n"); */
		}
		matchmouse();
		break;
	
	case KeyPress:
		if(kbd.stall)
			return;
		XLookupString((XKeyEvent*)xev, NULL, 0, &k, NULL);
		if(k == XK_F11){
			fullscreen = !fullscreen;
			_xmovewindow(fullscreen ? screenrect : windowrect);
			return;
		}
		if((c = _xtoplan9kbd(xev)) < 0)
			return;
		kbd.r[kbd.wi++] = c;
		if(kbd.wi == nelem(kbd.r))
			kbd.wi = 0;
		if(kbd.ri == kbd.wi)
			kbd.stall = 1;
		matchkbd();
		break;
	
	case FocusOut:
		abortcompose();
		break;
	
	case SelectionRequest:
		_xselect(xev);
		break;
	}
}

