fix: calm down winwatch and assure its full repaint

This commit is contained in:
MvA
2026-02-01 08:34:06 +01:00
committed by Dan Cross
parent 0155f29bdc
commit 552faac470

View File

@@ -35,7 +35,9 @@ int sortlabels;
int showwmnames; int showwmnames;
extern Font *font; extern Font *font;
Image *lightblue; Image *lightblue;
Image *backbuffer = nil;
vlong last = 0;
vlong now;
enum { enum {
PAD = 3, PAD = 3,
@@ -276,7 +278,7 @@ refreshwin(void)
} }
void void
drawnowin(int i) drawnowin(Image *dst, int i)
{ {
Rectangle r; Rectangle r;
@@ -286,17 +288,17 @@ drawnowin(int i)
Pt(MARGIN + (PAD + Dx(r)) * (i / rows), Pt(MARGIN + (PAD + Dx(r)) * (i / rows),
MARGIN + (PAD + Dy(r)) * (i % rows))), MARGIN + (PAD + Dy(r)) * (i % rows))),
screen->r.min); screen->r.min);
draw(screen, insetrect(r, -1), lightblue, nil, ZP); draw(dst, insetrect(r, -1), lightblue, nil, ZP);
} }
void void
drawwin(int i) drawwin(Image *dst, int i)
{ {
draw(screen, win[i].r, lightblue, nil, ZP); draw(dst, win[i].r, lightblue, nil, ZP);
_string(screen, addpt(win[i].r.min, Pt(2, 0)), display->black, ZP, _string(dst, addpt(win[i].r.min, Pt(2, 0)), display->black, ZP,
font, win[i].label, nil, strlen(win[i].label), font, win[i].label, nil, strlen(win[i].label),
win[i].r, nil, ZP, SoverD); 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; win[i].dirty = 0;
} }
@@ -336,17 +338,39 @@ redraw(Image *screen, int all)
int i; int i;
all |= geometry(); 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; i<nwin; i++) for(i=0; i<nwin; i++)
if(all || win[i].dirty) drawwin(backbuffer, i);
drawwin(i);
if(!all) for (; i<onwin; i++)
for (; i<onwin; i++) drawnowin(backbuffer, i);
drawnowin(i);
/* 4. Atomic Copy to Screen (The Fix) */
/* We use backbuffer->r.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; onwin = nwin;
} }
void void
eresized(int new) eresized(int new)
{ {
@@ -483,9 +507,18 @@ main(int argc, char **argv)
case Emouse: case Emouse:
if(e.mouse.buttons) if(e.mouse.buttons)
click(e.mouse); 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(); refreshwin();
/* Always redraw. It is cheap now, with the buffered drawing and the limited rate. */
redraw(screen, 0); redraw(screen, 0);
break; break;
} }