nandi/jolt-nativepublic Fork 0
5416ab28fada343bf6c0fd963096487787b0cf35
Commits
Clone
git clone https://git.rickub.com/nandi/jolt-native.git
git clone ssh://git@rickub.com/nandi/jolt-native.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

README.md · 78 lines · 3.1 KBmarkdown Blame HistoryRaw
Paint glimmer with nothing under it f554a01 nandi 11d ago1# glimmer-gfx
2
3glimmer's **software** backend: no toolkit, no shared object, no GPU. The
4rasterizer, the layout and the font are jolt; the only foreign code is Xlib,
5and Xlib draws nothing — it opens a window and takes a finished framebuffer.
6
7It is [glimmer-vidya](../glimmer-vidya) with nothing underneath it. The
8reconciler does not know what it is patching, so the same hiccup that egui
9paints as a window and [glimmer-tui](../glimmer-tui) paints as cells is painted
10here, a pixel at a time, by code in this directory:
11
12```clojure
13(ns myapp
14 (:require [glimmer.ratom :as ra]
15 [glimmer.core :as ui]
16 [glimmer-gfx.core])) ; installs this backend
17
18(defn app []
19 [:card {:spacing 8}
20 [:title {:label "Counter"}]
21 [:label {:label (str "Count: " (ra/deref count))}]
22 [:button {:label "+ 1" :kind :primary :on-click #(ra/swap! count inc)}]])
23
24(defn -main [& _] (ui/run app :title "myapp"))
25```
26
27## Running
28
29```bash
30jolt test # headless: no window, no display
31LD_LIBRARY_PATH=/path/to/libX11 jolt counter
32```
33
34Xlib is a *system* library here, not one of this repo's crates, and it must be
35one the jolt binary can load — on a nix-built jolt, the host `/usr/lib` copy is
36a different glibc and fails before `dlopen` returns.
37
38## What a backend has to do
39
40Read this one first. It is the smallest complete backend in the repo, and the
41only one where every part of the answer is visible rather than behind an ABI.
42
43 src/glimmer_gfx/raster.clj framebuffer, rect/line, a 3x5 font no FFI
44 src/glimmer_gfx/core.clj the backend: tree, layout, paint no FFI
45 src/glimmer_gfx/x11.clj the window, and nothing else
46
47`glimmer.backend`'s map is mostly trivial — `create!` allocates an atom,
48`append-child!` conjes onto a vector. The work is what a toolkit would have
49done for you:
50
51* **A tree to patch.** The reconciler needs somewhere to hold widgets between
52 frames, which an immediate-mode painter has not got. Here it is atoms of
53 `{:tag :props :children}`, about 60 lines. glimmer-vidya needs the same thing
54 and keeps it in Rust behind a second C ABI, because egui hands the
55 reconciler nothing to hold.
56* **Layout.** `measure!` sizes bottom-up, `place!` positions top-down. This is
57 most of the file. `:spacing`, `:max-width` and container padding are
58 honoured; `:align` and `:grow` are not, so children keep their measured
59 width, left-aligned.
60* **Hit testing.** Deepest interactive node under the cursor, last match wins.
61 A press claims a widget and holds it until release, so a slider keeps
62 tracking when the pointer leaves its rect.
63
64Tags: `:page` `:card` `:vbox` `:hbox` `:title` `:label` `:button` `:checkbox`
65`:slider` `:spacer`. Props are the shared vocabulary — `:label`, `:spacing`,
66`:max-width`, `:kind`, `:checked`, `:value`/`:min`/`:max`, `:on-click`,
67`:on-change`.
68
69## Text
70
71There is no font stack. `raster.clj` carries a 3x5 bitmap font for ASCII,
72authored as art and editable in place:
73
74 "A.#.|#.#|###|#.#|#.#"
75
76It scales by whole pixels, which is why the UI looks like it does. A real font
77means FreeType, which means a crate — at which point this stops being the
78backend that runs anywhere.