#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);
}
|