⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyboard.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <thread.h>#include <draw.h>#include <mouse.h>#include <keyboard.h>#include <control.h>#include <scribble.h>int debug = 0;typedef struct Win Win;struct Win {	int n;	int dirty;	char *label;	Control *button;};Win *win;int nwin;int mwin;int onwin;int rows, cols;int kbdonly;int scribbleleft;int winshow;Channel *kc;Channel *ec;Channel *tc;Rectangle r, rk, rs, rw;Font *keyfont, *keyctlfont;enum{	Back,	Shade,	Light,	Mask,	Ncol};enum {	kbdheight = 2 + 5*13,};enum {	Keyback		= 0xeeee9eff,	Keyshade		= 0xaaaa55ff,	Keylight		= DWhite,	Keymask		= 0x0C0C0C0C,};Image	*colors[Ncol];Control *kbd;Control *scrib;Control *boxbox;Controlset *cs;int	ctldeletequits = 1;int	wctl;inthidden(void){	char buf[128];	int n;	close(wctl);	if ((wctl = open("/dev/wctl", ORDWR)) < 0)		return 0;	n = read(wctl, buf, sizeof buf-1);	if (n <= 0)		sysfatal("wctl read: %r");	buf[n] = 0;	return strstr(buf, "visible") == nil;}voidmousemux(void *v){	Mouse m;	Channel *c;	int ob;	c = v;	for(ob = 0;;ob = m.buttons){		if(recv(c, &m) < 0)			break;		if ((m.buttons & 0x20) == 0) {			if (ob & 0x20) {				/* hide button just came up */				if (hidden()) {					if (debug) fprint(2, "unhide");					if (fprint(wctl, "unhide") <= 0)						fprint(2, "unhide failed: %r\n");				} else {					if (debug) fprint(2, "hide");					if (fprint(wctl, "hide") <= 0)						fprint(2, "hide failed: %r\n");				}			} else				send(cs->mousec, &m);		}	}}voidrefreshwin(void){	char label[128];	int i, fd, lfd, n, nr, nw, m;	Dir *pd;	if((fd = open("/dev/wsys", OREAD)) < 0)		return;	nw = 0;/* i'd rather read one at a time but rio won't let me */	while((nr=dirread(fd, &pd)) > 0){		for(i=0; i<nr; i++){			n = atoi(pd[i].name);			sprint(label, "/dev/wsys/%d/label", n);			if((lfd = open(label, OREAD)) < 0)				continue;			m = read(lfd, label, sizeof(label)-1);			close(lfd);			if(m < 0)				continue;			label[m] = '\0';			if(nw < nwin && win[nw].n == n && strcmp(win[nw].label, label)==0){				nw++;				continue;			}			if(nw < nwin){				free(win[nw].label);				win[nw].label = nil;			}			if(nw >= mwin){				mwin += 8;				win = ctlrealloc(win, mwin*sizeof(win[0]));				memset(&win[mwin-8], 0, 8*sizeof(win[0]));			}			win[nw].n = n;			win[nw].label = ctlstrdup(label);			win[nw].dirty = 1;			sprint(label, "%d", nw);			if (win[nw].button == nil){				win[nw].button = createtextbutton(cs, label);				chanprint(cs->ctl, "%q font keyfont", label);				chanprint(cs->ctl, "%q image keyback", label);				chanprint(cs->ctl, "%q pressedtextcolor red", label);				chanprint(cs->ctl, "%q mask transparent", label);				chanprint(cs->ctl, "%q border 1", label);				chanprint(cs->ctl, "%q bordercolor black", label);				chanprint(cs->ctl, "%q align centerleft", label);				chanprint(cs->ctl, "%q size 16 %d 512 %d", label, keyfont->height+2, keyfont->height+2);				controlwire(win[nw].button, "event", ec);			}			if (nw >= nwin){				activate(win[nw].button);				chanprint(cs->ctl, "cols add %q", label);			}			chanprint(cs->ctl, "%q text %q", win[nw].button->name, win[nw].label);			nw++;		}	}	for(i = nw; i < nwin; i++){		free(win[i].label);		win[i].label = nil;		deactivate(win[i].button);		chanprint(cs->ctl, "cols remove %q", win[i].button->name);	}	nwin = nw;	close(fd);	if (rw.max.x)		chanprint(cs->ctl, "cols rect %R\ncols show", rw);}voidresizecontrolset(Controlset*){	int fd;	char buf[61];	if(getwindow(display, Refnone) < 0)		ctlerror("resize failed: %r");	if (hidden()) {		if (debug) fprint(2, "resizecontrolset: hidden\n");		return;	}	fd = open("/dev/screen", OREAD);	if (fd < 0) {		r = display->image->r;		if (debug) fprint(2, "display->imgae->r: %R\n", r);	} else {		if (read(fd, buf, 60) != 60)			sysfatal("resizecontrolset: read: /dev/screen: %r");		close(fd);		buf[60] = '\0';		r.min.x = atoi(buf+1+1*12);		r.min.y = atoi(buf+1+2*12);		r.max.x = atoi(buf+1+3*12);		r.max.y = atoi(buf+1+4*12);		if (debug) fprint(2, "/dev/screen: %R\n", r);	}	r = insetrect(r, 4);	r.min.y = r.max.y - kbdheight - 2*Borderwidth;	if (debug) fprint(2, "before eqrect: %R\n", r);	if (eqrect(r, screen->r) == 0) {		if (debug) fprint(2, "resizecontrolset: resize %R\n", r);		if (fprint(wctl, "resize -r %R", insetrect(r, -4)) <= 0) {			fprint(2, "resizecontrolset: resize failed\n");		}		return;	}	if (debug) fprint(2, "after eqrect: %R\n", r);	rk = r;	if (winshow){		rw = rk;		rw.min.x = (3*rk.max.x + rk.min.x)/4;		rk.max.x = rw.min.x;		if (debug) fprint(2, "rw: rect %R\n", rw);		chanprint(cs->ctl, "cols rect %R\ncols show", rw);	}	if (kbdonly) {		chanprint(cs->ctl, "keyboard rect %R\nkeyboard show", rk);	} else {		rs = rk;		if (scribbleleft){			rk.min.x = (rk.max.x + 3*rk.min.x)/4;			rs.max.x = rk.min.x;		}else{			rk.max.x = (3*rk.max.x + rk.min.x)/4;			rs.min.x = rk.max.x;		}		chanprint(cs->ctl, "keyboard rect %R\nkeyboard show", rk);		if (debug) fprint(2, "rk: rect %R\nkeyboard show\n", rk);		chanprint(cs->ctl, "scribble rect %R\nscribble show", rs);		if (debug) fprint(2, "rs: rect %R\nscribble show\n", rs);	}}voidusage(void){	fprint(2, "usage: keyboard\n");	threadexitsall("usage");}voidtimerproc(void*v){	Channel *c;	c = v;	for(;;){		sleep(5000);		sendul(c, 1);	}}voidwatchproc(void*){	for(;;){}}voidthreadmain(int argc, char *argv[]){	int i, n, kbdfd;	char str[UTFmax+1];	Rune r;	Mousectl	*mousectl;	Channel *mtok;	char *e, buf[128], *args[8];	int fd;	ARGBEGIN{	case 'w':		winshow++;		break;	case 'l':		scribbleleft++;		break;	case 'n':		kbdonly++;		break;	case 'd':		ScribbleDebug++;		debug++;		break;	default:		usage();	}ARGEND	if(argc != 0)		usage();	kbdfd = open("/dev/kbdin", OWRITE);	if (kbdfd < 0 && (kbdfd = open("#r/kbdin", OWRITE)) < 0) {		if (debug) fprint(2, "open %s: %r\n", "#r/kbdin");		kbdfd = 1;	}	initdraw(0, 0, "keyboard");	mousectl = initmouse(nil, screen);	wctl = open("/dev/wctl", ORDWR);	if (wctl < 0) {		fprint(2, "open %s: %r\n", "/dev/wctl");		wctl = 2;	/* for debugging */	}	mtok = chancreate(sizeof(Mouse), 0);	initcontrols();	cs = newcontrolset(screen, nil, mtok, mousectl->resizec);	threadcreate(mousemux, mousectl->c, 4096);	kc = chancreate(sizeof(char*), 0);	tc = chancreate(sizeof(int), 1);	ec = chancreate(sizeof(char*), 1);	colors[Back] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyback);	namectlimage(colors[Back], "keyback");	colors[Light] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keylight);	namectlimage(colors[Light], "keylight");	colors[Shade] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyshade);	namectlimage(colors[Shade], "keyshade");	colors[Mask] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, Keymask);	namectlimage(colors[Shade], "keymask");	keyfont = openfont(display, "/lib/font/bit/lucidasans/boldlatin1.6.font");	namectlfont(keyfont, "keyfont");	keyctlfont = openfont(display, "/lib/font/bit/lucidasans/unicode.6.font");	namectlfont(keyctlfont, "keyctlfont");	kbd = createkeyboard(cs, "keyboard");	chanprint(cs->ctl, "keyboard font keyfont keyctlfont");	chanprint(cs->ctl, "keyboard image keyback");	chanprint(cs->ctl, "keyboard light keylight");	chanprint(cs->ctl, "keyboard mask keymask");	chanprint(cs->ctl, "keyboard border 1");	chanprint(cs->ctl, "keyboard size %d %d %d %d", 246, 2 + 5 * (keyfont->height + 1), 512, 256);	controlwire(kbd, "event", kc);	if (kbdonly == 0){		scrib = createscribble(cs, "scribble");		if (scrib == nil)			sysfatal("createscribble");		chanprint(cs->ctl, "scribble font keyfont");		chanprint(cs->ctl, "scribble image keyback");		chanprint(cs->ctl, "scribble border 1");		controlwire(scrib, "event", kc);	}	if (winshow){		boxbox = createboxbox(cs, "cols");			chanprint(cs->ctl, "cols border 2");		chanprint(cs->ctl, "cols bordercolor keyback");	}	resizecontrolset(nil);	activate(kbd);	if (kbdonly == 0)		activate(scrib);	if (winshow){		refreshwin();		proccreate(timerproc, tc, 2048);	}	for(;;){		Alt a[] = {			{ kc, &e, CHANRCV },			{ ec, &e, CHANRCV },			{ tc, &n, CHANRCV },			{ nil, nil, CHANEND }		};		switch(alt(a)){		case 0:	/* Keyboard */			n = tokenize(e, args, nelem(args));			if(n == 3)			if(strcmp(args[0], "keyboard:")==0 || strcmp(args[0], "scribble:")==0)			if(strcmp(args[1], "value") == 0){				n = atoi(args[2]);				if(n <= 0xFFFF){					r = n;					i = runetochar(str, &r);					write(kbdfd, str, i);				}			}			break;		case 1:	/* Button event */			n = tokenize(e, args, nelem(args));			if (n != 3 || strcmp(args[1], "value"))				sysfatal("event string");			i = atoi(args[0]);			if (i < 0 || i >= nwin)				sysfatal("win out of range: %d of %d", i, nwin);			n = atoi(args[2]);			if (n){				sprint(buf, "/dev/wsys/%d/wctl", win[i].n);				if((fd = open(buf, OWRITE)) >= 0){					while (write(fd, "top\n", 4) < 0) {						/* wait until mouse comes up */						rerrstr(buf, sizeof buf);						if (strncmp(buf, "action disallowed when mouse active", sizeof buf)){							fprint(2, "write top: %s\n", buf);							break;						}						sleep(100);					}					if (write(fd, "current\n", 8) < 0)						fprint(2, "write current: %r\n");					close(fd);				}				chanprint(cs->ctl, "%q value 0", win[i].button->name);			}			break;		case 2:			refreshwin();			break;		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -