Sigrid Solveig Haflínudóttirdon't send over any keys if Kmod4 was used29bc6af4 years agoHistory
433 lines · 7.2 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <draw.h>#include <keyboard.h> typedef struct W W; enum {	Mmod4 = 1<<0,	Mctl = 1<<1,	Mshift = 1<<2, 	Step = 16,	Stepbig = 64, 	Fvisible = 1<<0,	Fcurrent = 1<<1,	Fsticky = 1<<2,	Ffullscreen = 1<<3,}; struct W {	int id;	Rectangle r;	int vd;	int flags;}; static int vd = 1; /* current virtual desktop */static int wsys; /* rios /dev/wsys fd */static int mod;static W *ws, *wcur;static int wsn;static int vd2wcur[10] = {-1}; static char *sticky[32] = {	"bar",	"cat clock",	"clock",	"faces",	"kbmap",	"stats",	"winwatch",	nil,}; static intwwctl(int id, int mode){	char s[64]; 	snprint(s, sizeof(s), "/dev/wsys/%d/wctl", id); 	return open(s, mode);} static voidwsupdate(void){	int i, k, n, f, seen, tn, dsn;	char s[256], *t[8];	W *newws, *w;	Dir *ds, *d; 	seek(wsys, 0, 0);	if((dsn = dirreadall(wsys, &ds)) < 0)		sysfatal("/dev/wsys: %r"); 	newws = malloc(sizeof(W)*dsn);	wcur = nil;	for(i = 0, d = ds, w = newws; i < dsn; i++, d++){		if((f = wwctl(atoi(d->name), OREAD)) < 0)			continue;		n = read(f, s, sizeof(s)-1);		close(f);		if(n < 12)			continue;		s[n] = 0;		if((tn = tokenize(s, t, nelem(t))) < 6)			continue; 		w->id = atoi(d->name);		w->r.min.x = atoi(t[0]);		w->r.min.y = atoi(t[1]);		w->r.max.x = atoi(t[2]);		w->r.max.y = atoi(t[3]);		w->vd = -1;		w->flags = 0; 		/* move over the current state of the window */		for(k = 0, seen = 0; k < wsn; k++){			if(ws[k].id == w->id){				w->vd = ws[k].vd;				w->flags = ws[k].flags & ~(Fvisible|Fcurrent);				if(w->flags & Ffullscreen)					w->r = ws[k].r;				seen = 1;				break;			}		} 		/* update current state */		for(k = 4; k < tn; k++){			if(strcmp(t[k], "current") == 0){				w->flags |= Fcurrent;				wcur = w;				w->vd = vd;			}else if(strcmp(t[k], "visible") == 0){				w->flags |= Fvisible;				w->vd = vd;			}		} 		if(!seen){			/* not seen previously - set the new state for it */			w->vd = vd;		} 		/* because a different program can run in any window we have to re-read */		snprint(s, sizeof(s), "/dev/wsys/%d/label", w->id);		w->flags &= ~Fsticky;		if((f = open(s, OREAD)) >= 0){			n = read(f, s, sizeof(s)-1);			close(f);			if(n > 0){				s[n] = 0;				for(k = 0; k < nelem(sticky) && sticky[k] != nil; k++){					if(strcmp(sticky[k], s) == 0){						w->flags |= Fsticky;						break;					}				}			}		}		w++;	} 	free(ds);	free(ws);	ws = newws;	wsn = w - newws;} static voidspawn(char *s){	if(rfork(RFPROC|RFNOWAIT|RFNAMEG|RFENVG|RFCFDG|RFREND) == 0)		execl("/bin/rc", "rc", s, nil);} static voidtogglefullscreen(void){	int f; 	if(wcur == nil || (f = wwctl(wcur->id, OWRITE)) < 0)		return;	wcur->flags ^= Ffullscreen;	if(wcur->flags & Ffullscreen)		fprint(f, "resize -r 0 0 9999 9999");	else		fprint(f, "resize -r %d %d %d %d", wcur->r.min.x, wcur->r.min.y, wcur->r.max.x, wcur->r.max.y);	close(f);} static voidtogglesticky(void){	if(wcur != nil)		wcur->flags ^= Fsticky;} static voidvdaction(int nvd){	int f, wcurf;	W *w; 	if(mod == Mmod4){		wcur = nil;		wcurf = -1;		vd2wcur[vd] = -1;		for(w = ws; w < ws+wsn; w++){			if((f = wwctl(w->id, OWRITE)) < 0)				continue; 			if(w->flags & Fvisible)				w->vd = vd;			else if(w->vd == vd)				w->vd = -1; 			if(w->flags & Fcurrent)				vd2wcur[vd] = w->id; 			if(w->vd != nvd && (w->flags & Fsticky) == 0){				fprint(f, "hide");			}else{				fprint(f, "unhide");				if(vd2wcur[nvd] == w->id && wcurf < 0){					wcur = w;					wcurf = f;					f = -1;				}			}			if(f >= 0)				close(f);		}		if(wcur != nil){			fprint(wcurf, "top");			fprint(wcurf, "current");			close(wcurf);		}		vd = nvd;		fprint(3, "%d\n", vd);	}else if(mod == (Mmod4 | Mshift) && wcur != nil && wcur->vd != nvd){		if((f = wwctl(wcur->id, OWRITE)) >= 0){			fprint(f, "hide");			wcur->vd = nvd;			vd2wcur[nvd] = wcur->id; /* bring to the top */			wcur = nil;			close(f);		}	}} static voidarrowaction(int x, int y){	int f; 	if(wcur == nil || (f = wwctl(wcur->id, OWRITE)) < 0)		return; 	x *= (mod & Mctl) ? Stepbig : Step;	y *= (mod & Mctl) ? Stepbig : Step;	if((mod & Mshift) == 0)		fprint(f, "move -minx %+d -miny %+d", x, y);	else		fprint(f, "resize -maxx %+d -maxy %+d -minx %+d -miny %+d", x, y, -x, -y);	close(f);} static struct {	int x, y;}cyclectx; static intcyclecmp(void *a_, void *b_){	W *a = a_, *b = b_; 	return cyclectx.x*(a->r.min.x - b->r.min.x) + cyclectx.y*(a->r.min.y - b->r.min.y);} static voidcycleaction(int x, int y){	int wcurid, i, f;	W *w, *w₀; 	wcurid = wcur == nil ? -1 : wcur->id;	cyclectx.x = x;	cyclectx.y = y;	qsort(ws, wsn, sizeof(*ws), cyclecmp);	w₀ = nil;	wcur = nil;	for(i = 0, w = ws; i < wsn; i++, w++){		if(w->id == wcurid){			wcur = w;			continue;		}		if((w->flags & Fsticky) != 0 || w->vd != vd)			continue;		if(w₀ == nil)			w₀ = w;		if(wcur != nil)			break;	}	if(i >= wsn)		w = w₀;	if(w == nil || (f = wwctl(w->id, OWRITE)) < 0)		return;	fprint(f, "top");	fprint(f, "current");	close(f);	wcur = w;} static voidkeyevent(Rune r){	wsupdate(); 	if(r == '\n')		spawn("window");	else if(r == 'f')		togglefullscreen();	else if(r == 's')		togglesticky();	else if(r >= '0' && r <= '9')		vdaction(r - '0');	else if(r == Kup)		arrowaction(0, -1);	else if(r == Kdown)		arrowaction(0, 1);	else if(r == Kleft)		arrowaction(-1, 0);	else if(r == Kright)		arrowaction(1, 0);	else if(r == 'h')		cycleaction(-1, 0);	else if(r == 'l')		cycleaction(1, 0);	else if(r == 'j')		cycleaction(0, 1);	else if(r == 'k')		cycleaction(0, -1);} static voidprocess(char *s){	int n, o, oldmod;	char b[128], *p;	Rune r; 	if(*s == 'K' && s[1] == 0)		mod = 0; 	o = 0;	b[o++] = *s;	for(p = s+1; *p != 0; p += n){		if((n = chartorune(&r, p)) == 1 && r == Runeerror){			/* bail out */			n = strlen(p);			memmove(b+o, p, n);			o += n;			p += n;			break;		} 		oldmod = mod; 		if(*s == 'c' && (mod & Mmod4) != 0){			keyevent(r);			continue;		} 		if(*s == 'k'){			if(r == Kmod4)				mod |= Mmod4;			else if(r == Kctl)				mod |= Mctl;			else if(r == Kshift)				mod |= Mshift;			else if(r >= '0' && r <= '9' && (mod & (Mshift|Mmod4)) == (Mshift|Mmod4))				keyevent(r);		}else if(*s == 'K'){			if(r == Kmod4)				mod &= ~Mmod4;			else if(r == Kctl)				mod &= ~Mctl;			else if(r == Kshift)				mod &= ~Mshift;		} 		if((oldmod | mod) & Mmod4)			continue; 		memmove(b+o, p, n);		o += n;	} 	/* all runes filtered out - ignore completely */	if(o == 1 && p-s > 1)		return; 	b[o++] = 0;	if(write(1, b, o) != o)		exits(nil);} static voidusage(void){	fprint(2, "usage: %s [-s label]\n", argv0);	exits("usage");} voidmain(int argc, char **argv){	char b[128];	int i, j, n; 	for(n = 0; sticky[n] != nil; n++)		; 	ARGBEGIN{	case 's':		if(n >= nelem(sticky))			sysfatal("ewwww");		sticky[n++] = EARGF(usage());		break;	default:		usage();	}ARGEND 	if((wsys = open("/dev/wsys", OREAD)) < 0)		sysfatal("%r"); 	/* initial state */	wsupdate();	for(i = 0; i < wsn; i++)		ws[i].vd = vd;	fprint(3, "%d\n", vd); 	for(i = 0;;){		if((n = read(0, b+i, sizeof(b)-i)) <= 0)			break;		n += i;		for(j = 0; j < n; j++){			if(b[j] == 0){				process(b+i);				i = j+1;			}		}		memmove(b, b+i, j-i);		i -= j;	} 	exits(nil);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t