From 552faac4704380c066fffb3ead568e86e3d9b4b3 Mon Sep 17 00:00:00 2001 From: MvA Date: Sun, 1 Feb 2026 08:34:06 +0100 Subject: [PATCH] fix: calm down winwatch and assure its full repaint --- src/cmd/rio/winwatch.c | 65 +++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/src/cmd/rio/winwatch.c b/src/cmd/rio/winwatch.c index da021278..3c0c5b77 100644 --- a/src/cmd/rio/winwatch.c +++ b/src/cmd/rio/winwatch.c @@ -35,7 +35,9 @@ int sortlabels; int showwmnames; extern Font *font; Image *lightblue; - +Image *backbuffer = nil; +vlong last = 0; +vlong now; enum { PAD = 3, @@ -276,7 +278,7 @@ refreshwin(void) } void -drawnowin(int i) +drawnowin(Image *dst, int i) { Rectangle r; @@ -286,17 +288,17 @@ drawnowin(int i) Pt(MARGIN + (PAD + Dx(r)) * (i / rows), MARGIN + (PAD + Dy(r)) * (i % rows))), screen->r.min); - draw(screen, insetrect(r, -1), lightblue, nil, ZP); + draw(dst, insetrect(r, -1), lightblue, nil, ZP); } void -drawwin(int i) +drawwin(Image *dst, int i) { - draw(screen, win[i].r, lightblue, nil, ZP); - _string(screen, addpt(win[i].r.min, Pt(2, 0)), display->black, ZP, + draw(dst, win[i].r, lightblue, nil, ZP); + _string(dst, addpt(win[i].r.min, Pt(2, 0)), display->black, ZP, font, win[i].label, nil, strlen(win[i].label), win[i].r, nil, ZP, SoverD); - border(screen, win[i].r, 1, display->black, ZP); + border(dst, win[i].r, 1, display->black, ZP); win[i].dirty = 0; } @@ -336,17 +338,39 @@ redraw(Image *screen, int all) int i; all |= geometry(); - if(all) - draw(screen, screen->r, lightblue, nil, ZP); + + /* 1. Allocate/Resize buffer only if screen size changes */ + if(backbuffer == nil || Dx(backbuffer->r) != Dx(screen->r) || Dy(backbuffer->r) != Dy(screen->r)){ + if(backbuffer) + freeimage(backbuffer); + + /* Create buffer with the same coordinates as the screen */ + backbuffer = allocimage(display, screen->r, screen->chan, 0, DWhite); + if(backbuffer == nil) + return; + } + + /* 2. Paint background on the off-screen buffer */ + draw(backbuffer, backbuffer->r, lightblue, nil, ZP); + + /* 3. Draw all items onto the buffer */ for(i=0; ir.min as the source point, ensuring alignment */ + draw(screen, screen->r, backbuffer, nil, backbuffer->r.min); + + /* 5. Force the update to the X server immediately */ + flushimage(display, 1); + onwin = nwin; } + void eresized(int new) { @@ -483,9 +507,18 @@ main(int argc, char **argv) case Emouse: if(e.mouse.buttons) click(e.mouse); - /* fall through */ - default: /* Etimer */ + + /* Rate-limited fallthrough */ + now = nsec(); + /* If less than 200ms (200,000,000ns) has passed, skip refresh */ + if(now - last < 200*1000000LL) + break; + /* Otherwise, fall through to refresh */ + + default: /* Etimer */ + last = nsec(); refreshwin(); + /* Always redraw. It is cheap now, with the buffered drawing and the limited rate. */ redraw(screen, 0); break; }