9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] hidpi
@ 2021-12-20 16:13 Philip Silva
  2021-12-20 16:34 ` hiro
                   ` (3 more replies)
  0 siblings, 4 replies; 19+ messages in thread
From: Philip Silva @ 2021-12-20 16:13 UTC (permalink / raw)
  To: 9front

I've been creating patches to enable hidpi to make scrollbars bigger when using > 100 dpi. It's basically 3 patches: 1st one for adding int displaydpi, 2nd one for adding an entry to plan9.ini and a 3rd very experimental one that changes scrollbar and border widths including some glitches. (And a 4th one that hardcodes 200 dpi in drawterm-metal-cocoa) The extra fields and most code is just copied from plan9port. (d0e0701, c96d832) I'm using this since a few months now and it works, the only problems I had:

- system wouldn't boot anymore when only applying the libdraw part of the 1st patch (I fixed that and checked in a fresh install in a VM that it would just ignore when the new draw command q1d isn't present in devdraw)
- glitches: the borders aren't calculated correctly (3rd patch for rio and acme is very wip)
- despite the glitches it works reasonably well with acme and rio but some applications are quite small then. Not sure how much effort it would be to patch for compat. with dpi != 100

There is also the field forcedpi that is left largely ignored but generally is supposed to override displaydpi when necessary.

Greetings, Philip


--


1st Patch for libdraw and devdraw:

diff c7dcc82b0be805717efbe77c98eaadf3ee1e31af uncommitted
--- a/sys/include/ape/draw.h
+++ b/sys/include/ape/draw.h
@@ -208,6 +208,7 @@
 	Image		*windows;
 	Image		*screenimage;
 	int			_isnewdisplay;
+	int			dpi;
 };

 struct Image
--- a/sys/include/draw.h
+++ b/sys/include/draw.h
@@ -200,6 +200,7 @@
 	Image		*windows;
 	Image		*screenimage;
 	int		_isnewdisplay;
+	int		dpi;
 };

 struct Image
--- a/sys/src/9/port/devdraw.c
+++ b/sys/src/9/port/devdraw.c
@@ -77,6 +77,8 @@
 	int		refreshme;
 	int		infoid;
 	int		op;
+	int		displaydpi;
+	int		forcedpi;
 };

 struct Refresh
@@ -785,6 +789,7 @@
 	cl->slot = i;
 	cl->clientid = ++sdraw.clientid;
 	cl->op = SoverD;
+	cl->displaydpi=100;
 	sdraw.client[i] = cl;
 	return cl;
 }
@@ -1396,6 +1401,7 @@
 	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
 	uchar *u, *a, refresh;
 	char *fmt;
+	Fmt f;
 	ulong value, chan;
 	Rectangle r, clipr;
 	Point p, q, *pp, sp;
@@ -1643,6 +1649,35 @@
 			font->nfchar = ni;
 			font->ascent = a[9];
 			continue;
+
+		/* query: 'Q' n[1] queryspec[n] */
+		case 'q':
+			if(n < 2){
+				error(Eshortdraw);
+			}
+			m = 1+1+a[1];
+			if(n < m){
+				error(Eshortdraw);
+			}
+			fmtstrinit(&f);
+			for(c=0; c<a[1]; c++){
+				switch(a[2+c]){
+				default:
+					error("unknown query");
+				case 'd':       /* dpi */
+					if(client->forcedpi)
+						fmtprint(&f, "%11d ", client->forcedpi);
+					else
+						fmtprint(&f, "%11d ", client->displaydpi);
+					break;
+				}
+			}
+			client->readdata = (uchar*)fmtstrflush(&f);
+			if(client->readdata == nil)
+				error(Enomem);
+			client->nreaddata = strlen((char*)client->readdata);
+			continue;
+

 		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
 		case 'l':
--- a/sys/src/libdraw/init.c
+++ b/sys/src/libdraw/init.c
@@ -197,6 +197,7 @@
 Display*
 initdisplay(char *dev, char *win, void(*error)(Display*, char*))
 {
+	uchar *a;
 	char buf[128], info[NINFO+1], *t, isnew;
 	int n, datafd, ctlfd, reffd;
 	Display *disp;
@@ -319,6 +320,18 @@
 	if(dir!=nil && dir->qid.vers==1)	/* other way to tell */
 		disp->_isnewdisplay = 1;
 	free(dir);
+
+	a = bufimage(disp, 3);
+	if(a == nil)
+		goto Error5;
+	a[0] = 'q';
+	a[1] = 1;
+	a[2] = 'd';
+	disp->dpi = 100;
+	if(flushimage(disp, 0) >= 0){
+		if((read(datafd, info, sizeof info)) == 12)
+			disp->dpi = atoi(info);
+	}

 	return disp;
 }

--

2nd Patch for plan9.ini:

diff c7dcc82b0be805717efbe77c98eaadf3ee1e31af uncommitted
--- a/sys/man/8/plan9.ini
+++ b/sys/man/8/plan9.ini
@@ -971,6 +971,8 @@
 .BR off .
 The first two specify differing levels of power saving;
 the third turns the monitor off completely.
+.SS \fL*dpi=\fIvalue\fP
+This is used to specify the screen dpi.
 .SS NVRAM
 .SS \fLnvram=\fIfile\fP
 .SS \fLnvrlen=\fIlength\fP
--- a/sys/src/9/port/devdraw.c
+++ b/sys/src/9/port/devdraw.c
@@ -765,6 +765,7 @@
 drawnewclient(void)
 {
 	Client *cl, **cp;
+	char *p;
 	int i;

 	for(i=0; i<sdraw.nclient; i++){
@@ -789,7 +790,9 @@
 	cl->slot = i;
 	cl->clientid = ++sdraw.clientid;
 	cl->op = SoverD;
-	cl->displaydpi=100;
+	if((p = getconf("dpi")) == nil || (cl->displaydpi = atoi(p)) == 0){
+		cl->displaydpi=100;
+	}
 	sdraw.client[i] = cl;
 	return cl;
 }

--

3rd Patch for rio/acme (proof-of-concept, just to provide an example)

diff 75d8e460a00505c2b21a0d06ceb4300c93d9c4d6 uncommitted
--- a/sys/include/ape/draw.h
+++ b/sys/include/ape/draw.h
@@ -69,6 +69,7 @@
 	Displaybufsize	= 8000,
 	ICOSSCALE	= 1024,
 	Borderwidth =	4,
+	DefaultDPI  =	100,
 };

 enum
@@ -358,6 +359,7 @@
 extern Image*	namedimage(Display*, char*);
 extern int	nameimage(Image*, char*, int);
 extern Image* allocimagemix(Display*, ulong, ulong);
+extern int scalesize(Display*, int);

 /*
  * Colors
--- a/sys/include/draw.h
+++ b/sys/include/draw.h
@@ -61,6 +61,7 @@
 	Displaybufsize	= 8000,
 	ICOSSCALE	= 1024,
 	Borderwidth =	4,
+	DefaultDPI  =	100,
 };

 enum
@@ -354,6 +355,7 @@
 extern Image*	namedimage(Display*, char*);
 extern int	nameimage(Image*, char*, int);
 extern Image* allocimagemix(Display*, ulong, ulong);
+extern int scalesize(Display*, int);

 /*
  * Colors
--- a/sys/src/cmd/acme/dat.h
+++ b/sys/src/cmd/acme/dat.h
@@ -473,11 +473,14 @@
 	BUFSIZE = Maxblock+IOHDRSZ,	/* size from fbufalloc() */
 	RBUFSIZE = BUFSIZE/sizeof(Rune),
 	EVENTSIZE = 256,
-	Scrollwid = 12,	/* width of scroll bar */
-	Scrollgap = 4,	/* gap right of scroll bar */
-	Margin = 4,	/* margin around text */
-	Border = 2,	/* line between rows, cols, windows */
 };
+
+// like in p9p c96d832
+#define Scrollwid scalesize(display, 12)	/* width of scroll bar */
+#define Scrollgap scalesize(display, 4)	/* gap right of scroll bar */
+#define Margin scalesize(display, 4)	/* margin around text */
+#define Border scalesize(display, 2)	/* line between rows, cols, windows */
+#define ButtonBorder scalesize(display, 2)

 #define	QID(w,q)	((w<<8)|(q))
 #define	WIN(q)	((((ulong)(q).path)>>8) & 0xFFFFFF)
--- a/sys/src/cmd/rio/wind.c
+++ b/sys/src/cmd/rio/wind.c
@@ -12,6 +12,14 @@
 #include "dat.h"
 #include "fns.h"

+static int
+wscale(Window *w, int n)
+{
+        if(w == nil || w->i == nil)
+                return n;
+        return scalesize(w->i->display, n);
+}
+
 Window*
 wlookid(int id)
 {
@@ -308,7 +316,7 @@
 		else
 			col = lighttitlecol;
 	}
-	border(w->i, w->i->r, Selborder, col, ZP);
+	border(w->i, w->i->r, wscale(w, Selborder), col, ZP);
 }

 static void
@@ -353,17 +361,17 @@

 	w->i = i;
 	w->mc.image = i;
-	r = insetrect(i->r, Selborder+1);
+	r = insetrect(i->r, wscale(w, Selborder)+wscale(w, 1));
 	w->scrollr = r;
-	w->scrollr.max.x = r.min.x+Scrollwid;
+	w->scrollr.max.x = r.min.x+wscale(w, Scrollwid);
 	w->lastsr = ZR;
-	r.min.x += Scrollwid+Scrollgap;
+	r.min.x += wscale(w, Scrollwid)+wscale(w, Scrollgap);
 	frclear(w, FALSE);
 	frinit(w, r, w->font, w->i, cols);
 	wsetcols(w, w == input);
 	w->maxtab = maxtab*stringwidth(w->font, "0");
 	if(!w->mouseopen || !w->winnameread){
-		r = insetrect(w->i->r, Selborder);
+		r = insetrect(w->i->r, wscale(w, Selborder));
 		draw(w->i, r, cols[BACK], nil, w->entire.min);
 		wfill(w);
 		wsetselect(w, w->q0, w->q1);
@@ -370,7 +378,7 @@
 		wscrdraw(w);
 	}
 	if(w == input)
-		wborder(w, Selborder);
+		wborder(w, wscale(w, Selborder));
 	else
 		wborder(w, Unselborder);
 	flushimage(display, 1);
@@ -390,9 +398,9 @@
 	if(!w->mouseopen || !w->winnameread)
 		frredraw(w);
 	if(w == input)
-		wborder(w, Selborder);
+		wborder(w, wscale(w, Selborder));
 	else
-		wborder(w, Unselborder);
+		wborder(w, wscale(w, Unselborder));
 }

 static void
@@ -401,9 +409,9 @@
 	Rectangle r;

 	if(w == input)
-		wborder(w, Selborder);
+		wborder(w, wscale(w, Selborder));
 	else
-		wborder(w, Unselborder);
+		wborder(w, wscale(w, Unselborder));
 	r = insetrect(w->i->r, Selborder);
 	draw(w->i, r, w->cols[BACK], nil, w->entire.min);
 	wfill(w);
@@ -1249,7 +1257,7 @@

 	w = emalloc(sizeof(Window));
 	w->screenr = i->r;
-	r = insetrect(i->r, Selborder+1);
+	r = insetrect(i->r, wscale(w, Selborder)+wscale(w, 1));
 	w->i = i;
 	w->mc = *mc;
 	w->ck = ck;
@@ -1263,9 +1271,9 @@
 	w->complete = chancreate(sizeof(Completion*), 0);
 	w->gone = chancreate(sizeof(char*), 0);
 	w->scrollr = r;
-	w->scrollr.max.x = r.min.x+Scrollwid;
+	w->scrollr.max.x = r.min.x+wscale(w, Scrollwid);
 	w->lastsr = ZR;
-	r.min.x += Scrollwid+Scrollgap;
+	r.min.x += wscale(w, Scrollwid)+wscale(w, Scrollgap);
 	frinit(w, r, font, i, cols);
 	w->maxtab = maxtab*stringwidth(font, "0");
 	w->topped = ++topped;
@@ -1274,9 +1282,9 @@
 	w->scrolling = scrolling;
 	w->dir = estrdup(startdir);
 	w->label = estrdup("<unnamed>");
-	r = insetrect(w->i->r, Selborder);
+	r = insetrect(w->i->r, wscale(w, Selborder));
 	draw(w->i, r, cols[BACK], nil, w->entire.min);
-	wborder(w, Selborder);
+	wborder(w, wscale(w, Selborder));
 	wscrdraw(w);
 	incref(w);	/* ref will be removed after mounting; avoids delete before ready to be deleted */
 	return w;
--- a/sys/src/libdraw/init.c
+++ b/sys/src/libdraw/init.c
@@ -452,5 +465,13 @@
 	p = d->bufp;
 	d->bufp += n;
 	return p;
+}
+
+int
+scalesize(Display *d, int n)
+{
+	if(d == nil || d->dpi <= DefaultDPI)
+		return n;
+	return (n*d->dpi+DefaultDPI/2)/DefaultDPI;
 }

--

4th Patch (drawterm-metal-cocoa - I've been using this most of the time):

diff 0b7990cf2b84e7a80cf3f3a9e7eadca10d51a2c5 uncommitted
--- a/include/draw.h
+++ b/include/draw.h
@@ -193,6 +193,7 @@
 	Image		*windows;
 	Image		*screenimage;
 	int		_isnewdisplay;
+	int		dpi;
 };

 struct Image
--- a/kern/devdraw.c
+++ b/kern/devdraw.c
@@ -76,6 +76,8 @@
 	int		refreshme;
 	int		infoid;
 	int		op;
+	int		displaydpi;
+	int		forcedpi;
 };

 struct Refresh
@@ -166,6 +168,8 @@
 	Client*		drawclientofpath(ulong);
 	DImage*	allocdimage(Memimage*);

+int displaydpi = 200;
+
 static	char Enodrawimage[] =	"unknown id for draw image";
 static	char Enodrawscreen[] =	"unknown id for draw screen";
 static	char Eshortdraw[] =	"short draw message";
@@ -783,6 +787,7 @@
 	cl->slot = i;
 	cl->clientid = ++sdraw.clientid;
 	cl->op = SoverD;
+	cl->displaydpi = displaydpi;
 	sdraw.client[i] = cl;
 	return cl;
 }
@@ -1408,6 +1413,7 @@
 	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
 	uchar *u, *a, refresh;
 	char *fmt;
+	Fmt f;
 	ulong value, chan;
 	Rectangle r, clipr;
 	Point p, q, *pp, sp;
@@ -1654,6 +1660,34 @@
 			memset(font->fchar, 0, ni*sizeof(FChar));
 			font->nfchar = ni;
 			font->ascent = a[9];
+			continue;
+
+		/* query: 'Q' n[1] queryspec[n] */
+		case 'q':
+			if(n < 2)
+				error(Eshortdraw);
+			m = 1+1+a[1];
+			if(n < m)
+				error(Eshortdraw);
+			fmtstrinit(&f);
+			for(c=0; c<a[1]; c++){
+				switch(a[2+c]){
+				default:
+					error("unknown query");
+					break;
+				case 'd':       /* dpi */
+					if(client->forcedpi)
+						fmtprint(&f, "%11d ", client->forcedpi);
+					else {
+						fmtprint(&f, "%11d ", client->displaydpi);
+					}
+					break;
+				}
+			}
+			client->readdata = (uchar*)fmtstrflush(&f);
+			if(client->readdata == nil)
+				error(Enomem);
+			client->nreaddata = strlen((char*)client->readdata);
 			continue;

 		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */



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

* Re: [9front] hidpi
  2021-12-20 16:13 [9front] hidpi Philip Silva
@ 2021-12-20 16:34 ` hiro
  2021-12-20 17:04 ` [9front] hidpi Philip Silva
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 19+ messages in thread
From: hiro @ 2021-12-20 16:34 UTC (permalink / raw)
  To: 9front

you didn't document this in the devdraw man page. are you sure though
that we need to do this on devdraw level?

On 12/20/21, Philip Silva <philip.silva@protonmail.com> wrote:
> I've been creating patches to enable hidpi to make scrollbars bigger when
> using > 100 dpi. It's basically 3 patches: 1st one for adding int
> displaydpi, 2nd one for adding an entry to plan9.ini and a 3rd very
> experimental one that changes scrollbar and border widths including some
> glitches. (And a 4th one that hardcodes 200 dpi in drawterm-metal-cocoa) The
> extra fields and most code is just copied from plan9port. (d0e0701, c96d832)
> I'm using this since a few months now and it works, the only problems I
> had:
>
> - system wouldn't boot anymore when only applying the libdraw part of the
> 1st patch (I fixed that and checked in a fresh install in a VM that it would
> just ignore when the new draw command q1d isn't present in devdraw)
> - glitches: the borders aren't calculated correctly (3rd patch for rio and
> acme is very wip)
> - despite the glitches it works reasonably well with acme and rio but some
> applications are quite small then. Not sure how much effort it would be to
> patch for compat. with dpi != 100
>
> There is also the field forcedpi that is left largely ignored but generally
> is supposed to override displaydpi when necessary.
>
> Greetings, Philip
>
>
> --
>
>
> 1st Patch for libdraw and devdraw:
>
> diff c7dcc82b0be805717efbe77c98eaadf3ee1e31af uncommitted
> --- a/sys/include/ape/draw.h
> +++ b/sys/include/ape/draw.h
> @@ -208,6 +208,7 @@
>  	Image		*windows;
>  	Image		*screenimage;
>  	int			_isnewdisplay;
> +	int			dpi;
>  };
>
>  struct Image
> --- a/sys/include/draw.h
> +++ b/sys/include/draw.h
> @@ -200,6 +200,7 @@
>  	Image		*windows;
>  	Image		*screenimage;
>  	int		_isnewdisplay;
> +	int		dpi;
>  };
>
>  struct Image
> --- a/sys/src/9/port/devdraw.c
> +++ b/sys/src/9/port/devdraw.c
> @@ -77,6 +77,8 @@
>  	int		refreshme;
>  	int		infoid;
>  	int		op;
> +	int		displaydpi;
> +	int		forcedpi;
>  };
>
>  struct Refresh
> @@ -785,6 +789,7 @@
>  	cl->slot = i;
>  	cl->clientid = ++sdraw.clientid;
>  	cl->op = SoverD;
> +	cl->displaydpi=100;
>  	sdraw.client[i] = cl;
>  	return cl;
>  }
> @@ -1396,6 +1401,7 @@
>  	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy,
> oesize, esize, doflush;
>  	uchar *u, *a, refresh;
>  	char *fmt;
> +	Fmt f;
>  	ulong value, chan;
>  	Rectangle r, clipr;
>  	Point p, q, *pp, sp;
> @@ -1643,6 +1649,35 @@
>  			font->nfchar = ni;
>  			font->ascent = a[9];
>  			continue;
> +
> +		/* query: 'Q' n[1] queryspec[n] */
> +		case 'q':
> +			if(n < 2){
> +				error(Eshortdraw);
> +			}
> +			m = 1+1+a[1];
> +			if(n < m){
> +				error(Eshortdraw);
> +			}
> +			fmtstrinit(&f);
> +			for(c=0; c<a[1]; c++){
> +				switch(a[2+c]){
> +				default:
> +					error("unknown query");
> +				case 'd':       /* dpi */
> +					if(client->forcedpi)
> +						fmtprint(&f, "%11d ", client->forcedpi);
> +					else
> +						fmtprint(&f, "%11d ", client->displaydpi);
> +					break;
> +				}
> +			}
> +			client->readdata = (uchar*)fmtstrflush(&f);
> +			if(client->readdata == nil)
> +				error(Enomem);
> +			client->nreaddata = strlen((char*)client->readdata);
> +			continue;
> +
>
>  		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1]
> width[1] */
>  		case 'l':
> --- a/sys/src/libdraw/init.c
> +++ b/sys/src/libdraw/init.c
> @@ -197,6 +197,7 @@
>  Display*
>  initdisplay(char *dev, char *win, void(*error)(Display*, char*))
>  {
> +	uchar *a;
>  	char buf[128], info[NINFO+1], *t, isnew;
>  	int n, datafd, ctlfd, reffd;
>  	Display *disp;
> @@ -319,6 +320,18 @@
>  	if(dir!=nil && dir->qid.vers==1)	/* other way to tell */
>  		disp->_isnewdisplay = 1;
>  	free(dir);
> +
> +	a = bufimage(disp, 3);
> +	if(a == nil)
> +		goto Error5;
> +	a[0] = 'q';
> +	a[1] = 1;
> +	a[2] = 'd';
> +	disp->dpi = 100;
> +	if(flushimage(disp, 0) >= 0){
> +		if((read(datafd, info, sizeof info)) == 12)
> +			disp->dpi = atoi(info);
> +	}
>
>  	return disp;
>  }
>
> --
>
> 2nd Patch for plan9.ini:
>
> diff c7dcc82b0be805717efbe77c98eaadf3ee1e31af uncommitted
> --- a/sys/man/8/plan9.ini
> +++ b/sys/man/8/plan9.ini
> @@ -971,6 +971,8 @@
>  .BR off .
>  The first two specify differing levels of power saving;
>  the third turns the monitor off completely.
> +.SS \fL*dpi=\fIvalue\fP
> +This is used to specify the screen dpi.
>  .SS NVRAM
>  .SS \fLnvram=\fIfile\fP
>  .SS \fLnvrlen=\fIlength\fP
> --- a/sys/src/9/port/devdraw.c
> +++ b/sys/src/9/port/devdraw.c
> @@ -765,6 +765,7 @@
>  drawnewclient(void)
>  {
>  	Client *cl, **cp;
> +	char *p;
>  	int i;
>
>  	for(i=0; i<sdraw.nclient; i++){
> @@ -789,7 +790,9 @@
>  	cl->slot = i;
>  	cl->clientid = ++sdraw.clientid;
>  	cl->op = SoverD;
> -	cl->displaydpi=100;
> +	if((p = getconf("dpi")) == nil || (cl->displaydpi = atoi(p)) == 0){
> +		cl->displaydpi=100;
> +	}
>  	sdraw.client[i] = cl;
>  	return cl;
>  }
>
> --
>
> 3rd Patch for rio/acme (proof-of-concept, just to provide an example)
>
> diff 75d8e460a00505c2b21a0d06ceb4300c93d9c4d6 uncommitted
> --- a/sys/include/ape/draw.h
> +++ b/sys/include/ape/draw.h
> @@ -69,6 +69,7 @@
>  	Displaybufsize	= 8000,
>  	ICOSSCALE	= 1024,
>  	Borderwidth =	4,
> +	DefaultDPI  =	100,
>  };
>
>  enum
> @@ -358,6 +359,7 @@
>  extern Image*	namedimage(Display*, char*);
>  extern int	nameimage(Image*, char*, int);
>  extern Image* allocimagemix(Display*, ulong, ulong);
> +extern int scalesize(Display*, int);
>
>  /*
>   * Colors
> --- a/sys/include/draw.h
> +++ b/sys/include/draw.h
> @@ -61,6 +61,7 @@
>  	Displaybufsize	= 8000,
>  	ICOSSCALE	= 1024,
>  	Borderwidth =	4,
> +	DefaultDPI  =	100,
>  };
>
>  enum
> @@ -354,6 +355,7 @@
>  extern Image*	namedimage(Display*, char*);
>  extern int	nameimage(Image*, char*, int);
>  extern Image* allocimagemix(Display*, ulong, ulong);
> +extern int scalesize(Display*, int);
>
>  /*
>   * Colors
> --- a/sys/src/cmd/acme/dat.h
> +++ b/sys/src/cmd/acme/dat.h
> @@ -473,11 +473,14 @@
>  	BUFSIZE = Maxblock+IOHDRSZ,	/* size from fbufalloc() */
>  	RBUFSIZE = BUFSIZE/sizeof(Rune),
>  	EVENTSIZE = 256,
> -	Scrollwid = 12,	/* width of scroll bar */
> -	Scrollgap = 4,	/* gap right of scroll bar */
> -	Margin = 4,	/* margin around text */
> -	Border = 2,	/* line between rows, cols, windows */
>  };
> +
> +// like in p9p c96d832
> +#define Scrollwid scalesize(display, 12)	/* width of scroll bar */
> +#define Scrollgap scalesize(display, 4)	/* gap right of scroll bar */
> +#define Margin scalesize(display, 4)	/* margin around text */
> +#define Border scalesize(display, 2)	/* line between rows, cols, windows
> */
> +#define ButtonBorder scalesize(display, 2)
>
>  #define	QID(w,q)	((w<<8)|(q))
>  #define	WIN(q)	((((ulong)(q).path)>>8) & 0xFFFFFF)
> --- a/sys/src/cmd/rio/wind.c
> +++ b/sys/src/cmd/rio/wind.c
> @@ -12,6 +12,14 @@
>  #include "dat.h"
>  #include "fns.h"
>
> +static int
> +wscale(Window *w, int n)
> +{
> +        if(w == nil || w->i == nil)
> +                return n;
> +        return scalesize(w->i->display, n);
> +}
> +
>  Window*
>  wlookid(int id)
>  {
> @@ -308,7 +316,7 @@
>  		else
>  			col = lighttitlecol;
>  	}
> -	border(w->i, w->i->r, Selborder, col, ZP);
> +	border(w->i, w->i->r, wscale(w, Selborder), col, ZP);
>  }
>
>  static void
> @@ -353,17 +361,17 @@
>
>  	w->i = i;
>  	w->mc.image = i;
> -	r = insetrect(i->r, Selborder+1);
> +	r = insetrect(i->r, wscale(w, Selborder)+wscale(w, 1));
>  	w->scrollr = r;
> -	w->scrollr.max.x = r.min.x+Scrollwid;
> +	w->scrollr.max.x = r.min.x+wscale(w, Scrollwid);
>  	w->lastsr = ZR;
> -	r.min.x += Scrollwid+Scrollgap;
> +	r.min.x += wscale(w, Scrollwid)+wscale(w, Scrollgap);
>  	frclear(w, FALSE);
>  	frinit(w, r, w->font, w->i, cols);
>  	wsetcols(w, w == input);
>  	w->maxtab = maxtab*stringwidth(w->font, "0");
>  	if(!w->mouseopen || !w->winnameread){
> -		r = insetrect(w->i->r, Selborder);
> +		r = insetrect(w->i->r, wscale(w, Selborder));
>  		draw(w->i, r, cols[BACK], nil, w->entire.min);
>  		wfill(w);
>  		wsetselect(w, w->q0, w->q1);
> @@ -370,7 +378,7 @@
>  		wscrdraw(w);
>  	}
>  	if(w == input)
> -		wborder(w, Selborder);
> +		wborder(w, wscale(w, Selborder));
>  	else
>  		wborder(w, Unselborder);
>  	flushimage(display, 1);
> @@ -390,9 +398,9 @@
>  	if(!w->mouseopen || !w->winnameread)
>  		frredraw(w);
>  	if(w == input)
> -		wborder(w, Selborder);
> +		wborder(w, wscale(w, Selborder));
>  	else
> -		wborder(w, Unselborder);
> +		wborder(w, wscale(w, Unselborder));
>  }
>
>  static void
> @@ -401,9 +409,9 @@
>  	Rectangle r;
>
>  	if(w == input)
> -		wborder(w, Selborder);
> +		wborder(w, wscale(w, Selborder));
>  	else
> -		wborder(w, Unselborder);
> +		wborder(w, wscale(w, Unselborder));
>  	r = insetrect(w->i->r, Selborder);
>  	draw(w->i, r, w->cols[BACK], nil, w->entire.min);
>  	wfill(w);
> @@ -1249,7 +1257,7 @@
>
>  	w = emalloc(sizeof(Window));
>  	w->screenr = i->r;
> -	r = insetrect(i->r, Selborder+1);
> +	r = insetrect(i->r, wscale(w, Selborder)+wscale(w, 1));
>  	w->i = i;
>  	w->mc = *mc;
>  	w->ck = ck;
> @@ -1263,9 +1271,9 @@
>  	w->complete = chancreate(sizeof(Completion*), 0);
>  	w->gone = chancreate(sizeof(char*), 0);
>  	w->scrollr = r;
> -	w->scrollr.max.x = r.min.x+Scrollwid;
> +	w->scrollr.max.x = r.min.x+wscale(w, Scrollwid);
>  	w->lastsr = ZR;
> -	r.min.x += Scrollwid+Scrollgap;
> +	r.min.x += wscale(w, Scrollwid)+wscale(w, Scrollgap);
>  	frinit(w, r, font, i, cols);
>  	w->maxtab = maxtab*stringwidth(font, "0");
>  	w->topped = ++topped;
> @@ -1274,9 +1282,9 @@
>  	w->scrolling = scrolling;
>  	w->dir = estrdup(startdir);
>  	w->label = estrdup("<unnamed>");
> -	r = insetrect(w->i->r, Selborder);
> +	r = insetrect(w->i->r, wscale(w, Selborder));
>  	draw(w->i, r, cols[BACK], nil, w->entire.min);
> -	wborder(w, Selborder);
> +	wborder(w, wscale(w, Selborder));
>  	wscrdraw(w);
>  	incref(w);	/* ref will be removed after mounting; avoids delete before
> ready to be deleted */
>  	return w;
> --- a/sys/src/libdraw/init.c
> +++ b/sys/src/libdraw/init.c
> @@ -452,5 +465,13 @@
>  	p = d->bufp;
>  	d->bufp += n;
>  	return p;
> +}
> +
> +int
> +scalesize(Display *d, int n)
> +{
> +	if(d == nil || d->dpi <= DefaultDPI)
> +		return n;
> +	return (n*d->dpi+DefaultDPI/2)/DefaultDPI;
>  }
>
> --
>
> 4th Patch (drawterm-metal-cocoa - I've been using this most of the time):
>
> diff 0b7990cf2b84e7a80cf3f3a9e7eadca10d51a2c5 uncommitted
> --- a/include/draw.h
> +++ b/include/draw.h
> @@ -193,6 +193,7 @@
>  	Image		*windows;
>  	Image		*screenimage;
>  	int		_isnewdisplay;
> +	int		dpi;
>  };
>
>  struct Image
> --- a/kern/devdraw.c
> +++ b/kern/devdraw.c
> @@ -76,6 +76,8 @@
>  	int		refreshme;
>  	int		infoid;
>  	int		op;
> +	int		displaydpi;
> +	int		forcedpi;
>  };
>
>  struct Refresh
> @@ -166,6 +168,8 @@
>  	Client*		drawclientofpath(ulong);
>  	DImage*	allocdimage(Memimage*);
>
> +int displaydpi = 200;
> +
>  static	char Enodrawimage[] =	"unknown id for draw image";
>  static	char Enodrawscreen[] =	"unknown id for draw screen";
>  static	char Eshortdraw[] =	"short draw message";
> @@ -783,6 +787,7 @@
>  	cl->slot = i;
>  	cl->clientid = ++sdraw.clientid;
>  	cl->op = SoverD;
> +	cl->displaydpi = displaydpi;
>  	sdraw.client[i] = cl;
>  	return cl;
>  }
> @@ -1408,6 +1413,7 @@
>  	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy,
> oesize, esize, doflush;
>  	uchar *u, *a, refresh;
>  	char *fmt;
> +	Fmt f;
>  	ulong value, chan;
>  	Rectangle r, clipr;
>  	Point p, q, *pp, sp;
> @@ -1654,6 +1660,34 @@
>  			memset(font->fchar, 0, ni*sizeof(FChar));
>  			font->nfchar = ni;
>  			font->ascent = a[9];
> +			continue;
> +
> +		/* query: 'Q' n[1] queryspec[n] */
> +		case 'q':
> +			if(n < 2)
> +				error(Eshortdraw);
> +			m = 1+1+a[1];
> +			if(n < m)
> +				error(Eshortdraw);
> +			fmtstrinit(&f);
> +			for(c=0; c<a[1]; c++){
> +				switch(a[2+c]){
> +				default:
> +					error("unknown query");
> +					break;
> +				case 'd':       /* dpi */
> +					if(client->forcedpi)
> +						fmtprint(&f, "%11d ", client->forcedpi);
> +					else {
> +						fmtprint(&f, "%11d ", client->displaydpi);
> +					}
> +					break;
> +				}
> +			}
> +			client->readdata = (uchar*)fmtstrflush(&f);
> +			if(client->readdata == nil)
> +				error(Enomem);
> +			client->nreaddata = strlen((char*)client->readdata);
>  			continue;
>
>  		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1]
> width[1] */
>
>
>

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

* [9front] Re: hidpi
  2021-12-20 16:13 [9front] hidpi Philip Silva
  2021-12-20 16:34 ` hiro
@ 2021-12-20 17:04 ` Philip Silva
  2021-12-20 17:29   ` hiro
  2021-12-20 19:15   ` Noam Preil
  2021-12-20 17:59 ` [9front] hidpi igor
  2021-12-22  8:39 ` igor
  3 siblings, 2 replies; 19+ messages in thread
From: Philip Silva @ 2021-12-20 17:04 UTC (permalink / raw)
  To: 9front

> you didn't document this in the devdraw man page.

True, I could add this.

> are you sure though that we need to do this on devdraw level?

Not really sure to be honest, I only have a rough idea about libdraw or how to exchange configuration options. At least in plan9port there is also the new q(1d) command to query DPIs and 9fans.net/go/draw uses it as well. I wonder whether this could be realized by just using environment variables instead of configuring this through plan9.ini/the result of q1d in drawterm.

https://github.com/9fans/go/blob/v0.0.4/draw/init.go#L300


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

* Re: [9front] Re: hidpi
  2021-12-20 17:04 ` [9front] hidpi Philip Silva
@ 2021-12-20 17:29   ` hiro
  2021-12-20 19:15   ` Noam Preil
  1 sibling, 0 replies; 19+ messages in thread
From: hiro @ 2021-12-20 17:29 UTC (permalink / raw)
  To: 9front

I don't like *automatically* setting DPI depending on what lies Xorg tells us.

On the other hand I find giving the user the ability to set DPI is
nice. Mainly because different users sit at a different distance to
their monitor.

On 12/20/21, Philip Silva <philip.silva@protonmail.com> wrote:
>> you didn't document this in the devdraw man page.
>
> True, I could add this.
>
>> are you sure though that we need to do this on devdraw level?
>
> Not really sure to be honest, I only have a rough idea about libdraw or how
> to exchange configuration options. At least in plan9port there is also the
> new q(1d) command to query DPIs and 9fans.net/go/draw uses it as well. I
> wonder whether this could be realized by just using environment variables
> instead of configuring this through plan9.ini/the result of q1d in
> drawterm.
>
> https://github.com/9fans/go/blob/v0.0.4/draw/init.go#L300
>
>

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

* Re: [9front] hidpi
  2021-12-20 16:13 [9front] hidpi Philip Silva
  2021-12-20 16:34 ` hiro
  2021-12-20 17:04 ` [9front] hidpi Philip Silva
@ 2021-12-20 17:59 ` igor
  2021-12-20 18:28   ` hiro
  2021-12-20 19:02   ` Philip Silva
  2021-12-22  8:39 ` igor
  3 siblings, 2 replies; 19+ messages in thread
From: igor @ 2021-12-20 17:59 UTC (permalink / raw)
  To: 9front

Hi Philip,

This reminds me of a plan9port feature to change DPI (useful
on a high res display, e.g. Retina display). Are you trying
to achieve something similar as this:

• https://groups.google.com/g/plan9port-dev/c/rXtpIufTrbMhttps://github.com/9fans/plan9port/blob/master/src/cmd/devdraw/devdraw.c#L976

Cheers,
Igor

Quoth Philip Silva <philip.silva@protonmail.com>:
> I've been creating patches to enable hidpi to make scrollbars bigger when using > 100 dpi. It's basically 3 patches: 1st one for adding int displaydpi, 2nd one for adding an entry to plan9.ini and a 3rd very experimental one that changes scrollbar and border widths including some glitches. (And a 4th one that hardcodes 200 dpi in drawterm-metal-cocoa) The extra fields and most code is just copied from plan9port. (d0e0701, c96d832) I'm using this since a few months now and it works, the only problems I had:
> 
> - system wouldn't boot anymore when only applying the libdraw part of the 1st patch (I fixed that and checked in a fresh install in a VM that it would just ignore when the new draw command q1d isn't present in devdraw)
> - glitches: the borders aren't calculated correctly (3rd patch for rio and acme is very wip)
> - despite the glitches it works reasonably well with acme and rio but some applications are quite small then. Not sure how much effort it would be to patch for compat. with dpi != 100
> 
> There is also the field forcedpi that is left largely ignored but generally is supposed to override displaydpi when necessary.
> 
> Greetings, Philip
> 
> 
> --
> 
> 
> 1st Patch for libdraw and devdraw:
> 
> diff c7dcc82b0be805717efbe77c98eaadf3ee1e31af uncommitted
> --- a/sys/include/ape/draw.h
> +++ b/sys/include/ape/draw.h
> @@ -208,6 +208,7 @@
>  	Image		*windows;
>  	Image		*screenimage;
>  	int			_isnewdisplay;
> +	int			dpi;
>  };
> 
>  struct Image
> --- a/sys/include/draw.h
> +++ b/sys/include/draw.h
> @@ -200,6 +200,7 @@
>  	Image		*windows;
>  	Image		*screenimage;
>  	int		_isnewdisplay;
> +	int		dpi;
>  };
> 
>  struct Image
> --- a/sys/src/9/port/devdraw.c
> +++ b/sys/src/9/port/devdraw.c
> @@ -77,6 +77,8 @@
>  	int		refreshme;
>  	int		infoid;
>  	int		op;
> +	int		displaydpi;
> +	int		forcedpi;
>  };
> 
>  struct Refresh
> @@ -785,6 +789,7 @@
>  	cl->slot = i;
>  	cl->clientid = ++sdraw.clientid;
>  	cl->op = SoverD;
> +	cl->displaydpi=100;
>  	sdraw.client[i] = cl;
>  	return cl;
>  }
> @@ -1396,6 +1401,7 @@
>  	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
>  	uchar *u, *a, refresh;
>  	char *fmt;
> +	Fmt f;
>  	ulong value, chan;
>  	Rectangle r, clipr;
>  	Point p, q, *pp, sp;
> @@ -1643,6 +1649,35 @@
>  			font->nfchar = ni;
>  			font->ascent = a[9];
>  			continue;
> +
> +		/* query: 'Q' n[1] queryspec[n] */
> +		case 'q':
> +			if(n < 2){
> +				error(Eshortdraw);
> +			}
> +			m = 1+1+a[1];
> +			if(n < m){
> +				error(Eshortdraw);
> +			}
> +			fmtstrinit(&f);
> +			for(c=0; c<a[1]; c++){
> +				switch(a[2+c]){
> +				default:
> +					error("unknown query");
> +				case 'd':       /* dpi */
> +					if(client->forcedpi)
> +						fmtprint(&f, "%11d ", client->forcedpi);
> +					else
> +						fmtprint(&f, "%11d ", client->displaydpi);
> +					break;
> +				}
> +			}
> +			client->readdata = (uchar*)fmtstrflush(&f);
> +			if(client->readdata == nil)
> +				error(Enomem);
> +			client->nreaddata = strlen((char*)client->readdata);
> +			continue;
> +
> 
>  		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
>  		case 'l':
> --- a/sys/src/libdraw/init.c
> +++ b/sys/src/libdraw/init.c
> @@ -197,6 +197,7 @@
>  Display*
>  initdisplay(char *dev, char *win, void(*error)(Display*, char*))
>  {
> +	uchar *a;
>  	char buf[128], info[NINFO+1], *t, isnew;
>  	int n, datafd, ctlfd, reffd;
>  	Display *disp;
> @@ -319,6 +320,18 @@
>  	if(dir!=nil && dir->qid.vers==1)	/* other way to tell */
>  		disp->_isnewdisplay = 1;
>  	free(dir);
> +
> +	a = bufimage(disp, 3);
> +	if(a == nil)
> +		goto Error5;
> +	a[0] = 'q';
> +	a[1] = 1;
> +	a[2] = 'd';
> +	disp->dpi = 100;
> +	if(flushimage(disp, 0) >= 0){
> +		if((read(datafd, info, sizeof info)) == 12)
> +			disp->dpi = atoi(info);
> +	}
> 
>  	return disp;
>  }
> 
> --
> 
> 2nd Patch for plan9.ini:
> 
> diff c7dcc82b0be805717efbe77c98eaadf3ee1e31af uncommitted
> --- a/sys/man/8/plan9.ini
> +++ b/sys/man/8/plan9.ini
> @@ -971,6 +971,8 @@
>  .BR off .
>  The first two specify differing levels of power saving;
>  the third turns the monitor off completely.
> +.SS \fL*dpi=\fIvalue\fP
> +This is used to specify the screen dpi.
>  .SS NVRAM
>  .SS \fLnvram=\fIfile\fP
>  .SS \fLnvrlen=\fIlength\fP
> --- a/sys/src/9/port/devdraw.c
> +++ b/sys/src/9/port/devdraw.c
> @@ -765,6 +765,7 @@
>  drawnewclient(void)
>  {
>  	Client *cl, **cp;
> +	char *p;
>  	int i;
> 
>  	for(i=0; i<sdraw.nclient; i++){
> @@ -789,7 +790,9 @@
>  	cl->slot = i;
>  	cl->clientid = ++sdraw.clientid;
>  	cl->op = SoverD;
> -	cl->displaydpi=100;
> +	if((p = getconf("dpi")) == nil || (cl->displaydpi = atoi(p)) == 0){
> +		cl->displaydpi=100;
> +	}
>  	sdraw.client[i] = cl;
>  	return cl;
>  }
> 
> --
> 
> 3rd Patch for rio/acme (proof-of-concept, just to provide an example)
> 
> diff 75d8e460a00505c2b21a0d06ceb4300c93d9c4d6 uncommitted
> --- a/sys/include/ape/draw.h
> +++ b/sys/include/ape/draw.h
> @@ -69,6 +69,7 @@
>  	Displaybufsize	= 8000,
>  	ICOSSCALE	= 1024,
>  	Borderwidth =	4,
> +	DefaultDPI  =	100,
>  };
> 
>  enum
> @@ -358,6 +359,7 @@
>  extern Image*	namedimage(Display*, char*);
>  extern int	nameimage(Image*, char*, int);
>  extern Image* allocimagemix(Display*, ulong, ulong);
> +extern int scalesize(Display*, int);
> 
>  /*
>   * Colors
> --- a/sys/include/draw.h
> +++ b/sys/include/draw.h
> @@ -61,6 +61,7 @@
>  	Displaybufsize	= 8000,
>  	ICOSSCALE	= 1024,
>  	Borderwidth =	4,
> +	DefaultDPI  =	100,
>  };
> 
>  enum
> @@ -354,6 +355,7 @@
>  extern Image*	namedimage(Display*, char*);
>  extern int	nameimage(Image*, char*, int);
>  extern Image* allocimagemix(Display*, ulong, ulong);
> +extern int scalesize(Display*, int);
> 
>  /*
>   * Colors
> --- a/sys/src/cmd/acme/dat.h
> +++ b/sys/src/cmd/acme/dat.h
> @@ -473,11 +473,14 @@
>  	BUFSIZE = Maxblock+IOHDRSZ,	/* size from fbufalloc() */
>  	RBUFSIZE = BUFSIZE/sizeof(Rune),
>  	EVENTSIZE = 256,
> -	Scrollwid = 12,	/* width of scroll bar */
> -	Scrollgap = 4,	/* gap right of scroll bar */
> -	Margin = 4,	/* margin around text */
> -	Border = 2,	/* line between rows, cols, windows */
>  };
> +
> +// like in p9p c96d832
> +#define Scrollwid scalesize(display, 12)	/* width of scroll bar */
> +#define Scrollgap scalesize(display, 4)	/* gap right of scroll bar */
> +#define Margin scalesize(display, 4)	/* margin around text */
> +#define Border scalesize(display, 2)	/* line between rows, cols, windows */
> +#define ButtonBorder scalesize(display, 2)
> 
>  #define	QID(w,q)	((w<<8)|(q))
>  #define	WIN(q)	((((ulong)(q).path)>>8) & 0xFFFFFF)
> --- a/sys/src/cmd/rio/wind.c
> +++ b/sys/src/cmd/rio/wind.c
> @@ -12,6 +12,14 @@
>  #include "dat.h"
>  #include "fns.h"
> 
> +static int
> +wscale(Window *w, int n)
> +{
> +        if(w == nil || w->i == nil)
> +                return n;
> +        return scalesize(w->i->display, n);
> +}
> +
>  Window*
>  wlookid(int id)
>  {
> @@ -308,7 +316,7 @@
>  		else
>  			col = lighttitlecol;
>  	}
> -	border(w->i, w->i->r, Selborder, col, ZP);
> +	border(w->i, w->i->r, wscale(w, Selborder), col, ZP);
>  }
> 
>  static void
> @@ -353,17 +361,17 @@
> 
>  	w->i = i;
>  	w->mc.image = i;
> -	r = insetrect(i->r, Selborder+1);
> +	r = insetrect(i->r, wscale(w, Selborder)+wscale(w, 1));
>  	w->scrollr = r;
> -	w->scrollr.max.x = r.min.x+Scrollwid;
> +	w->scrollr.max.x = r.min.x+wscale(w, Scrollwid);
>  	w->lastsr = ZR;
> -	r.min.x += Scrollwid+Scrollgap;
> +	r.min.x += wscale(w, Scrollwid)+wscale(w, Scrollgap);
>  	frclear(w, FALSE);
>  	frinit(w, r, w->font, w->i, cols);
>  	wsetcols(w, w == input);
>  	w->maxtab = maxtab*stringwidth(w->font, "0");
>  	if(!w->mouseopen || !w->winnameread){
> -		r = insetrect(w->i->r, Selborder);
> +		r = insetrect(w->i->r, wscale(w, Selborder));
>  		draw(w->i, r, cols[BACK], nil, w->entire.min);
>  		wfill(w);
>  		wsetselect(w, w->q0, w->q1);
> @@ -370,7 +378,7 @@
>  		wscrdraw(w);
>  	}
>  	if(w == input)
> -		wborder(w, Selborder);
> +		wborder(w, wscale(w, Selborder));
>  	else
>  		wborder(w, Unselborder);
>  	flushimage(display, 1);
> @@ -390,9 +398,9 @@
>  	if(!w->mouseopen || !w->winnameread)
>  		frredraw(w);
>  	if(w == input)
> -		wborder(w, Selborder);
> +		wborder(w, wscale(w, Selborder));
>  	else
> -		wborder(w, Unselborder);
> +		wborder(w, wscale(w, Unselborder));
>  }
> 
>  static void
> @@ -401,9 +409,9 @@
>  	Rectangle r;
> 
>  	if(w == input)
> -		wborder(w, Selborder);
> +		wborder(w, wscale(w, Selborder));
>  	else
> -		wborder(w, Unselborder);
> +		wborder(w, wscale(w, Unselborder));
>  	r = insetrect(w->i->r, Selborder);
>  	draw(w->i, r, w->cols[BACK], nil, w->entire.min);
>  	wfill(w);
> @@ -1249,7 +1257,7 @@
> 
>  	w = emalloc(sizeof(Window));
>  	w->screenr = i->r;
> -	r = insetrect(i->r, Selborder+1);
> +	r = insetrect(i->r, wscale(w, Selborder)+wscale(w, 1));
>  	w->i = i;
>  	w->mc = *mc;
>  	w->ck = ck;
> @@ -1263,9 +1271,9 @@
>  	w->complete = chancreate(sizeof(Completion*), 0);
>  	w->gone = chancreate(sizeof(char*), 0);
>  	w->scrollr = r;
> -	w->scrollr.max.x = r.min.x+Scrollwid;
> +	w->scrollr.max.x = r.min.x+wscale(w, Scrollwid);
>  	w->lastsr = ZR;
> -	r.min.x += Scrollwid+Scrollgap;
> +	r.min.x += wscale(w, Scrollwid)+wscale(w, Scrollgap);
>  	frinit(w, r, font, i, cols);
>  	w->maxtab = maxtab*stringwidth(font, "0");
>  	w->topped = ++topped;
> @@ -1274,9 +1282,9 @@
>  	w->scrolling = scrolling;
>  	w->dir = estrdup(startdir);
>  	w->label = estrdup("<unnamed>");
> -	r = insetrect(w->i->r, Selborder);
> +	r = insetrect(w->i->r, wscale(w, Selborder));
>  	draw(w->i, r, cols[BACK], nil, w->entire.min);
> -	wborder(w, Selborder);
> +	wborder(w, wscale(w, Selborder));
>  	wscrdraw(w);
>  	incref(w);	/* ref will be removed after mounting; avoids delete before ready to be deleted */
>  	return w;
> --- a/sys/src/libdraw/init.c
> +++ b/sys/src/libdraw/init.c
> @@ -452,5 +465,13 @@
>  	p = d->bufp;
>  	d->bufp += n;
>  	return p;
> +}
> +
> +int
> +scalesize(Display *d, int n)
> +{
> +	if(d == nil || d->dpi <= DefaultDPI)
> +		return n;
> +	return (n*d->dpi+DefaultDPI/2)/DefaultDPI;
>  }
> 
> --
> 
> 4th Patch (drawterm-metal-cocoa - I've been using this most of the time):
> 
> diff 0b7990cf2b84e7a80cf3f3a9e7eadca10d51a2c5 uncommitted
> --- a/include/draw.h
> +++ b/include/draw.h
> @@ -193,6 +193,7 @@
>  	Image		*windows;
>  	Image		*screenimage;
>  	int		_isnewdisplay;
> +	int		dpi;
>  };
> 
>  struct Image
> --- a/kern/devdraw.c
> +++ b/kern/devdraw.c
> @@ -76,6 +76,8 @@
>  	int		refreshme;
>  	int		infoid;
>  	int		op;
> +	int		displaydpi;
> +	int		forcedpi;
>  };
> 
>  struct Refresh
> @@ -166,6 +168,8 @@
>  	Client*		drawclientofpath(ulong);
>  	DImage*	allocdimage(Memimage*);
> 
> +int displaydpi = 200;
> +
>  static	char Enodrawimage[] =	"unknown id for draw image";
>  static	char Enodrawscreen[] =	"unknown id for draw screen";
>  static	char Eshortdraw[] =	"short draw message";
> @@ -783,6 +787,7 @@
>  	cl->slot = i;
>  	cl->clientid = ++sdraw.clientid;
>  	cl->op = SoverD;
> +	cl->displaydpi = displaydpi;
>  	sdraw.client[i] = cl;
>  	return cl;
>  }
> @@ -1408,6 +1413,7 @@
>  	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
>  	uchar *u, *a, refresh;
>  	char *fmt;
> +	Fmt f;
>  	ulong value, chan;
>  	Rectangle r, clipr;
>  	Point p, q, *pp, sp;
> @@ -1654,6 +1660,34 @@
>  			memset(font->fchar, 0, ni*sizeof(FChar));
>  			font->nfchar = ni;
>  			font->ascent = a[9];
> +			continue;
> +
> +		/* query: 'Q' n[1] queryspec[n] */
> +		case 'q':
> +			if(n < 2)
> +				error(Eshortdraw);
> +			m = 1+1+a[1];
> +			if(n < m)
> +				error(Eshortdraw);
> +			fmtstrinit(&f);
> +			for(c=0; c<a[1]; c++){
> +				switch(a[2+c]){
> +				default:
> +					error("unknown query");
> +					break;
> +				case 'd':       /* dpi */
> +					if(client->forcedpi)
> +						fmtprint(&f, "%11d ", client->forcedpi);
> +					else {
> +						fmtprint(&f, "%11d ", client->displaydpi);
> +					}
> +					break;
> +				}
> +			}
> +			client->readdata = (uchar*)fmtstrflush(&f);
> +			if(client->readdata == nil)
> +				error(Enomem);
> +			client->nreaddata = strlen((char*)client->readdata);
>  			continue;
> 
>  		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
> 
> 


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

* Re: [9front] hidpi
  2021-12-20 17:59 ` [9front] hidpi igor
@ 2021-12-20 18:28   ` hiro
  2021-12-20 19:27     ` Noam Preil
  2021-12-20 19:02   ` Philip Silva
  1 sibling, 1 reply; 19+ messages in thread
From: hiro @ 2021-12-20 18:28 UTC (permalink / raw)
  To: 9front

Yeah this links to a relevant discussion that shows how the code
considers only macos.

The idea was that linux users should just send a patch.
But this doesn't solve the issue that even if the hardware reports the
correct dpi to the computer, and the OS correctly forwards this
information to graphical clients, and drawterm implements this
interface, we still don't know the user's actual need of scale.

Due to variable distance to the screen and variable quality of user's
eyes, the hardware reporting of DPI becomes quite irrelevant.

So for simplicity I propose devdraw and thus drawterm does *not* get
an interface.

On 12/20/21, igor@9lab.org <igor@9lab.org> wrote:
> Hi Philip,
>
> This reminds me of a plan9port feature to change DPI (useful
> on a high res display, e.g. Retina display). Are you trying
> to achieve something similar as this:
>
> • https://groups.google.com/g/plan9port-dev/c/rXtpIufTrbM
> •
> https://github.com/9fans/plan9port/blob/master/src/cmd/devdraw/devdraw.c#L976
>
> Cheers,
> Igor
>
> Quoth Philip Silva <philip.silva@protonmail.com>:
>> I've been creating patches to enable hidpi to make scrollbars bigger when
>> using > 100 dpi. It's basically 3 patches: 1st one for adding int
>> displaydpi, 2nd one for adding an entry to plan9.ini and a 3rd very
>> experimental one that changes scrollbar and border widths including some
>> glitches. (And a 4th one that hardcodes 200 dpi in drawterm-metal-cocoa)
>> The extra fields and most code is just copied from plan9port. (d0e0701,
>> c96d832) I'm using this since a few months now and it works, the only
>> problems I had:
>>
>> - system wouldn't boot anymore when only applying the libdraw part of the
>> 1st patch (I fixed that and checked in a fresh install in a VM that it
>> would just ignore when the new draw command q1d isn't present in devdraw)
>> - glitches: the borders aren't calculated correctly (3rd patch for rio and
>> acme is very wip)
>> - despite the glitches it works reasonably well with acme and rio but some
>> applications are quite small then. Not sure how much effort it would be to
>> patch for compat. with dpi != 100
>>
>> There is also the field forcedpi that is left largely ignored but
>> generally is supposed to override displaydpi when necessary.
>>
>> Greetings, Philip
>>
>>
>> --
>>
>>
>> 1st Patch for libdraw and devdraw:
>>
>> diff c7dcc82b0be805717efbe77c98eaadf3ee1e31af uncommitted
>> --- a/sys/include/ape/draw.h
>> +++ b/sys/include/ape/draw.h
>> @@ -208,6 +208,7 @@
>>  	Image		*windows;
>>  	Image		*screenimage;
>>  	int			_isnewdisplay;
>> +	int			dpi;
>>  };
>>
>>  struct Image
>> --- a/sys/include/draw.h
>> +++ b/sys/include/draw.h
>> @@ -200,6 +200,7 @@
>>  	Image		*windows;
>>  	Image		*screenimage;
>>  	int		_isnewdisplay;
>> +	int		dpi;
>>  };
>>
>>  struct Image
>> --- a/sys/src/9/port/devdraw.c
>> +++ b/sys/src/9/port/devdraw.c
>> @@ -77,6 +77,8 @@
>>  	int		refreshme;
>>  	int		infoid;
>>  	int		op;
>> +	int		displaydpi;
>> +	int		forcedpi;
>>  };
>>
>>  struct Refresh
>> @@ -785,6 +789,7 @@
>>  	cl->slot = i;
>>  	cl->clientid = ++sdraw.clientid;
>>  	cl->op = SoverD;
>> +	cl->displaydpi=100;
>>  	sdraw.client[i] = cl;
>>  	return cl;
>>  }
>> @@ -1396,6 +1401,7 @@
>>  	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy,
>> oesize, esize, doflush;
>>  	uchar *u, *a, refresh;
>>  	char *fmt;
>> +	Fmt f;
>>  	ulong value, chan;
>>  	Rectangle r, clipr;
>>  	Point p, q, *pp, sp;
>> @@ -1643,6 +1649,35 @@
>>  			font->nfchar = ni;
>>  			font->ascent = a[9];
>>  			continue;
>> +
>> +		/* query: 'Q' n[1] queryspec[n] */
>> +		case 'q':
>> +			if(n < 2){
>> +				error(Eshortdraw);
>> +			}
>> +			m = 1+1+a[1];
>> +			if(n < m){
>> +				error(Eshortdraw);
>> +			}
>> +			fmtstrinit(&f);
>> +			for(c=0; c<a[1]; c++){
>> +				switch(a[2+c]){
>> +				default:
>> +					error("unknown query");
>> +				case 'd':       /* dpi */
>> +					if(client->forcedpi)
>> +						fmtprint(&f, "%11d ", client->forcedpi);
>> +					else
>> +						fmtprint(&f, "%11d ", client->displaydpi);
>> +					break;
>> +				}
>> +			}
>> +			client->readdata = (uchar*)fmtstrflush(&f);
>> +			if(client->readdata == nil)
>> +				error(Enomem);
>> +			client->nreaddata = strlen((char*)client->readdata);
>> +			continue;
>> +
>>
>>  		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4]
>> left[1] width[1] */
>>  		case 'l':
>> --- a/sys/src/libdraw/init.c
>> +++ b/sys/src/libdraw/init.c
>> @@ -197,6 +197,7 @@
>>  Display*
>>  initdisplay(char *dev, char *win, void(*error)(Display*, char*))
>>  {
>> +	uchar *a;
>>  	char buf[128], info[NINFO+1], *t, isnew;
>>  	int n, datafd, ctlfd, reffd;
>>  	Display *disp;
>> @@ -319,6 +320,18 @@
>>  	if(dir!=nil && dir->qid.vers==1)	/* other way to tell */
>>  		disp->_isnewdisplay = 1;
>>  	free(dir);
>> +
>> +	a = bufimage(disp, 3);
>> +	if(a == nil)
>> +		goto Error5;
>> +	a[0] = 'q';
>> +	a[1] = 1;
>> +	a[2] = 'd';
>> +	disp->dpi = 100;
>> +	if(flushimage(disp, 0) >= 0){
>> +		if((read(datafd, info, sizeof info)) == 12)
>> +			disp->dpi = atoi(info);
>> +	}
>>
>>  	return disp;
>>  }
>>
>> --
>>
>> 2nd Patch for plan9.ini:
>>
>> diff c7dcc82b0be805717efbe77c98eaadf3ee1e31af uncommitted
>> --- a/sys/man/8/plan9.ini
>> +++ b/sys/man/8/plan9.ini
>> @@ -971,6 +971,8 @@
>>  .BR off .
>>  The first two specify differing levels of power saving;
>>  the third turns the monitor off completely.
>> +.SS \fL*dpi=\fIvalue\fP
>> +This is used to specify the screen dpi.
>>  .SS NVRAM
>>  .SS \fLnvram=\fIfile\fP
>>  .SS \fLnvrlen=\fIlength\fP
>> --- a/sys/src/9/port/devdraw.c
>> +++ b/sys/src/9/port/devdraw.c
>> @@ -765,6 +765,7 @@
>>  drawnewclient(void)
>>  {
>>  	Client *cl, **cp;
>> +	char *p;
>>  	int i;
>>
>>  	for(i=0; i<sdraw.nclient; i++){
>> @@ -789,7 +790,9 @@
>>  	cl->slot = i;
>>  	cl->clientid = ++sdraw.clientid;
>>  	cl->op = SoverD;
>> -	cl->displaydpi=100;
>> +	if((p = getconf("dpi")) == nil || (cl->displaydpi = atoi(p)) == 0){
>> +		cl->displaydpi=100;
>> +	}
>>  	sdraw.client[i] = cl;
>>  	return cl;
>>  }
>>
>> --
>>
>> 3rd Patch for rio/acme (proof-of-concept, just to provide an example)
>>
>> diff 75d8e460a00505c2b21a0d06ceb4300c93d9c4d6 uncommitted
>> --- a/sys/include/ape/draw.h
>> +++ b/sys/include/ape/draw.h
>> @@ -69,6 +69,7 @@
>>  	Displaybufsize	= 8000,
>>  	ICOSSCALE	= 1024,
>>  	Borderwidth =	4,
>> +	DefaultDPI  =	100,
>>  };
>>
>>  enum
>> @@ -358,6 +359,7 @@
>>  extern Image*	namedimage(Display*, char*);
>>  extern int	nameimage(Image*, char*, int);
>>  extern Image* allocimagemix(Display*, ulong, ulong);
>> +extern int scalesize(Display*, int);
>>
>>  /*
>>   * Colors
>> --- a/sys/include/draw.h
>> +++ b/sys/include/draw.h
>> @@ -61,6 +61,7 @@
>>  	Displaybufsize	= 8000,
>>  	ICOSSCALE	= 1024,
>>  	Borderwidth =	4,
>> +	DefaultDPI  =	100,
>>  };
>>
>>  enum
>> @@ -354,6 +355,7 @@
>>  extern Image*	namedimage(Display*, char*);
>>  extern int	nameimage(Image*, char*, int);
>>  extern Image* allocimagemix(Display*, ulong, ulong);
>> +extern int scalesize(Display*, int);
>>
>>  /*
>>   * Colors
>> --- a/sys/src/cmd/acme/dat.h
>> +++ b/sys/src/cmd/acme/dat.h
>> @@ -473,11 +473,14 @@
>>  	BUFSIZE = Maxblock+IOHDRSZ,	/* size from fbufalloc() */
>>  	RBUFSIZE = BUFSIZE/sizeof(Rune),
>>  	EVENTSIZE = 256,
>> -	Scrollwid = 12,	/* width of scroll bar */
>> -	Scrollgap = 4,	/* gap right of scroll bar */
>> -	Margin = 4,	/* margin around text */
>> -	Border = 2,	/* line between rows, cols, windows */
>>  };
>> +
>> +// like in p9p c96d832
>> +#define Scrollwid scalesize(display, 12)	/* width of scroll bar */
>> +#define Scrollgap scalesize(display, 4)	/* gap right of scroll bar */
>> +#define Margin scalesize(display, 4)	/* margin around text */
>> +#define Border scalesize(display, 2)	/* line between rows, cols, windows
>> */
>> +#define ButtonBorder scalesize(display, 2)
>>
>>  #define	QID(w,q)	((w<<8)|(q))
>>  #define	WIN(q)	((((ulong)(q).path)>>8) & 0xFFFFFF)
>> --- a/sys/src/cmd/rio/wind.c
>> +++ b/sys/src/cmd/rio/wind.c
>> @@ -12,6 +12,14 @@
>>  #include "dat.h"
>>  #include "fns.h"
>>
>> +static int
>> +wscale(Window *w, int n)
>> +{
>> +        if(w == nil || w->i == nil)
>> +                return n;
>> +        return scalesize(w->i->display, n);
>> +}
>> +
>>  Window*
>>  wlookid(int id)
>>  {
>> @@ -308,7 +316,7 @@
>>  		else
>>  			col = lighttitlecol;
>>  	}
>> -	border(w->i, w->i->r, Selborder, col, ZP);
>> +	border(w->i, w->i->r, wscale(w, Selborder), col, ZP);
>>  }
>>
>>  static void
>> @@ -353,17 +361,17 @@
>>
>>  	w->i = i;
>>  	w->mc.image = i;
>> -	r = insetrect(i->r, Selborder+1);
>> +	r = insetrect(i->r, wscale(w, Selborder)+wscale(w, 1));
>>  	w->scrollr = r;
>> -	w->scrollr.max.x = r.min.x+Scrollwid;
>> +	w->scrollr.max.x = r.min.x+wscale(w, Scrollwid);
>>  	w->lastsr = ZR;
>> -	r.min.x += Scrollwid+Scrollgap;
>> +	r.min.x += wscale(w, Scrollwid)+wscale(w, Scrollgap);
>>  	frclear(w, FALSE);
>>  	frinit(w, r, w->font, w->i, cols);
>>  	wsetcols(w, w == input);
>>  	w->maxtab = maxtab*stringwidth(w->font, "0");
>>  	if(!w->mouseopen || !w->winnameread){
>> -		r = insetrect(w->i->r, Selborder);
>> +		r = insetrect(w->i->r, wscale(w, Selborder));
>>  		draw(w->i, r, cols[BACK], nil, w->entire.min);
>>  		wfill(w);
>>  		wsetselect(w, w->q0, w->q1);
>> @@ -370,7 +378,7 @@
>>  		wscrdraw(w);
>>  	}
>>  	if(w == input)
>> -		wborder(w, Selborder);
>> +		wborder(w, wscale(w, Selborder));
>>  	else
>>  		wborder(w, Unselborder);
>>  	flushimage(display, 1);
>> @@ -390,9 +398,9 @@
>>  	if(!w->mouseopen || !w->winnameread)
>>  		frredraw(w);
>>  	if(w == input)
>> -		wborder(w, Selborder);
>> +		wborder(w, wscale(w, Selborder));
>>  	else
>> -		wborder(w, Unselborder);
>> +		wborder(w, wscale(w, Unselborder));
>>  }
>>
>>  static void
>> @@ -401,9 +409,9 @@
>>  	Rectangle r;
>>
>>  	if(w == input)
>> -		wborder(w, Selborder);
>> +		wborder(w, wscale(w, Selborder));
>>  	else
>> -		wborder(w, Unselborder);
>> +		wborder(w, wscale(w, Unselborder));
>>  	r = insetrect(w->i->r, Selborder);
>>  	draw(w->i, r, w->cols[BACK], nil, w->entire.min);
>>  	wfill(w);
>> @@ -1249,7 +1257,7 @@
>>
>>  	w = emalloc(sizeof(Window));
>>  	w->screenr = i->r;
>> -	r = insetrect(i->r, Selborder+1);
>> +	r = insetrect(i->r, wscale(w, Selborder)+wscale(w, 1));
>>  	w->i = i;
>>  	w->mc = *mc;
>>  	w->ck = ck;
>> @@ -1263,9 +1271,9 @@
>>  	w->complete = chancreate(sizeof(Completion*), 0);
>>  	w->gone = chancreate(sizeof(char*), 0);
>>  	w->scrollr = r;
>> -	w->scrollr.max.x = r.min.x+Scrollwid;
>> +	w->scrollr.max.x = r.min.x+wscale(w, Scrollwid);
>>  	w->lastsr = ZR;
>> -	r.min.x += Scrollwid+Scrollgap;
>> +	r.min.x += wscale(w, Scrollwid)+wscale(w, Scrollgap);
>>  	frinit(w, r, font, i, cols);
>>  	w->maxtab = maxtab*stringwidth(font, "0");
>>  	w->topped = ++topped;
>> @@ -1274,9 +1282,9 @@
>>  	w->scrolling = scrolling;
>>  	w->dir = estrdup(startdir);
>>  	w->label = estrdup("<unnamed>");
>> -	r = insetrect(w->i->r, Selborder);
>> +	r = insetrect(w->i->r, wscale(w, Selborder));
>>  	draw(w->i, r, cols[BACK], nil, w->entire.min);
>> -	wborder(w, Selborder);
>> +	wborder(w, wscale(w, Selborder));
>>  	wscrdraw(w);
>>  	incref(w);	/* ref will be removed after mounting; avoids delete before
>> ready to be deleted */
>>  	return w;
>> --- a/sys/src/libdraw/init.c
>> +++ b/sys/src/libdraw/init.c
>> @@ -452,5 +465,13 @@
>>  	p = d->bufp;
>>  	d->bufp += n;
>>  	return p;
>> +}
>> +
>> +int
>> +scalesize(Display *d, int n)
>> +{
>> +	if(d == nil || d->dpi <= DefaultDPI)
>> +		return n;
>> +	return (n*d->dpi+DefaultDPI/2)/DefaultDPI;
>>  }
>>
>> --
>>
>> 4th Patch (drawterm-metal-cocoa - I've been using this most of the time):
>>
>> diff 0b7990cf2b84e7a80cf3f3a9e7eadca10d51a2c5 uncommitted
>> --- a/include/draw.h
>> +++ b/include/draw.h
>> @@ -193,6 +193,7 @@
>>  	Image		*windows;
>>  	Image		*screenimage;
>>  	int		_isnewdisplay;
>> +	int		dpi;
>>  };
>>
>>  struct Image
>> --- a/kern/devdraw.c
>> +++ b/kern/devdraw.c
>> @@ -76,6 +76,8 @@
>>  	int		refreshme;
>>  	int		infoid;
>>  	int		op;
>> +	int		displaydpi;
>> +	int		forcedpi;
>>  };
>>
>>  struct Refresh
>> @@ -166,6 +168,8 @@
>>  	Client*		drawclientofpath(ulong);
>>  	DImage*	allocdimage(Memimage*);
>>
>> +int displaydpi = 200;
>> +
>>  static	char Enodrawimage[] =	"unknown id for draw image";
>>  static	char Enodrawscreen[] =	"unknown id for draw screen";
>>  static	char Eshortdraw[] =	"short draw message";
>> @@ -783,6 +787,7 @@
>>  	cl->slot = i;
>>  	cl->clientid = ++sdraw.clientid;
>>  	cl->op = SoverD;
>> +	cl->displaydpi = displaydpi;
>>  	sdraw.client[i] = cl;
>>  	return cl;
>>  }
>> @@ -1408,6 +1413,7 @@
>>  	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy,
>> oesize, esize, doflush;
>>  	uchar *u, *a, refresh;
>>  	char *fmt;
>> +	Fmt f;
>>  	ulong value, chan;
>>  	Rectangle r, clipr;
>>  	Point p, q, *pp, sp;
>> @@ -1654,6 +1660,34 @@
>>  			memset(font->fchar, 0, ni*sizeof(FChar));
>>  			font->nfchar = ni;
>>  			font->ascent = a[9];
>> +			continue;
>> +
>> +		/* query: 'Q' n[1] queryspec[n] */
>> +		case 'q':
>> +			if(n < 2)
>> +				error(Eshortdraw);
>> +			m = 1+1+a[1];
>> +			if(n < m)
>> +				error(Eshortdraw);
>> +			fmtstrinit(&f);
>> +			for(c=0; c<a[1]; c++){
>> +				switch(a[2+c]){
>> +				default:
>> +					error("unknown query");
>> +					break;
>> +				case 'd':       /* dpi */
>> +					if(client->forcedpi)
>> +						fmtprint(&f, "%11d ", client->forcedpi);
>> +					else {
>> +						fmtprint(&f, "%11d ", client->displaydpi);
>> +					}
>> +					break;
>> +				}
>> +			}
>> +			client->readdata = (uchar*)fmtstrflush(&f);
>> +			if(client->readdata == nil)
>> +				error(Enomem);
>> +			client->nreaddata = strlen((char*)client->readdata);
>>  			continue;
>>
>>  		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4]
>> left[1] width[1] */
>>
>>
>
>

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

* Re: [9front] hidpi
  2021-12-20 17:59 ` [9front] hidpi igor
  2021-12-20 18:28   ` hiro
@ 2021-12-20 19:02   ` Philip Silva
  1 sibling, 0 replies; 19+ messages in thread
From: Philip Silva @ 2021-12-20 19:02 UTC (permalink / raw)
  To: 9front

Yes exactly. I mean at least the first patch would just add the fields displaydpi+forcedpi to the Display struct and allow querying those. So it would be possible to have applications to deal with different DPIs.

 From what I understand from the plan9port code, on macOS it makes a smart guess [1] if it's retina or not (=> displaydpi value). Also users can toggle CMD+R [2] and toggle that manually (=> forcedpi value).

[1] https://github.com/9fans/plan9port/blob/master/src/cmd/devdraw/mac-screen.m#L480
[2] https://github.com/9fans/plan9port/blob/master/src/cmd/devdraw/srv.c#L521

> I don't like *automatically* setting DPI depending on what lies Xorg tells us.

True that's quite a pain. Maybe that's why it's such a mess on Linux.

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐

On Monday, December 20th, 2021 at 18:59, <igor@9lab.org> wrote:

> Hi Philip,
>
> This reminds me of a plan9port feature to change DPI (useful
>
> on a high res display, e.g. Retina display). Are you trying
>
> to achieve something similar as this:
>
> • https://groups.google.com/g/plan9port-dev/c/rXtpIufTrbM
>
> • https://github.com/9fans/plan9port/blob/master/src/cmd/devdraw/devdraw.c#L976
>

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

* Re: [9front] Re: hidpi
  2021-12-20 17:04 ` [9front] hidpi Philip Silva
  2021-12-20 17:29   ` hiro
@ 2021-12-20 19:15   ` Noam Preil
  2021-12-20 19:34     ` ori
  1 sibling, 1 reply; 19+ messages in thread
From: Noam Preil @ 2021-12-20 19:15 UTC (permalink / raw)
  To: Philip Silva


>> are you sure though that we need to do this on devdraw level?
>
> Not really sure to be honest, I only have a rough idea about libdraw or 
> how to exchange configuration options. At least in plan9port there is 
> also the new q(1d) command to query DPIs and 9fans.net/go/draw uses it 
> as well. I wonder whether this could be realized by just using 
> environment variables instead of configuring this through plan9.ini/the 
> result of q1d in drawterm.

I think env variables are the wrong approach, at least in terms of ideal 
future behavior. With (hypothetical future) multimonitor support (or a 
short-term hack binding in a second machine's /dev/draw) you'd want 
per-monitor DPI configuration---i.e. if you start a program on one 
monitor, then move it to the other (with a /dev/draw shim which can be 
attached and detached from specific backends, and multiplexed, etc), DPI 
should change.

I think devdraw is thus *exactly* where this information belongs, as DPI 
is dependent on the monitor, and that information is in devdraw's domain.

- Noam Preil

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

* Re: [9front] hidpi
  2021-12-20 18:28   ` hiro
@ 2021-12-20 19:27     ` Noam Preil
  0 siblings, 0 replies; 19+ messages in thread
From: Noam Preil @ 2021-12-20 19:27 UTC (permalink / raw)
  To: hiro


> Due to variable distance to the screen and variable quality of user's
> eyes, the hardware reporting of DPI becomes quite irrelevant.
>
> So for simplicity I propose devdraw and thus drawterm does *not* get
> an interface

On the contrary, wouldn't the simplest option be for devdraw to have an 
interface for changing it? Then, in a terminal within drawterm, you can 
trivially alter the DPI to suit your needs.

- Noam Preil

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

* Re: [9front] Re: hidpi
  2021-12-20 19:15   ` Noam Preil
@ 2021-12-20 19:34     ` ori
  2021-12-20 20:50       ` ori
  2021-12-20 21:47       ` Noam Preil
  0 siblings, 2 replies; 19+ messages in thread
From: ori @ 2021-12-20 19:34 UTC (permalink / raw)
  To: 9front

Quoth Noam Preil <noam@pixelhero.dev>:
> 
> >> are you sure though that we need to do this on devdraw level?
> >
> > Not really sure to be honest, I only have a rough idea about libdraw or 
> > how to exchange configuration options. At least in plan9port there is 
> > also the new q(1d) command to query DPIs and 9fans.net/go/draw uses it 
> > as well. I wonder whether this could be realized by just using 
> > environment variables instead of configuring this through plan9.ini/the 
> > result of q1d in drawterm.
> 
> I think env variables are the wrong approach, at least in terms of ideal 
> future behavior. With (hypothetical future) multimonitor support (or a 
> short-term hack binding in a second machine's /dev/draw) you'd want 
> per-monitor DPI configuration---i.e. if you start a program on one 
> monitor, then move it to the other (with a /dev/draw shim which can be 
> attached and detached from specific backends, and multiplexed, etc), DPI 
> should change.
> 
> I think devdraw is thus *exactly* where this information belongs, as DPI 
> is dependent on the monitor, and that information is in devdraw's domain.
> 
> - Noam Preil
> 

Yes, but not in the draw device itself:

	/dev/draw/geom

which presents a sequence of numbers, 6 to a line,
representing the screen rectangle in size and pixels;
each line represents one monitor.

libdraw and other programs that care can read this.


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

* Re: [9front] Re: hidpi
  2021-12-20 19:34     ` ori
@ 2021-12-20 20:50       ` ori
  2021-12-20 21:10         ` hiro
  2021-12-21  0:29         ` Philip Silva
  2021-12-20 21:47       ` Noam Preil
  1 sibling, 2 replies; 19+ messages in thread
From: ori @ 2021-12-20 20:50 UTC (permalink / raw)
  To: 9front

Quoth ori@eigenstate.org:
> the screen rectangle in size and pixels;

er. in pixels and mm, eg:

	#    x0     y0      x1    y1   width   height
	      0      0   3840   2160     527      296


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

* Re: [9front] Re: hidpi
  2021-12-20 20:50       ` ori
@ 2021-12-20 21:10         ` hiro
  2021-12-20 21:19           ` ori
  2021-12-21  0:29         ` Philip Silva
  1 sibling, 1 reply; 19+ messages in thread
From: hiro @ 2021-12-20 21:10 UTC (permalink / raw)
  To: 9front

mm can be calculated from dpi and amount of pixels. this doesn't add
anything to the game

On 12/20/21, ori@eigenstate.org <ori@eigenstate.org> wrote:
> Quoth ori@eigenstate.org:
>> the screen rectangle in size and pixels;
>
> er. in pixels and mm, eg:
>
> 	#    x0     y0      x1    y1   width   height
> 	      0      0   3840   2160     527      296
>
>

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

* Re: [9front] Re: hidpi
  2021-12-20 21:10         ` hiro
@ 2021-12-20 21:19           ` ori
  2021-12-20 22:02             ` sirjofri
  0 siblings, 1 reply; 19+ messages in thread
From: ori @ 2021-12-20 21:19 UTC (permalink / raw)
  To: 9front

Quoth hiro <23hiro@gmail.com>:
> 
> mm can be calculated from dpi and amount of pixels. this doesn't add
> anything to the game

I'm not suggesting exposing both mm and dpi. The
two are interchangable, and either one is fine.

the key point is that it sits outside of devdraw,
not as part of the draw protocol. the second point
is that it's easy to extend to multihead; eg, on
a triple head setup it would look something like:

      0      0   3840   2160     527      296
   3840      0   7680   2160     527      296
   7680      0  11520   2160     527      296

(multihead has been on my wishlist for a long
time, and I want to work on it soon.)


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

* Re: [9front] Re: hidpi
  2021-12-20 19:34     ` ori
  2021-12-20 20:50       ` ori
@ 2021-12-20 21:47       ` Noam Preil
  1 sibling, 0 replies; 19+ messages in thread
From: Noam Preil @ 2021-12-20 21:47 UTC (permalink / raw)
  To: 9front

Re: mm vs DPI: with VGA, physical size is already available. aux/vga can 
report it accurately, at least on my server.

I think /dev/draw/geom giving both virtual size in pixels and physical 
size in mm is the right approach. An  additional event to tell 
applications it has changed would also be useful.

Possibly also a read/write /dev/draw/dpi or something would also be nice, 
and make it nice and easy to change DPI on demand.

- Noam Preil

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

* Re: [9front] Re: hidpi
  2021-12-20 21:19           ` ori
@ 2021-12-20 22:02             ` sirjofri
  0 siblings, 0 replies; 19+ messages in thread
From: sirjofri @ 2021-12-20 22:02 UTC (permalink / raw)
  To: 9front

Hello,

all this stuff will be very helpful when creating a good Plan 9 interface 
for phones. The pinephone is currently on top of my desk and I hope to be 
able to do first tests with it (without destroying the hardware by 
setting wrong voltage values). Wish me luck

sirjofri

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

* Re: [9front] Re: hidpi
  2021-12-20 20:50       ` ori
  2021-12-20 21:10         ` hiro
@ 2021-12-21  0:29         ` Philip Silva
  2021-12-21  8:37           ` hiro
  1 sibling, 1 reply; 19+ messages in thread
From: Philip Silva @ 2021-12-21  0:29 UTC (permalink / raw)
  To: 9front

On the other hand speaking of different viewing distances/ideal widget sizes when things should be larger or smaller, it might be necessary to lie about mm (or dpi). Another option would be to just define scaling factors so scrollbars have practical sizes:

0 0 3840 2160 2.2 2.2

(Also I wonder if making widget sizes like scrollbar widths a pre-defined multiple of the font height would already work... Or if it's necessary to scale both independently)

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐

On Monday, December 20th, 2021 at 21:50, <ori@eigenstate.org> wrote:

> Quoth ori@eigenstate.org:
>
> > the screen rectangle in size and pixels;
>
> er. in pixels and mm, eg:
>
> # x0 y0 x1 y1 width height
>
> 0 0 3840 2160 527 296

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

* Re: [9front] Re: hidpi
  2021-12-21  0:29         ` Philip Silva
@ 2021-12-21  8:37           ` hiro
  0 siblings, 0 replies; 19+ messages in thread
From: hiro @ 2021-12-21  8:37 UTC (permalink / raw)
  To: 9front

yes, a more neutral scaling factor sounds like it would confuse less people.

and locking in with the fontsizes sounds like a great idea to me!

On 12/21/21, Philip Silva <philip.silva@protonmail.com> wrote:
> On the other hand speaking of different viewing distances/ideal widget sizes
> when things should be larger or smaller, it might be necessary to lie about
> mm (or dpi). Another option would be to just define scaling factors so
> scrollbars have practical sizes:
>
> 0 0 3840 2160 2.2 2.2
>
> (Also I wonder if making widget sizes like scrollbar widths a pre-defined
> multiple of the font height would already work... Or if it's necessary to
> scale both independently)
>
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
>
> On Monday, December 20th, 2021 at 21:50, <ori@eigenstate.org> wrote:
>
>> Quoth ori@eigenstate.org:
>>
>> > the screen rectangle in size and pixels;
>>
>> er. in pixels and mm, eg:
>>
>> # x0 y0 x1 y1 width height
>>
>> 0 0 3840 2160 527 296
>

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

* Re: [9front] hidpi
  2021-12-20 16:13 [9front] hidpi Philip Silva
                   ` (2 preceding siblings ...)
  2021-12-20 17:59 ` [9front] hidpi igor
@ 2021-12-22  8:39 ` igor
  2021-12-22 11:31   ` Philip Silva
  3 siblings, 1 reply; 19+ messages in thread
From: igor @ 2021-12-22  8:39 UTC (permalink / raw)
  To: 9front

Quoth Philip Silva <philip.silva@protonmail.com>:
[…]
> - glitches: the borders aren't calculated correctly (3rd patch for rio and acme is very wip)
[…]

By glitches, do you mean issues like the one here:

• https://9lab.org/img/plan9/acid.png

…where there is an issue in computing the column growth ⁽¹⁾ (I think)
manifesting itself as an artefact that looks like a white line at the
bottom of an acme column.  On small res displays this isn't
noticeable, however, on high-res screens it is annoying.

I stopped half way through due to lack of time debugging this
(still on my todo list), and was wondering if you observed the
same glitch.

⁽¹⁾ … https://9lab.org/plan9/debugging-with-acid/

> --
> 
> 
> 1st Patch for libdraw and devdraw:
> 
> diff c7dcc82b0be805717efbe77c98eaadf3ee1e31af uncommitted
> --- a/sys/include/ape/draw.h
> +++ b/sys/include/ape/draw.h
> @@ -208,6 +208,7 @@
>  	Image		*windows;
>  	Image		*screenimage;
>  	int			_isnewdisplay;
> +	int			dpi;
>  };
> 
>  struct Image
> --- a/sys/include/draw.h
> +++ b/sys/include/draw.h
> @@ -200,6 +200,7 @@
>  	Image		*windows;
>  	Image		*screenimage;
>  	int		_isnewdisplay;
> +	int		dpi;
>  };
> 
>  struct Image
> --- a/sys/src/9/port/devdraw.c
> +++ b/sys/src/9/port/devdraw.c
> @@ -77,6 +77,8 @@
>  	int		refreshme;
>  	int		infoid;
>  	int		op;
> +	int		displaydpi;
> +	int		forcedpi;
>  };
> 
>  struct Refresh
> @@ -785,6 +789,7 @@
>  	cl->slot = i;
>  	cl->clientid = ++sdraw.clientid;
>  	cl->op = SoverD;
> +	cl->displaydpi=100;
>  	sdraw.client[i] = cl;
>  	return cl;
>  }
> @@ -1396,6 +1401,7 @@
>  	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
>  	uchar *u, *a, refresh;
>  	char *fmt;
> +	Fmt f;
>  	ulong value, chan;
>  	Rectangle r, clipr;
>  	Point p, q, *pp, sp;
> @@ -1643,6 +1649,35 @@
>  			font->nfchar = ni;
>  			font->ascent = a[9];
>  			continue;
> +
> +		/* query: 'Q' n[1] queryspec[n] */
> +		case 'q':
> +			if(n < 2){
> +				error(Eshortdraw);
> +			}
> +			m = 1+1+a[1];
> +			if(n < m){
> +				error(Eshortdraw);
> +			}
> +			fmtstrinit(&f);
> +			for(c=0; c<a[1]; c++){
> +				switch(a[2+c]){
> +				default:
> +					error("unknown query");
> +				case 'd':       /* dpi */
> +					if(client->forcedpi)
> +						fmtprint(&f, "%11d ", client->forcedpi);
> +					else
> +						fmtprint(&f, "%11d ", client->displaydpi);
> +					break;
> +				}
> +			}
> +			client->readdata = (uchar*)fmtstrflush(&f);
> +			if(client->readdata == nil)
> +				error(Enomem);
> +			client->nreaddata = strlen((char*)client->readdata);
> +			continue;
> +
> 
>  		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
>  		case 'l':
> --- a/sys/src/libdraw/init.c
> +++ b/sys/src/libdraw/init.c
> @@ -197,6 +197,7 @@
>  Display*
>  initdisplay(char *dev, char *win, void(*error)(Display*, char*))
>  {
> +	uchar *a;
>  	char buf[128], info[NINFO+1], *t, isnew;
>  	int n, datafd, ctlfd, reffd;
>  	Display *disp;
> @@ -319,6 +320,18 @@
>  	if(dir!=nil && dir->qid.vers==1)	/* other way to tell */
>  		disp->_isnewdisplay = 1;
>  	free(dir);
> +
> +	a = bufimage(disp, 3);
> +	if(a == nil)
> +		goto Error5;
> +	a[0] = 'q';
> +	a[1] = 1;
> +	a[2] = 'd';
> +	disp->dpi = 100;
> +	if(flushimage(disp, 0) >= 0){
> +		if((read(datafd, info, sizeof info)) == 12)
> +			disp->dpi = atoi(info);
> +	}
> 
>  	return disp;
>  }
> 
> --
> 
> 2nd Patch for plan9.ini:
> 
> diff c7dcc82b0be805717efbe77c98eaadf3ee1e31af uncommitted
> --- a/sys/man/8/plan9.ini
> +++ b/sys/man/8/plan9.ini
> @@ -971,6 +971,8 @@
>  .BR off .
>  The first two specify differing levels of power saving;
>  the third turns the monitor off completely.
> +.SS \fL*dpi=\fIvalue\fP
> +This is used to specify the screen dpi.
>  .SS NVRAM
>  .SS \fLnvram=\fIfile\fP
>  .SS \fLnvrlen=\fIlength\fP
> --- a/sys/src/9/port/devdraw.c
> +++ b/sys/src/9/port/devdraw.c
> @@ -765,6 +765,7 @@
>  drawnewclient(void)
>  {
>  	Client *cl, **cp;
> +	char *p;
>  	int i;
> 
>  	for(i=0; i<sdraw.nclient; i++){
> @@ -789,7 +790,9 @@
>  	cl->slot = i;
>  	cl->clientid = ++sdraw.clientid;
>  	cl->op = SoverD;
> -	cl->displaydpi=100;
> +	if((p = getconf("dpi")) == nil || (cl->displaydpi = atoi(p)) == 0){
> +		cl->displaydpi=100;
> +	}
>  	sdraw.client[i] = cl;
>  	return cl;
>  }
> 
> --
> 
> 3rd Patch for rio/acme (proof-of-concept, just to provide an example)
> 
> diff 75d8e460a00505c2b21a0d06ceb4300c93d9c4d6 uncommitted
> --- a/sys/include/ape/draw.h
> +++ b/sys/include/ape/draw.h
> @@ -69,6 +69,7 @@
>  	Displaybufsize	= 8000,
>  	ICOSSCALE	= 1024,
>  	Borderwidth =	4,
> +	DefaultDPI  =	100,
>  };
> 
>  enum
> @@ -358,6 +359,7 @@
>  extern Image*	namedimage(Display*, char*);
>  extern int	nameimage(Image*, char*, int);
>  extern Image* allocimagemix(Display*, ulong, ulong);
> +extern int scalesize(Display*, int);
> 
>  /*
>   * Colors
> --- a/sys/include/draw.h
> +++ b/sys/include/draw.h
> @@ -61,6 +61,7 @@
>  	Displaybufsize	= 8000,
>  	ICOSSCALE	= 1024,
>  	Borderwidth =	4,
> +	DefaultDPI  =	100,
>  };
> 
>  enum
> @@ -354,6 +355,7 @@
>  extern Image*	namedimage(Display*, char*);
>  extern int	nameimage(Image*, char*, int);
>  extern Image* allocimagemix(Display*, ulong, ulong);
> +extern int scalesize(Display*, int);
> 
>  /*
>   * Colors
> --- a/sys/src/cmd/acme/dat.h
> +++ b/sys/src/cmd/acme/dat.h
> @@ -473,11 +473,14 @@
>  	BUFSIZE = Maxblock+IOHDRSZ,	/* size from fbufalloc() */
>  	RBUFSIZE = BUFSIZE/sizeof(Rune),
>  	EVENTSIZE = 256,
> -	Scrollwid = 12,	/* width of scroll bar */
> -	Scrollgap = 4,	/* gap right of scroll bar */
> -	Margin = 4,	/* margin around text */
> -	Border = 2,	/* line between rows, cols, windows */
>  };
> +
> +// like in p9p c96d832
> +#define Scrollwid scalesize(display, 12)	/* width of scroll bar */
> +#define Scrollgap scalesize(display, 4)	/* gap right of scroll bar */
> +#define Margin scalesize(display, 4)	/* margin around text */
> +#define Border scalesize(display, 2)	/* line between rows, cols, windows */
> +#define ButtonBorder scalesize(display, 2)
> 
>  #define	QID(w,q)	((w<<8)|(q))
>  #define	WIN(q)	((((ulong)(q).path)>>8) & 0xFFFFFF)
> --- a/sys/src/cmd/rio/wind.c
> +++ b/sys/src/cmd/rio/wind.c
> @@ -12,6 +12,14 @@
>  #include "dat.h"
>  #include "fns.h"
> 
> +static int
> +wscale(Window *w, int n)
> +{
> +        if(w == nil || w->i == nil)
> +                return n;
> +        return scalesize(w->i->display, n);
> +}
> +
>  Window*
>  wlookid(int id)
>  {
> @@ -308,7 +316,7 @@
>  		else
>  			col = lighttitlecol;
>  	}
> -	border(w->i, w->i->r, Selborder, col, ZP);
> +	border(w->i, w->i->r, wscale(w, Selborder), col, ZP);
>  }
> 
>  static void
> @@ -353,17 +361,17 @@
> 
>  	w->i = i;
>  	w->mc.image = i;
> -	r = insetrect(i->r, Selborder+1);
> +	r = insetrect(i->r, wscale(w, Selborder)+wscale(w, 1));
>  	w->scrollr = r;
> -	w->scrollr.max.x = r.min.x+Scrollwid;
> +	w->scrollr.max.x = r.min.x+wscale(w, Scrollwid);
>  	w->lastsr = ZR;
> -	r.min.x += Scrollwid+Scrollgap;
> +	r.min.x += wscale(w, Scrollwid)+wscale(w, Scrollgap);
>  	frclear(w, FALSE);
>  	frinit(w, r, w->font, w->i, cols);
>  	wsetcols(w, w == input);
>  	w->maxtab = maxtab*stringwidth(w->font, "0");
>  	if(!w->mouseopen || !w->winnameread){
> -		r = insetrect(w->i->r, Selborder);
> +		r = insetrect(w->i->r, wscale(w, Selborder));
>  		draw(w->i, r, cols[BACK], nil, w->entire.min);
>  		wfill(w);
>  		wsetselect(w, w->q0, w->q1);
> @@ -370,7 +378,7 @@
>  		wscrdraw(w);
>  	}
>  	if(w == input)
> -		wborder(w, Selborder);
> +		wborder(w, wscale(w, Selborder));
>  	else
>  		wborder(w, Unselborder);
>  	flushimage(display, 1);
> @@ -390,9 +398,9 @@
>  	if(!w->mouseopen || !w->winnameread)
>  		frredraw(w);
>  	if(w == input)
> -		wborder(w, Selborder);
> +		wborder(w, wscale(w, Selborder));
>  	else
> -		wborder(w, Unselborder);
> +		wborder(w, wscale(w, Unselborder));
>  }
> 
>  static void
> @@ -401,9 +409,9 @@
>  	Rectangle r;
> 
>  	if(w == input)
> -		wborder(w, Selborder);
> +		wborder(w, wscale(w, Selborder));
>  	else
> -		wborder(w, Unselborder);
> +		wborder(w, wscale(w, Unselborder));
>  	r = insetrect(w->i->r, Selborder);
>  	draw(w->i, r, w->cols[BACK], nil, w->entire.min);
>  	wfill(w);
> @@ -1249,7 +1257,7 @@
> 
>  	w = emalloc(sizeof(Window));
>  	w->screenr = i->r;
> -	r = insetrect(i->r, Selborder+1);
> +	r = insetrect(i->r, wscale(w, Selborder)+wscale(w, 1));
>  	w->i = i;
>  	w->mc = *mc;
>  	w->ck = ck;
> @@ -1263,9 +1271,9 @@
>  	w->complete = chancreate(sizeof(Completion*), 0);
>  	w->gone = chancreate(sizeof(char*), 0);
>  	w->scrollr = r;
> -	w->scrollr.max.x = r.min.x+Scrollwid;
> +	w->scrollr.max.x = r.min.x+wscale(w, Scrollwid);
>  	w->lastsr = ZR;
> -	r.min.x += Scrollwid+Scrollgap;
> +	r.min.x += wscale(w, Scrollwid)+wscale(w, Scrollgap);
>  	frinit(w, r, font, i, cols);
>  	w->maxtab = maxtab*stringwidth(font, "0");
>  	w->topped = ++topped;
> @@ -1274,9 +1282,9 @@
>  	w->scrolling = scrolling;
>  	w->dir = estrdup(startdir);
>  	w->label = estrdup("<unnamed>");
> -	r = insetrect(w->i->r, Selborder);
> +	r = insetrect(w->i->r, wscale(w, Selborder));
>  	draw(w->i, r, cols[BACK], nil, w->entire.min);
> -	wborder(w, Selborder);
> +	wborder(w, wscale(w, Selborder));
>  	wscrdraw(w);
>  	incref(w);	/* ref will be removed after mounting; avoids delete before ready to be deleted */
>  	return w;
> --- a/sys/src/libdraw/init.c
> +++ b/sys/src/libdraw/init.c
> @@ -452,5 +465,13 @@
>  	p = d->bufp;
>  	d->bufp += n;
>  	return p;
> +}
> +
> +int
> +scalesize(Display *d, int n)
> +{
> +	if(d == nil || d->dpi <= DefaultDPI)
> +		return n;
> +	return (n*d->dpi+DefaultDPI/2)/DefaultDPI;
>  }
> 
> --
> 
> 4th Patch (drawterm-metal-cocoa - I've been using this most of the time):
> 
> diff 0b7990cf2b84e7a80cf3f3a9e7eadca10d51a2c5 uncommitted
> --- a/include/draw.h
> +++ b/include/draw.h
> @@ -193,6 +193,7 @@
>  	Image		*windows;
>  	Image		*screenimage;
>  	int		_isnewdisplay;
> +	int		dpi;
>  };
> 
>  struct Image
> --- a/kern/devdraw.c
> +++ b/kern/devdraw.c
> @@ -76,6 +76,8 @@
>  	int		refreshme;
>  	int		infoid;
>  	int		op;
> +	int		displaydpi;
> +	int		forcedpi;
>  };
> 
>  struct Refresh
> @@ -166,6 +168,8 @@
>  	Client*		drawclientofpath(ulong);
>  	DImage*	allocdimage(Memimage*);
> 
> +int displaydpi = 200;
> +
>  static	char Enodrawimage[] =	"unknown id for draw image";
>  static	char Enodrawscreen[] =	"unknown id for draw screen";
>  static	char Eshortdraw[] =	"short draw message";
> @@ -783,6 +787,7 @@
>  	cl->slot = i;
>  	cl->clientid = ++sdraw.clientid;
>  	cl->op = SoverD;
> +	cl->displaydpi = displaydpi;
>  	sdraw.client[i] = cl;
>  	return cl;
>  }
> @@ -1408,6 +1413,7 @@
>  	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
>  	uchar *u, *a, refresh;
>  	char *fmt;
> +	Fmt f;
>  	ulong value, chan;
>  	Rectangle r, clipr;
>  	Point p, q, *pp, sp;
> @@ -1654,6 +1660,34 @@
>  			memset(font->fchar, 0, ni*sizeof(FChar));
>  			font->nfchar = ni;
>  			font->ascent = a[9];
> +			continue;
> +
> +		/* query: 'Q' n[1] queryspec[n] */
> +		case 'q':
> +			if(n < 2)
> +				error(Eshortdraw);
> +			m = 1+1+a[1];
> +			if(n < m)
> +				error(Eshortdraw);
> +			fmtstrinit(&f);
> +			for(c=0; c<a[1]; c++){
> +				switch(a[2+c]){
> +				default:
> +					error("unknown query");
> +					break;
> +				case 'd':       /* dpi */
> +					if(client->forcedpi)
> +						fmtprint(&f, "%11d ", client->forcedpi);
> +					else {
> +						fmtprint(&f, "%11d ", client->displaydpi);
> +					}
> +					break;
> +				}
> +			}
> +			client->readdata = (uchar*)fmtstrflush(&f);
> +			if(client->readdata == nil)
> +				error(Enomem);
> +			client->nreaddata = strlen((char*)client->readdata);
>  			continue;
> 
>  		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
> 
> 


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

* Re: [9front] hidpi
  2021-12-22  8:39 ` igor
@ 2021-12-22 11:31   ` Philip Silva
  0 siblings, 0 replies; 19+ messages in thread
From: Philip Silva @ 2021-12-22 11:31 UTC (permalink / raw)
  To: 9front

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

Ah ok, interesting. The one I remember is actually a similar y offset problem but in the opposite side (drawing into the now thicker border on top). That was in rio though. I must admit I mechanically copied the changes from plan9port where it seemed reasonable and then continued replacing where it looked right. So that code has kind of heuristic reasoning :) Cool I'll probably look first into trying some of the ideas mentioned once I'm in reach of my laptop again

-------- Original Message --------
On Dec 22, 2021, 9:39 AM, < igor@9lab.org> wrote:
Quoth Philip Silva <philip.silva@protonmail.com>:
[…]
> - glitches: the borders aren't calculated correctly (3rd patch for rio and acme is very wip)
[…]
By glitches, do you mean issues like the one here:
• https://9lab.org/img/plan9/acid.png
…where there is an issue in computing the column growth ⁽¹⁾ (I think)
manifesting itself as an artefact that looks like a white line at the
bottom of an acme column. On small res displays this isn't
noticeable, however, on high-res screens it is annoying.
I stopped half way through due to lack of time debugging this
(still on my todo list), and was wondering if you observed the
same glitch.
⁽¹⁾ … https://9lab.org/plan9/debugging-with-acid/

[-- Attachment #2: Type: text/html, Size: 1438 bytes --]

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

end of thread, other threads:[~2021-12-23  0:48 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-20 16:13 [9front] hidpi Philip Silva
2021-12-20 16:34 ` hiro
2021-12-20 17:04 ` [9front] hidpi Philip Silva
2021-12-20 17:29   ` hiro
2021-12-20 19:15   ` Noam Preil
2021-12-20 19:34     ` ori
2021-12-20 20:50       ` ori
2021-12-20 21:10         ` hiro
2021-12-20 21:19           ` ori
2021-12-20 22:02             ` sirjofri
2021-12-21  0:29         ` Philip Silva
2021-12-21  8:37           ` hiro
2021-12-20 21:47       ` Noam Preil
2021-12-20 17:59 ` [9front] hidpi igor
2021-12-20 18:28   ` hiro
2021-12-20 19:27     ` Noam Preil
2021-12-20 19:02   ` Philip Silva
2021-12-22  8:39 ` igor
2021-12-22 11:31   ` Philip Silva

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).