nx_nishios_wm.nx source
↩ module page · 98 lines · 7361 B
1// nx_nishios_wm.nx -- NishiOS GUI rung-2: a WINDOW MANAGER / COMPOSITOR.
2// A desktop is more than one window: it's multiple windows composited in z-order over a wallpaper, with
3// a mouse cursor on top. This draws a gradient wallpaper, two windows that OVERLAP (the higher-z one
4// drawn last so it correctly occludes the lower one), a taskbar with buttons, and a shadowed arrow
5// cursor above everything -- then exports the composite as a real BMP via the nx_fb library.
6// KAT: z-order is correct (the overlap region shows the TOP window, not the bottom), the wallpaper is a
7// real gradient (rows differ), the cursor is drawn on top, and the BMP is well-formed.
8// HONEST SCOPE: a STATIC composite (one frame, fixed cursor). Live input (mouse/keyboard event loop),
9// dragging, and wiring this framebuffer into the boot kernel are the next rungs. No hw writes (Rule 26).
10// expect_exit: 0 license_tier: ORIGINAL
11import "nx_fb.nx"
12import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
13const K_MAGIC_192054: i64 = 192054
14
15func wm_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
16// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
17// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
18// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
19// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
20func wm_num(v: i64) -> i64 { nxi_out(v); return 0 }
21
22// draw a window: body + title strip + 1px black border + title text
23func draw_window(fb: *u8, W: i64, H: i64, font: *u8, idx: *u8, x: i64, y: i64, w: i64, h: i64, tr: i64, tg: i64, tb: i64, br: i64, bg: i64, bb: i64) -> i64 {
24 fb_rect(fb,W,H, x,y, w,h, br,bg,bb) // body
25 fb_rect(fb,W,H, x,y, w,14, tr,tg,tb) // title strip
26 fb_rect(fb,W,H, x,y, w,1, 0,0,0) // border top
27 fb_rect(fb,W,H, x,y+h-1, w,1, 0,0,0) // border bottom
28 fb_rect(fb,W,H, x,y, 1,h, 0,0,0) // border left
29 fb_rect(fb,W,H, x+w-1,y, 1,h, 0,0,0) // border right
30 fb_text(fb,W,H, font, idx, 7, x+3, y+3, 1, 240,240,250) // title "NISHIOS"
31 return 0
32}
33
34func main() -> i64 {
35 wm_puts("NishiOS GUI rung-2: a WINDOW MANAGER (gradient wallpaper + z-ordered overlapping windows + cursor)\n" as *u8)
36 let W: i64 = 320
37 let H: i64 = 200
38 let fb: *u8 = sys_mmap(W*H*3)
39
40 let font: *u8 = sys_mmap(64)
41 fb_gly(font,0, 0x81,0xC1,0xA1,0x91,0x89,0x85,0x83,0x81) // N
42 fb_gly(font,1, 0x7C,0x10,0x10,0x10,0x10,0x10,0x7C,0x00) // I
43 fb_gly(font,2, 0x7E,0x80,0x80,0x7C,0x02,0x02,0x7C,0x00) // S
44 fb_gly(font,3, 0x81,0x81,0x81,0xFF,0x81,0x81,0x81,0x00) // H
45 fb_gly(font,4, 0x7C,0x82,0x82,0x82,0x82,0x82,0x7C,0x00) // O
46 let idx: *u8 = sys_mmap(8)
47 idx[0]=0 as u8; idx[1]=1 as u8; idx[2]=2 as u8; idx[3]=3 as u8; idx[4]=1 as u8; idx[5]=4 as u8; idx[6]=2 as u8
48
49 // wallpaper: vertical gradient (12,12,48) -> (2,60,80)
50 var y: i64=0
51 while y<H { let r: i64=12-(10*y)/H; let g: i64=12+(48*y)/H; let b: i64=48+(32*y)/H; fb_rect(fb,W,H, 0,y, W,1, r,g,b); y=y+1 }
52
53 // two windows, drawn back-to-front (z-order): win1 first, win2 on top
54 draw_window(fb,W,H, font,idx, 40,45, 130,95, 40,120,60, 35,35,45) // win1 "terminal" (green title, dark body) -- BELOW
55 draw_window(fb,W,H, font,idx, 120,80, 150,95, 50,80,180, 200,200,215) // win2 "files" (blue title, light body) -- ON TOP
56
57 // taskbar + two buttons
58 fb_rect(fb,W,H, 0,186, W,14, 25,25,40)
59 fb_rect(fb,W,H, 4,189, 40,8, 80,200,80)
60 fb_rect(fb,W,H, 50,189, 40,8, 80,140,220)
61
62 // mouse cursor (shadowed arrow) on top of everything, at (185,100) -- over win2
63 let curs: *u8 = sys_mmap(16)
64 curs[0]=0x80 as u8; curs[1]=0xC0 as u8; curs[2]=0xE0 as u8; curs[3]=0xF0 as u8; curs[4]=0xF8 as u8; curs[5]=0xFC as u8; curs[6]=0xFE as u8; curs[7]=0xFF as u8; curs[8]=0xFC as u8; curs[9]=0xEC as u8; curs[10]=0xC6 as u8; curs[11]=0x86 as u8
65 let cx: i64=185
66 let cy: i64=100
67 var cr: i64=0
68 while cr<12 { let bits: i64=curs[cr] as i64; var cc: i64=0; while cc<8 { if ((bits>>(7-cc))&1)==1 { fb_setpx(fb,W,H, cx+cc+1, cy+cr+1, 0,0,0) } cc=cc+1 } cr=cr+1 } // shadow
69 cr=0
70 while cr<12 { let bits2: i64=curs[cr] as i64; var cc2: i64=0; while cc2<8 { if ((bits2>>(7-cc2))&1)==1 { fb_setpx(fb,W,H, cx+cc2, cy+cr, 255,255,255) } cc2=cc2+1 } cr=cr+1 } // white arrow
71
72 let sz: i64 = fb_bmp_save(fb, W, H, "knowledge/status/nishios_wm.bmp\x00" as *u8)
73 let html: *u8 = "<!doctype html><html><body style=\x27margin:0;background:#0a0a12;display:flex;align-items:center;justify-content:center;height:100vh\x27><div><img src=\x27nishios_wm.bmp\x27 style=\x27image-rendering:pixelated;width:640px;border:1px solid #333\x27><div style=\x27color:#8af;font-family:monospace;text-align:center;margin-top:8px\x27>NishiOS window manager -- 2 windows composited in z-order + cursor, drawn by the kernel</div></div></body></html>\x00"
74 let hd: i64 = sys_openat_wr("knowledge/status/nishios_wm.html\x00" as *u8, 0x1a4)
75 if hd>0 { var hn: i64=0; while html[hn]!=(0 as u8){hn=hn+1} sys_write(hd, html, hn); sys_close(hd) }
76 wm_puts(" composited desktop -> knowledge/status/nishios_wm.bmp (" as *u8); wm_num(sz); wm_puts(" bytes) + nishios_wm.html\n" as *u8)
77
78 var pass: i64=0
79 var ttl: i64=0
80 // z-order: overlap point (140,110) must be win2 body (200,200,215), NOT win1 (35,35,45)
81 let p_ov: i64 = (110*W+140)*3
82 ttl=ttl+1; wm_puts(" T1 z-order correct (overlap shows TOP window 200,200,215): " as *u8); if (fb[p_ov] as i64)==200 { if (fb[p_ov+2] as i64)==215 { pass=pass+1; wm_puts("PASS\n" as *u8) } else { wm_puts("FAIL\n" as *u8) } } else { wm_puts("FAIL\n" as *u8) }
83 // win1-only point (60,75) must be win1 body (35,35,45)
84 let p_w1: i64 = (75*W+60)*3
85 ttl=ttl+1; wm_puts(" T2 lower window visible where not occluded (35,35,45): " as *u8); if (fb[p_w1] as i64)==35 { if (fb[p_w1+2] as i64)==45 { pass=pass+1; wm_puts("PASS\n" as *u8) } else { wm_puts("FAIL\n" as *u8) } } else { wm_puts("FAIL\n" as *u8) }
86 // gradient wallpaper: column x=300 differs between y=10 and y=180
87 let g_top: i64 = (10*W+300)*3+1
88 let g_bot: i64 = (180*W+300)*3+1
89 ttl=ttl+1; wm_puts(" T3 wallpaper is a real gradient (rows differ): " as *u8); if (fb[g_top] as i64) != (fb[g_bot] as i64) { pass=pass+1; wm_puts("PASS\n" as *u8) } else { wm_puts("FAIL\n" as *u8) }
90 // cursor tip (185,100) white on top
91 let p_cu: i64 = (100*W+185)*3
92 ttl=ttl+1; wm_puts(" T4 mouse cursor drawn on top (white tip @185,100): " as *u8); if (fb[p_cu] as i64)==255 { if (fb[p_cu+1] as i64)==255 { pass=pass+1; wm_puts("PASS\n" as *u8) } else { wm_puts("FAIL\n" as *u8) } } else { wm_puts("FAIL\n" as *u8) }
93 ttl=ttl+1; wm_puts(" T5 BMP exported (192054 bytes): " as *u8); if sz==K_MAGIC_192054 { pass=pass+1; wm_puts("PASS\n" as *u8) } else { wm_puts("FAIL\n" as *u8) }
94
95 wm_puts("NISHIOS-WM-GATE passed " as *u8); wm_num(pass); wm_puts("/" as *u8); wm_num(ttl)
96 if pass==ttl { wm_puts(" verdict=GREEN (a real window manager composites z-ordered windows + cursor; open nishios_wm.bmp/html to SEE it)\n" as *u8); sys_exit(0); return 0 }
97 wm_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1
98}