#include "i.h" // globals Rectangle rmain; Rectangle rctl; Rectangle rprog; static void setwinrects(int new); static void rawkeyboard(void* arg); static void rawmouse(void* arg); static int sendevmouse(int x, int y, int mtype); enum { CTLHEIGHT = 65, // height of control (menu and toolbar) window PROGHEIGHT = 24, // height of progress window NCLIPR = 10, }; static Rectangle cliprstack[NCLIPR]; static int nclipr; void guiinit(void) { setwinrects(0); if(proccreate(rawmouse, nil, STACKSIZESMALL) < 0) fatalerror("can't create io procs"); if(proccreate(rawkeyboard, nil, STACKSIZESMALL) < 0) fatalerror("can't create io procs"); } static void setwinrects(int new) { int x,y,w,h; // Refnone ok because rio backs up our window if(new && getwindow(display, Refnone) < 0) fatalerror("can't reattach to window"); // pay no attention to config values of x,y,defaultwidth,defaultheight, // since the user has swept the area for i x = screen->r.min.x; y = screen->r.min.y; w = Dx(screen->r); h = Dy(screen->r); if(w < 150 || h < CTLHEIGHT+PROGHEIGHT+100) fatalerror("window too small"); rctl = Rect(x, y, x + w, y + CTLHEIGHT); rmain = Rect(x, y + CTLHEIGHT, x + w, y + h); rprog = Rect(x, rmain.max.y, x + w, rmain.max.y); if(config.showprogress) { rmain.max.y -= PROGHEIGHT; rprog.min.y -= PROGHEIGHT; } nclipr = 0; cliprstack[nclipr++] = screen->clipr; } // Change screen's clipr to r, saving old value in clipr stack void pushclipr(Rectangle r) { assert(nclipr < NCLIPR); cliprstack[nclipr++] = screen->clipr; replclipr(screen, 0, r); } // Replace screen's clipr to r, without changing clipr stack void replaceclipr(Rectangle r) { replclipr(screen, 0, r); } // Restore screen's clipr to saveclipr void popclipr() { assert(nclipr > 0); replclipr(screen, 0, cliprstack[--nclipr]); } Image* makepopup(int width, int height) { int x; int y; Rectangle r; Image* popupwin; x = rmain.min.x + (Dx(rmain) - width)/2; if(x < 0) x = 0; y = rmain.min.y + (Dy(rmain) - height)/2; if(y < 0) y = 0; r = Rect(x, y, x + width, y + height); popupwin = allocwindow(screen->screen, r, Refbackup, DGrey); return popupwin; } static void rawkeyboard(void* arg) { int fd; int ctl; int i; Rune r; int n; int k; int nutf; EV ev; char buf[10]; USED(arg); meminit(GRnone); fd = open("/dev/cons", OREAD); ctl = open("/dev/consctl", OWRITE|OCEXEC); if(fd < 0 || ctl < 0) fatalerror("can't open raw console"); write(ctl, "rawon", 5); i = 0; while(1) { n = read(fd, buf+i, sizeof(buf) - i); if(n < 1) break; i += n; while(i > 0 && fullrune(buf, i)) { nutf = chartorune(&r, buf); k = r; switch(k) { case 128: k = Kdown; break; case 206: k = Kup; break; case 205: k = Khome; break; } ev = evkey(k); if(send(evchan, &ev) < 0) return; memmove(buf, buf+nutf, i-nutf); i -= nutf; } } } static void rawmouse(void* arg) { int fd; int n; int xold; int yold; int bold; int x; int y; int b; int domoved; EV ev; char buf[1+4*12]; USED(arg); meminit(GRnone); fd = open("/dev/mouse", OREAD); if(fd < 0) fatalerror("no mouse"); xold = -1; yold = -1; bold = 0; while(1) { n = read(fd, buf, sizeof(buf)); if(n <= 0) break; if(buf[0] == 'r') { setwinrects(1); ev.tag = EVresizetag; if(send(evchan, &ev) < 0) return; continue; } if(buf[0] != 'm' || n != sizeof(buf)) continue; x = atoi(buf+1+0*12); y = atoi(buf+1+1*12); b = (atoi(buf+1+2*12))&7; domoved = (x != xold || y != yold); if(b == 0) { if(bold&1) if(sendevmouse(xold, yold, Mlbuttonup) < 0) return; if(bold&2) if(sendevmouse(xold, yold, Mmbuttonup) < 0) return; if(bold&4) if(sendevmouse(xold, yold, Mrbuttonup) < 0) return; } else { if(b&1) { if(bold&1) { if(sendevmouse(x, y, Mldrag) < 0) return; domoved = 0; } else { if(domoved) { if(sendevmouse(x, y, Mmove) < 0) return; domoved = 0; } if(sendevmouse(x, y, Mlbuttondown) < 0) return; } } if(b&2) { if(bold&2) { if(sendevmouse(x, y, Mmdrag) < 0) return; domoved = 0; } else { if(domoved) { if(sendevmouse(x, y, Mmove) < 0) return; domoved = 0; } if(sendevmouse(x, y, Mmbuttondown) < 0) return; } } if(b&4) { if(bold&4) { if(sendevmouse(x, y, Mrdrag) < 0) return; domoved = 0; } else { if(domoved) { if(sendevmouse(x, y, Mmove) < 0) return; domoved = 0; } if(sendevmouse(x, y, Mrbuttondown) < 0) return; } } } if(domoved) if(sendevmouse(x, y, Mmove) < 0) return; xold = x; yold = y; bold = b; } } static int sendevmouse(int x, int y, int mtype) { EV ev; ev = evmouse(Pt(x,y), mtype); return send(evchan, &ev); }