Skip to content

Instantly share code, notes, and snippets.

@semanticentity
Created December 20, 2025 09:28
Show Gist options
  • Select an option

  • Save semanticentity/147734c5e4a35940928705e5f3c9e97a to your computer and use it in GitHub Desktop.

Select an option

Save semanticentity/147734c5e4a35940928705e5f3c9e97a to your computer and use it in GitHub Desktop.
Regions, Not Rectangles
<div id="app">
<header class="panel">
<div class="titleRow">
<h1>Regions, Not Rectangles</h1>
<div class="badge">Based on interview with <a href="https://www.youtube.com/watch?v=kGIIwyJ7G94" target="_blank">Bill Atkinson, discussing Lisa source code</a></div>
</div>
<p class="sub">
A web window manager demo: visible regions are stored as <strong>scanline deltas</strong> and rendered as
<strong>top‑down slabs</strong>. (This is the core idea Bill Atkinson is describing.)
</p>
<p class="quote">
“It’s not a rectangle of drawing space — it’s an arbitrary shape.”
</p>
</header>
<main class="layout">
<section class="stage panel">
<div class="stageTop">
<div class="kioskLabel">720 × 360 • 1‑bit vibe • region clipping</div>
<div id="hud" class="hud" aria-live="polite"></div>
</div>
<canvas id="ui" width="720" height="360" tabindex="0" aria-describedby="desc"></canvas>
<div class="hint">
Mouse: click to front, drag to move. Keyboard: <kbd>[</kbd>/<kbd>]</kbd> cycle, arrows move, <kbd>Enter</kbd> bring front.
</div>
</section>
<aside class="side">
<section class="panel controls">
<h2>Controls</h2>
<label class="row">
<input type="checkbox" id="showRegions" checked />
Show visible regions (x‑ray)
</label>
<label class="row">
<input type="checkbox" id="showBands" checked />
Show band breaks (where region shape changes)
</label>
<label class="row">
<input type="checkbox" id="naiveMode" />
Naive redraw (draw full rects; “Xerox‑ish”)
</label>
<label class="row">
Scan step
<select id="scanStep">
<option value="1" selected>1px (faithful)</option>
<option value="2">2px (faster)</option>
<option value="4">4px (coarser)</option>
</select>
</label>
</section>
<section class="panel windows">
<h2>Windows</h2>
<p class="mini">
These buttons are the <strong>semantic / a11y mirror</strong> (screen readers & SEO).
The canvas is just the visual + region engine.
</p>
<div id="winList" class="winList" role="list"></div>
</section>
<section id="desc" class="panel desc">
<h2>What you’re seeing</h2>
<ul>
<li><strong>Structure region</strong>: the full window rect.</li>
<li><strong>Visible region</strong>: structure minus any windows above it.</li>
<li>Visible region is stored as <strong>scanline spans</strong>, then <strong>compressed into bands</strong> (only when spans change).</li>
<li>Rendering copies only those spans as <strong>slabs</strong> — fast, like Bill’s “write in slabs top‑down” description.</li>
</ul>
</section>
</aside>
</main>
</div>
const canvas = document.getElementById("ui");
const ctx = canvas.getContext("2d");
const hud = document.getElementById("hud");
const winList = document.getElementById("winList");
const showRegions = document.getElementById("showRegions");
const showBands = document.getElementById("showBands");
const naiveMode = document.getElementById("naiveMode");
const scanStepSel = document.getElementById("scanStep");
const W = canvas.width;
const H = canvas.height;
let activeId = null;
let hoverId = null;
let dragging = null;
let dragOffset = { x: 0, y: 0 };
let layoutDirty = true;
let rafPending = false;
/* -------------------------
1‑bit-ish patterns
-------------------------- */
function makePattern(kind){
const p = document.createElement("canvas");
p.width = 8; p.height = 8;
const pctx = p.getContext("2d");
pctx.fillStyle = "#fff";
pctx.fillRect(0,0,8,8);
pctx.fillStyle = "#000";
if (kind === "light") {
// sparse dots
for (let y=0;y<8;y++){
for (let x=0;x<8;x++){
if ((x+y) % 7 === 0) pctx.fillRect(x,y,1,1);
}
}
} else if (kind === "mid") {
// checker
for (let y=0;y<8;y++){
for (let x=0;x<8;x++){
if ((x+y) % 2 === 0) pctx.fillRect(x,y,1,1);
}
}
} else if (kind === "diag") {
// diagonal stripes
for (let y=0;y<8;y++){
for (let x=0;x<8;x++){
if ((x - y + 16) % 4 === 0) pctx.fillRect(x,y,1,1);
}
}
}
return ctx.createPattern(p, "repeat");
}
const PAT_LIGHT = makePattern("light");
const PAT_MID = makePattern("mid");
const PAT_DIAG = makePattern("diag");
/* -------------------------
Windows (structure regions)
Order is back->front.
-------------------------- */
const windows = [
mkWindow("write", "Write", 48, 42, 320, 220, PAT_LIGHT, drawWrite),
mkWindow("chart", "Chart", 210, 80, 320, 220, PAT_MID, drawChart),
mkWindow("tools", "Tools", 430, 120, 240, 190, PAT_DIAG, drawTools),
];
activeId = windows[windows.length-1].id;
function mkWindow(id, title, x, y, w, h, fillPat, drawFn){
const win = {
id, title, x, y, w, h,
fillPat,
drawFn,
buf: null,
visibleBands: [], // computed
metrics: { bands:0, spans:0, pixels:0, blits:0 }
};
win.buf = renderWindowBuffer(win);
return win;
}
/* -------------------------
Offscreen buffer == “picture”
(recorded result; we blit parts)
-------------------------- */
function renderWindowBuffer(win){
const b = document.createElement("canvas");
b.width = win.w;
b.height = win.h;
const bctx = b.getContext("2d");
// frame
bctx.fillStyle = "#fff";
bctx.fillRect(0,0,win.w,win.h);
// title bar
const tb = 18;
bctx.fillStyle = win.fillPat;
bctx.fillRect(0,0,win.w,tb);
bctx.strokeStyle = "#000";
bctx.lineWidth = 2;
bctx.strokeRect(1,1,win.w-2,win.h-2);
// title text
bctx.fillStyle = "#000";
bctx.font = "12px monospace";
bctx.fillText(win.title, 10, 13);
// close box (purely visual)
bctx.strokeRect(4,4,10,10);
bctx.beginPath();
bctx.moveTo(5,5); bctx.lineTo(13,13);
bctx.moveTo(13,5); bctx.lineTo(5,13);
bctx.stroke();
// content
bctx.save();
bctx.translate(0, tb);
const innerH = win.h - tb;
bctx.fillStyle = "#fff";
bctx.fillRect(0,0,win.w,innerH);
// subtle dither background
bctx.globalAlpha = 0.25;
bctx.fillStyle = win.fillPat;
bctx.fillRect(0,0,win.w,innerH);
bctx.globalAlpha = 1;
// content drawing
win.drawFn(bctx, win.w, innerH);
bctx.restore();
return b;
}
/* -------------------------
Content functions
-------------------------- */
function drawWrite(bctx, w, h){
bctx.fillStyle = "#000";
bctx.font = "12px monospace";
const lines = [
"This window is BEHIND sometimes.",
"When covered, its visible region",
"becomes a puzzle piece.",
"",
"We don’t redraw rectangles.",
"We blit only visible slabs.",
];
let y = 18;
for (const s of lines){
bctx.fillText(s, 10, y);
y += 16;
}
// fake caret
bctx.fillRect(10, y+4, 2, 12);
}
function drawChart(bctx, w, h){
bctx.fillStyle = "#000";
bctx.font = "12px monospace";
bctx.fillText("Bars are drawn once into the buffer.", 10, 18);
const baseY = 160;
const bars = [40, 110, 70, 140, 95];
for (let i=0;i<bars.length;i++){
const x = 20 + i*50;
const bh = bars[i];
bctx.fillStyle = (i%2===0) ? "#000" : "#fff";
bctx.strokeStyle = "#000";
bctx.fillRect(x, baseY-bh, 28, bh);
bctx.strokeRect(x, baseY-bh, 28, bh);
}
// “pie” ring
bctx.beginPath();
bctx.arc(w-70, 120, 38, 0, Math.PI*1.35);
bctx.stroke();
}
function drawTools(bctx, w, h){
bctx.fillStyle = "#000";
bctx.font = "12px monospace";
bctx.fillText("Drag me on top.", 10, 18);
// knobs
for (let i=0;i<3;i++){
const cx = 40 + i*65;
const cy = 75;
bctx.beginPath();
bctx.arc(cx, cy, 18, 0, Math.PI*2);
bctx.stroke();
bctx.beginPath();
bctx.moveTo(cx, cy);
bctx.lineTo(cx+10, cy-8);
bctx.stroke();
}
// toggles
bctx.strokeRect(10, 110, w-20, 60);
bctx.fillText("Visible region math", 16, 132);
bctx.fillText("happens in the WM", 16, 150);
}
/* -------------------------
Region math: subtract occluders
We store as scanline spans, then
compress into “bands” where spans
don’t change across adjacent lines.
-------------------------- */
function subtractIntervalList(spans, cut){
const [c0, c1] = cut;
const out = [];
for (const [s0, s1] of spans){
if (c1 <= s0 || c0 >= s1) {
out.push([s0, s1]);
} else {
if (c0 > s0) out.push([s0, Math.min(c0, s1)]);
if (c1 < s1) out.push([Math.max(c1, s0), s1]);
}
}
return out;
}
function spansKey(spans){
// stable compare for band compression
return spans.map(([a,b]) => `${a},${b}`).join("|");
}
function computeVisibleBandsForWindow(i, step){
const win = windows[i];
const x0 = Math.max(0, Math.floor(win.x));
const y0 = Math.max(0, Math.floor(win.y));
const x1 = Math.min(W, Math.ceil(win.x + win.w));
const y1 = Math.min(H, Math.ceil(win.y + win.h));
const bands = [];
let band = null;
let prevKey = null;
// metrics
let bandCount = 0, spanCount = 0, pixels = 0, blits = 0;
for (let y=y0; y<y1; y+=step){
let spans = [[x0, x1]];
// subtract every window ABOVE (i+1..end)
for (let j=i+1; j<windows.length; j++){
const o = windows[j];
const oy0 = Math.floor(o.y);
const oy1 = Math.ceil(o.y + o.h);
if (y >= oy0 && y < oy1){
const cut = [Math.floor(o.x), Math.ceil(o.x + o.w)];
spans = subtractIntervalList(spans, cut);
if (spans.length === 0) break;
}
}
// clamp + clean
spans = spans
.map(([a,b]) => [Math.max(0,a), Math.min(W,b)])
.filter(([a,b]) => b > a);
const key = spansKey(spans);
if (band && key === prevKey) {
band.h += step;
} else {
if (band) bands.push(band);
band = { y, h: step, spans };
prevKey = key;
bandCount++;
}
for (const [a,b] of spans){
spanCount++;
pixels += (b-a) * step;
blits++;
}
}
if (band) bands.push(band);
win.metrics = { bands: bandCount, spans: spanCount, pixels, blits };
return bands;
}
function recomputeLayout(){
const step = parseInt(scanStepSel.value, 10);
for (let i=0;i<windows.length;i++){
windows[i].visibleBands = computeVisibleBandsForWindow(i, step);
}
layoutDirty = false;
}
/* -------------------------
Render: “copy bits” by slabs
(blit only visible spans)
-------------------------- */
function render(){
if (layoutDirty) recomputeLayout();
// background
ctx.fillStyle = "#efefef";
ctx.fillRect(0,0,W,H);
// subtle stipple background
ctx.globalAlpha = 0.15;
ctx.fillStyle = PAT_LIGHT;
ctx.fillRect(0,0,W,H);
ctx.globalAlpha = 1;
let regionPixels = 0, regionBlits = 0, regionBands = 0;
let naivePixels = 0;
if (naiveMode.checked){
// draw full rect for each window, back->front
for (const win of windows){
ctx.drawImage(win.buf, Math.floor(win.x), Math.floor(win.y));
naivePixels += win.w * win.h;
}
} else {
// slab blit only visible spans
for (const win of windows){
const wx = Math.floor(win.x);
const wy = Math.floor(win.y);
for (const band of win.visibleBands){
const sy = band.y - wy;
for (const [a,b] of band.spans){
const sx = a - wx;
const sw = b - a;
// source is win.buf (window local), dest is screen
ctx.drawImage(
win.buf,
sx, sy, sw, band.h,
a, band.y, sw, band.h
);
regionPixels += sw * band.h;
regionBlits += 1;
}
regionBands += 1;
}
}
}
// overlays: visible regions (x-ray)
if (showRegions.checked){
ctx.save();
ctx.globalAlpha = 0.22;
// draw x‑ray fills by window, back->front
for (let i=0;i<windows.length;i++){
const win = windows[i];
const fill = (i%2===0) ? PAT_MID : PAT_DIAG;
ctx.fillStyle = fill;
for (const band of win.visibleBands){
for (const [a,b] of band.spans){
ctx.fillRect(a, band.y, b-a, band.h);
}
}
}
ctx.restore();
// outlines (crisp)
ctx.save();
ctx.strokeStyle = "rgba(0,0,0,0.6)";
ctx.setLineDash([4,4]);
for (const win of windows){
for (const band of win.visibleBands){
for (const [a,b] of band.spans){
ctx.strokeRect(a+0.5, band.y+0.5, (b-a)-1, band.h-1);
}
}
}
ctx.restore();
}
// band breaks
if (showBands.checked && !naiveMode.checked){
ctx.save();
ctx.strokeStyle = "rgba(0,0,0,0.35)";
for (const win of windows){
for (const band of win.visibleBands){
ctx.beginPath();
ctx.moveTo(0, band.y+0.5);
ctx.lineTo(W, band.y+0.5);
ctx.stroke();
}
}
ctx.restore();
}
// active/hover hints
const active = windows.find(w => w.id === activeId);
if (active){
ctx.save();
ctx.strokeStyle = "#000";
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeRect(Math.floor(active.x)+0.5, Math.floor(active.y)+0.5, active.w-1, active.h-1);
ctx.restore();
}
// HUD
const mode = naiveMode.checked ? "Naive" : "Regions";
const px = naiveMode.checked ? naivePixels : regionPixels;
const blits = naiveMode.checked ? "(n/a)" : regionBlits;
const bands = naiveMode.checked ? "(n/a)" : regionBands;
let savings = "";
if (!naiveMode.checked){
// compare vs naive full-rect draw
const full = windows.reduce((s,w)=>s + (w.w*w.h), 0);
const pct = full ? Math.max(0, Math.round(100 - (regionPixels / full)*100)) : 0;
savings = ` • saved ~${pct}% pixels vs full-rect`;
}
hud.textContent = `${mode} • blits: ${blits} • bands: ${bands} • pixels: ${px}${savings}`;
// window list UI
syncWinList();
}
/* -------------------------
Window list = semantic mirror
-------------------------- */
function syncWinList(){
// rebuild only if needed (small n anyway)
winList.innerHTML = "";
windows.forEach((w, idx) => {
const btn = document.createElement("button");
btn.className = "winBtn";
btn.type = "button";
btn.setAttribute("role", "listitem");
btn.setAttribute("aria-current", w.id === activeId ? "true" : "false");
btn.innerHTML = `<span>${w.title}</span><span>#${idx+1}</span>`;
btn.addEventListener("click", () => {
bringToFront(w.id);
requestRender();
canvas.focus();
});
winList.appendChild(btn);
});
}
/* -------------------------
Z-order helpers
-------------------------- */
function bringToFront(id){
const idx = windows.findIndex(w => w.id === id);
if (idx < 0) return;
const w = windows.splice(idx, 1)[0];
windows.push(w);
activeId = id;
layoutDirty = true;
}
function cycleActive(dir){
const idx = windows.findIndex(w => w.id === activeId);
if (idx < 0) return;
let next = idx + dir;
if (next < 0) next = windows.length - 1;
if (next >= windows.length) next = 0;
activeId = windows[next].id;
bringToFront(activeId); // makes cycle obvious
}
/* -------------------------
Pointer interaction (drag)
Last-clicked comes to top.
-------------------------- */
function toCanvasXY(e){
const r = canvas.getBoundingClientRect();
const x = (e.clientX - r.left) * (W / r.width);
const y = (e.clientY - r.top) * (H / r.height);
return { x, y };
}
function topWindowAt(x,y){
for (let i=windows.length-1; i>=0; i--){
const w = windows[i];
if (x >= w.x && x <= w.x+w.w && y >= w.y && y <= w.y+w.h) return w;
}
return null;
}
function clampWindow(w){
w.x = Math.round(Math.max(0, Math.min(W - w.w, w.x)));
w.y = Math.round(Math.max(0, Math.min(H - w.h, w.y)));
}
canvas.addEventListener("pointerdown", (e) => {
const {x,y} = toCanvasXY(e);
const w = topWindowAt(x,y);
if (!w) return;
// bring-to-front is the tribute requirement
bringToFront(w.id);
dragging = windows[windows.length-1]; // now top
dragOffset.x = x - dragging.x;
dragOffset.y = y - dragging.y;
canvas.setPointerCapture(e.pointerId);
layoutDirty = true;
requestRender();
});
canvas.addEventListener("pointermove", (e) => {
const {x,y} = toCanvasXY(e);
if (dragging){
dragging.x = x - dragOffset.x;
dragging.y = y - dragOffset.y;
clampWindow(dragging);
layoutDirty = true;
requestRender();
return;
}
const w = topWindowAt(x,y);
hoverId = w ? w.id : null;
canvas.style.cursor = w ? "grab" : "default";
requestRender();
});
canvas.addEventListener("pointerup", (e) => {
if (dragging){
dragging = null;
layoutDirty = true;
requestRender();
}
try { canvas.releasePointerCapture(e.pointerId); } catch {}
});
/* -------------------------
Keyboard controls
-------------------------- */
canvas.addEventListener("keydown", (e) => {
const active = windows.find(w => w.id === activeId);
if (!active) return;
const step = e.shiftKey ? 10 : 2;
if (e.key === "[" ){ cycleActive(-1); e.preventDefault(); requestRender(); return; }
if (e.key === "]" ){ cycleActive(+1); e.preventDefault(); requestRender(); return; }
if (e.key === "Enter"){
bringToFront(activeId);
e.preventDefault();
requestRender();
return;
}
if (e.key === "ArrowLeft"){ active.x -= step; clampWindow(active); layoutDirty=true; e.preventDefault(); requestRender(); return; }
if (e.key === "ArrowRight"){ active.x += step; clampWindow(active); layoutDirty=true; e.preventDefault(); requestRender(); return; }
if (e.key === "ArrowUp"){ active.y -= step; clampWindow(active); layoutDirty=true; e.preventDefault(); requestRender(); return; }
if (e.key === "ArrowDown"){ active.y += step; clampWindow(active); layoutDirty=true; e.preventDefault(); requestRender(); return; }
});
/* -------------------------
Control changes
-------------------------- */
for (const el of [showRegions, showBands, naiveMode, scanStepSel]){
el.addEventListener("change", () => {
layoutDirty = true;
requestRender();
});
}
/* -------------------------
Render scheduling
-------------------------- */
function requestRender(){
if (rafPending) return;
rafPending = true;
requestAnimationFrame(() => {
rafPending = false;
render();
});
}
/* boot */
window.addEventListener("resize", () => {
// Canvas scales via CSS; internal coords stay the same.
// We just re-render so overlays/HUD stay in sync.
requestRender();
}, { passive: true });
:root{
--bg: #d8d8d8;
--panel: #cfcfcf;
--paper: #efefef;
--ink: #111;
/* Type scale: ~1.5× */
--ui-scale: 1.5;
}
*{ box-sizing:border-box; }
html{
font-size: 16px; /* baseline */
}
body{
margin:0;
background:var(--bg);
color:var(--ink);
font-family: Chicago, Geneva, monospace;
/* 1.5× overall type scale */
font-size: calc(1rem * var(--ui-scale));
line-height: 1.25;
}
#app{
max-width: 1100px;
margin: 0 auto;
padding: 0.9rem;
}
.panel{
background:var(--panel);
border: 0.125rem solid var(--ink);
padding: 0.65rem;
}
.titleRow{
display:flex;
align-items:baseline;
justify-content:space-between;
gap:0.6rem;
}
h1{
margin:0;
font-size: 1.15rem;
letter-spacing: 0.02rem;
}
a{
color: var(--ink);
text-decoration: underline;
cursor: pointer;
font-size: 0.75rem;
font-weight: bold;
}
.badge{
border: 0.125rem solid var(--ink);
padding: 0.15rem 0.4rem;
background: var(--paper);
font-size: 0.75rem;
}
.sub{
margin:0.5rem 0 0.35rem;
font-size:0.85rem;
}
.quote{
margin:0;
padding:0.45rem 0.55rem;
background: var(--paper);
border: 0.125rem solid var(--ink);
font-size:1.5rem;
}
.quote .note{ opacity:0.75; }
.layout{
display:grid;
grid-template-columns: 1fr 22rem;
gap: 0.75rem;
margin-top: 0.75rem;
align-items:start;
}
/* Fully responsive: stack on narrow screens */
@media (max-width: 980px){
.layout{
grid-template-columns: 1fr;
}
}
/* Stage panel */
.stageTop{
display:flex;
justify-content:space-between;
gap: 0.5rem;
margin-bottom: 0.5rem;
align-items:center;
flex-wrap: wrap;
}
.kioskLabel{
font-size: 0.75rem;
padding: 0.15rem 0.4rem;
border: 0.125rem solid var(--ink);
background: var(--paper);
}
.hud{
font-size: 0.75rem;
text-align:right;
opacity: 0.95;
}
/* Canvas is fully responsive */
canvas{
display:block;
width: 100%;
height: auto; /* keeps aspect ratio from attributes */
background: var(--paper);
border: 0.18rem solid var(--ink);
image-rendering: pixelated;
outline: none;
touch-action: none; /* better pointer interactions on mobile */
}
canvas:focus-visible{
outline: 0.2rem dashed var(--ink);
outline-offset: 0.3rem;
}
.hint{
margin-top: 0.55rem;
font-size: 0.75rem;
opacity: 0.9;
}
kbd{
border: 0.125rem solid var(--ink);
background: var(--paper);
padding: 0 0.25rem;
font-size: 0.75rem;
}
/* Side panels */
.side{
display:flex;
flex-direction:column;
gap: 0.75rem;
}
.controls h2, .windows h2, .desc h2{
margin:0 0 0.5rem;
font-size: 0.95rem;
}
.controls .row{
display:flex;
align-items:center;
justify-content:space-between;
gap: 0.6rem;
font-size: 0.85rem;
margin: 0.4rem 0;
}
.controls select{
font-family: inherit;
border: 0.125rem solid var(--ink);
background: var(--paper);
font-size: 0.85rem;
}
.windows .mini{
margin: 0 0 0.5rem;
font-size: 0.75rem;
opacity: 0.9;
}
.winList{
display:flex;
flex-direction:column;
gap: 0.5rem;
}
.winBtn{
display:flex;
align-items:center;
justify-content:space-between;
gap: 0.6rem;
width:100%;
font-family: inherit;
border: 0.125rem solid var(--ink);
background: var(--paper);
padding: 0.55rem;
cursor: pointer;
font-size: 0.85rem;
}
.winBtn[aria-current="true"]{
background: #fff;
}
.winBtn:focus-visible{
outline: 0.2rem dashed var(--ink);
outline-offset: 0.2rem;
}
.desc ul{
margin: 0;
padding-left: 1.1rem;
font-size: 0.85rem;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment