# Schcom — the SchOS Compositor Owns the display. Every pixel that reaches the screen goes through it. Clients do not draw to the framebuffer; they draw into their own buffers and hand them over. Schcom decides what is on top of what, composites the result, and presents it. It also owns input: it reads the raw event devices and sends each event to whichever client should have it. That is the whole job. Window *placement* is not part of it — that is SchWM's, and Schcom exposes a protocol for it rather than implementing policy itself. ## Status **v0 runs.** A client connects, is given a shared buffer, draws into it and commits; the result is composited and presented. Verified end to end by `make schcom-test`, which boots SchOS, runs the compositor and a client, then screendumps the framebuffer and asserts the pixels **from the host** — the compositor's own report that it composited something proves nothing. It runs two overlapping clients and checks that the newer one wins in the overlap: a compositor that cannot order two surfaces cannot host a window manager. What exists: - framebuffer output through `/dev/fb0` and the fbdev ioctls, double-buffered - a versioned protocol over a Unix socket, with a handshake that must come first - shared-memory buffers, one per surface, owned by the compositor - surface / attach / **commit** semantics: nothing is shown mid-draw - input from `/dev/input/eventN`, routed to the topmost surface - clients that die are cleaned up, including their shm segments - **multiple clients**, composited bottom-to-top in creation order What does not exist yet: damage tracking beyond "repaint everything", multiple outputs, subsurfaces, and any focus model beyond "topmost". Those are additions rather than rewrites, which is the reason for committing to the surface/commit model now instead of growing into it later. ## Building Not part of the OS build. Needs `make ports` first, for the sysroot's libc: ```sh make projects # builds and stages into sysroot/bin make # rebuilds the image so the binaries are on it make schcom-test # boots it and checks the pixels ``` ## What it needs from the kernel | Need | State | |---|---| | Shared memory (`shmget`/`shmat`/`shmdt`) | done | | `mmap` of `/dev/fb0` | done | | Framebuffer geometry via the fbdev ioctls | done | | Unix domain sockets | done | | Raw input events — key down/up with modifiers | done | | `SCM_RIGHTS` | **not implemented** — there is no `sendmsg`/`recvmsg` at all | | Mode setting and double buffering | partial — virtio-gpu binds, no modeset API yet | ## Design notes - **Buffers are shared memory, not pipes.** A pipe means copying every frame; at 800×600×32 that is 1.9 MB per frame per client. - **The compositor owns the segment, not the client.** It has to survive a client crashing mid-frame, and it must not be something a client can resize underneath the compositor. - **One protocol, versioned from the start.** SchWM and SchDE are separate programs, so this is a real compatibility surface on day one. Every message carries its own length, so an unknown message is skipped rather than desynchronising the stream — that is what lets a v0 compositor survive a v1 client. - **Policy belongs to SchWM.** If Schcom starts deciding where windows go, the split has already failed. `CREATE_SURFACE` carries x/y today only because there is no SchWM yet to ask. ## On Wayland > **Decided: Schcom moves onto Wayland**, replacing the protocol below while > keeping the architecture. See [`docs/plan/wayland.md`](../../docs/plan/wayland.md). The protocol is deliberately Wayland-shaped — surfaces rather than windows, buffers attached and made visible only on commit, and the compositor telling clients when to draw. Wayland is **MIT-licensed**, so it can be linked against without any conflict with Apache-2.0 (see `docs/licensing.md`), and supporting it later is intended. The one place v0 knowingly diverges: a buffer handle is a System V shared memory id passed as an integer, where Wayland passes a file descriptor over `SCM_RIGHTS`. `struct schcom_surface` carries a `handle_kind` field precisely so that switching would be a new value rather than a protocol break. **That field cannot save us, and this README used to claim `SCM_RIGHTS` was done.** It is not — there is no `sendmsg`/`recvmsg` in the kernel at all. And Wayland's `wl_shm_create_pool` passes a descriptor with no alternative form, so *our* protocol being flexible is not the flexibility that is needed. Adding descriptor passing is item 1 of [`docs/plan/foundations.md`](../../docs/plan/foundations.md).