nandi/jolt-nativepublic Fork 0
0fb017593acce485b16f9756141b599beb49dc76
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 · 92 lines · 4.0 KBmarkdown Blame HistoryRaw
Paint glimmer with nothing under it f554a01 nandi 12d 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
Play three games on the gfx backend e98a184 nandi 11d ago32LD_LIBRARY_PATH=/path/to/libX11 jolt tictactoe # a game, in the same widgets
33LD_LIBRARY_PATH=/path/to/libX11 jolt maze # WASD, under the widgets
34LD_LIBRARY_PATH=/path/to/libX11 jolt asteroids # vector primitives, same two files
Paint glimmer with nothing under it f554a01 nandi 12d ago35```
36
37Xlib is a *system* library here, not one of this repo's crates, and it must be
38one the jolt binary can load — on a nix-built jolt, the host `/usr/lib` copy is
39a different glibc and fails before `dlopen` returns.
40
Play three games on the gfx backend e98a184 nandi 11d ago41`maze` is the other half of the story: sixty frames a second whatever you do,
42so there is nothing for a reconciler to reconcile. It skips glimmer and talks
43to `raster` and `x11` directly — `run-window` hands it a framebuffer and the
44keys held this frame, which is all a game loop ever wanted.
45
46`asteroids` is what those primitives are actually for: every shape is a list of
47points rotated and translated per frame and stroked with `raster/poly!`, so
48there is no sprite, no bitmap and no asset — the ship is four points and some
49trigonometry. `step` is pure, which is why the tests play a whole game without
50a display.
51
Paint glimmer with nothing under it f554a01 nandi 12d ago52## What a backend has to do
53
54Read this one first. It is the smallest complete backend in the repo, and the
55only one where every part of the answer is visible rather than behind an ABI.
56
57 src/glimmer_gfx/raster.clj framebuffer, rect/line, a 3x5 font no FFI
58 src/glimmer_gfx/core.clj the backend: tree, layout, paint no FFI
59 src/glimmer_gfx/x11.clj the window, and nothing else
60
61`glimmer.backend`'s map is mostly trivial — `create!` allocates an atom,
62`append-child!` conjes onto a vector. The work is what a toolkit would have
63done for you:
64
65* **A tree to patch.** The reconciler needs somewhere to hold widgets between
66 frames, which an immediate-mode painter has not got. Here it is atoms of
67 `{:tag :props :children}`, about 60 lines. glimmer-vidya needs the same thing
68 and keeps it in Rust behind a second C ABI, because egui hands the
69 reconciler nothing to hold.
70* **Layout.** `measure!` sizes bottom-up, `place!` positions top-down. This is
71 most of the file. `:spacing`, `:max-width` and container padding are
72 honoured; `:align` and `:grow` are not, so children keep their measured
73 width, left-aligned.
74* **Hit testing.** Deepest interactive node under the cursor, last match wins.
75 A press claims a widget and holds it until release, so a slider keeps
76 tracking when the pointer leaves its rect.
77
78Tags: `:page` `:card` `:vbox` `:hbox` `:title` `:label` `:button` `:checkbox`
79`:slider` `:spacer`. Props are the shared vocabulary — `:label`, `:spacing`,
80`:max-width`, `:kind`, `:checked`, `:value`/`:min`/`:max`, `:on-click`,
81`:on-change`.
82
83## Text
84
85There is no font stack. `raster.clj` carries a 3x5 bitmap font for ASCII,
86authored as art and editable in place:
87
88 "A.#.|#.#|###|#.#|#.#"
89
90It scales by whole pixels, which is why the UI looks like it does. A real font
91means FreeType, which means a crate — at which point this stops being the
92backend that runs anywhere.