9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] speaking of screenlock
@ 2021-07-13 14:27 Stuart Morrow
  2021-07-15 21:47 ` [9front] " Stuart Morrow
  0 siblings, 1 reply; 6+ messages in thread
From: Stuart Morrow @ 2021-07-13 14:27 UTC (permalink / raw)
  To: 9front

[-- Attachment #1: Type: text/plain, Size: 713 bytes --]

I noticed (i.e. I failed to notice months ago) that my screenlock
patch causes rio to redraw the green border. An attempt to
getwindow-and-redraw in the topper proc to fix this is attached, but
fails because screen image r is malloc'd. But I am asking for :130,142
to be merged as

1. it kind of fixes this anyway (as popups never happen in practice), and
2. it's just more efficient.

Further thoughts on screenlock: There's actually no need to discover
the screen size using /dev/screen OR /dev/draw - you can just invoke
newwindow with constants (e.g. 0 0 10000 10000) and rio forces it to
the real screen size. But then you're depending on an unmodded rio
with in principle other window managers could exist.

[-- Attachment #2: screenlock.c --]
[-- Type: text/x-csrc, Size: 5269 bytes --]

/* screenlock - lock a terminal */
#include <u.h>
#include <libc.h>
#include <libsec.h>
#include <draw.h>
#include <thread.h>
#include <auth.h>

void redraw(void);
void appendix(void);

char pic[] = "/lib/bunny.bit";
char notice[28+14]; /* KNAMELEN + length of a string */
int debug;
long blank;

void
usage(void)
{
	fprint(2, "usage: %s [-d]\n", argv0);
	exits("usage");
}

/* ^D, Delete, Enter, Backspace, ^U */
void
readline(char *buf, int nbuf)
{
	char c;
	int i;

	i = 0;
	while(i < nbuf-1){
		if(read(0, &c, 1) != 1 || c == '\04' || c == '\177'){
			i = 0;
			break;
		} else if(c == '\n')
			break;
		else if(c == '\b' && i > 0)
			--i;
		else if(c == ('u' & 037))
			i = 0;
		else
			buf[i++] = c;
		blank = time(0);
	}
	buf[i] = '\0';
}

void
checkpassword(void)
{
	char buf[256];
	AuthInfo *ai;

	for(;;){
		memset(buf, 0, sizeof buf);
		readline(buf, sizeof buf);

		border(screen, screen->r, 8, display->white, ZP);
		flushimage(display, 1);

		/* authenticate */
		ai = auth_userpasswd(getuser(), buf);
		if(ai != nil && ai->cap != nil)
			break;

		rerrstr(buf, sizeof buf);
		if(strncmp(buf, "needkey ", 8) == 0)
			break;

		auth_freeAI(ai);
		border(screen, screen->r, 8, display->black, ZP);
		flushimage(display, 1);
	}
	auth_freeAI(ai);
	memset(buf, 0, sizeof buf);
}

void
blanker(void *)
{
	int fd;

	threadsetname("blanker");

	if((fd = open("/dev/mousectl", OWRITE)) < 0)
		return;

	for(;;){
		if(blank != 0 && ((ulong)time(0) - (ulong)blank) >= 5){
			blank = 0;
			write(fd, "blank", 5);
		}
		sleep(1000);
	}
}

void
grabmouse(void*)
{
	int fd, x, y;
	char ibuf[256], obuf[256];

	threadsetname("grabmouse");

	if((fd = open("/dev/mouse", ORDWR)) < 0)
		sysfatal("can't open /dev/mouse: %r");

	snprint(obuf, sizeof obuf, "m %d %d",
		screen->r.min.x + Dx(screen->r)/2,
		screen->r.min.y + Dy(screen->r)/2);

	while(read(fd, ibuf, sizeof ibuf) > 0){
		ibuf[12] = 0;
		ibuf[24] = 0;
		x = atoi(ibuf+1);
		y = atoi(ibuf+13);
		if(x != screen->r.min.x + Dx(screen->r)/2 ||
		   y != screen->r.min.y + Dy(screen->r)/2){
			if(!debug)
				fprint(fd, "%s", obuf);
			blank = time(0);
		}
	}
}

void
top(void*)
{
	int fd, n;
	char buf[128];

	threadsetname("top");

	if((fd = open("/dev/wctl", ORDWR)) < 0)
		return;

	for(;;){
		n = read(fd, buf, sizeof buf);
		if(n > 48)
			if(strstr(buf+48, "notcurrent")){
				write(fd, "current", 7); /* rio redraws border… */
				getwindow(display, 1);
				redraw();
			}
	}
}

void
redraw(void)
{
	int fd, dx, dy;
	static Image *i;
	Point p, q;
	Rectangle r;
	
	screen = _screen->image;	/* fullscreen */

	if(i == nil){
		fd = open(pic, OREAD);
		if(fd >= 0)
			i = readimage(display, fd, 0);
		close(fd);
	}
	if(i != nil){
fprint(2, "_screen"":%p\n", _screen);
fprint(2, "_screen image"":%p\n", _screen->image);
fprint(2, "_screen image r"":%p\n", &_screen->image->r);
 		r = screen->r;
		p = Pt(r.max.x / 2, r.max.y * 2 / 3); 
		dx = (Dx(screen->r) - Dx(i->r)) / 2;
		r.min.x += dx;
		r.max.x -= dx;
		dy = (Dy(screen->r) - Dy(i->r)) / 2;
		r.min.y += dy;
		r.max.y -= dy;
		draw(screen, screen->r, display->black, nil, ZP);
		draw(screen, r, i, nil, i->r.min);
	}

	/* identify the user on screen, centered */
	q = stringsize(font, notice);
	q.x /= 2;
	p = subpt(p, q);

	stringbg(
		screen, p, display->white, ZP, font, notice,
		display->black, ZP
	);

	flushimage(display, 1);
}

void
lockscreen(void)
{
	enum { Cursorlen = 2*4 + 2*2*16 };
	char newcmd[128], cbuf[Cursorlen];
	Rectangle r;
	int fd;
	Tm *tm;

	display = initdisplay(nil, nil, nil);
	if(display == nil)
		sysfatal("can't open /dev/draw: %r");
	r = display->image->r;
	snprint(newcmd, sizeof newcmd, "-r %d %d %d %d",
		r.min.x, r.min.y, r.max.x, r.max.y);
	closedisplay(display);

	newwindow(newcmd);
	
	if((fd = open("/dev/consctl", OWRITE)) >= 0)
		write(fd, "rawon", 5);

	if((fd = open("/dev/cons", OREAD)) < 0)
		sysfatal("can't open cons: %r");
	dup(fd, 0);

	if((fd = open("/dev/cons", OWRITE)) < 0)
		sysfatal("can't open cons: %r");
	dup(fd, 1);
	dup(fd, 2);

	if(initdraw(nil, nil, "screenlock") < 0)
		sysfatal("initdraw failed");
	tm = localtime(time(&blank));
	sprint(notice, "user %s at %d:%02.2d", getuser(), tm->hour, tm->min);
	redraw();

	/* screen is now open and covered.  grab mouse and hold on tight */
	procrfork(top, nil, 8*1024, RFFDG);
	procrfork(grabmouse, nil, 8*1024, RFFDG);
	procrfork(blanker, nil, 8*1024, RFFDG);

	/* clear the cursor */
	if((fd = open("/dev/cursor", OWRITE)) >= 0){
		memset(cbuf, 0, sizeof cbuf);
		write(fd, cbuf, sizeof cbuf);
		/* leave it open */
	}

	/* do the top-getwindow-redraw cycle *here in the main proc*
		to show that it can actuall work */
	// :232 and this call can't be uncommented at the same time - there
	//	can be only one wctl reader
	//appendix();
}

void
threadmain(int argc, char *argv[])
{
	ARGBEGIN{
	case 'd':
		debug++;
		break;
	default:
		usage();
	}ARGEND

	if(argc != 0)
		usage();

	lockscreen();
	checkpassword();
	threadexitsall(nil);
}

void
appendix(void)
{
	int fd;//, n;
//	char buf[128];

	if((fd = open("/dev/wctl", ORDWR)) < 0)
		fprint(2, "%r");

	sleep(1000);
	write(fd, "new echo", 8);
	sleep(1000);
//	if(strstr(buf+48, "notcurrent")){
		write(fd, "current", 7); /* rio redraws border… */
		getwindow(display, 1);
		redraw();
//	}
}

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-07-16 11:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-13 14:27 [9front] speaking of screenlock Stuart Morrow
2021-07-15 21:47 ` [9front] " Stuart Morrow
2021-07-15 23:04   ` ori
2021-07-16  9:07     ` Stuart Morrow
2021-07-16 10:01       ` cinap_lenrek
2021-07-16 10:50         ` Stuart Morrow

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).