nandi/jolt-nativepublic Fork 0
42dabb0
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.

Tell a caller how big the window is

An :image can be bounded, but a caller wanting a row of tiles to divide the
window between them cannot work out what to bound it by: how many there
are, and how much gap goes between them, is arithmetic no single widget can
do from the space it was handed.

So vidya_screen_width and vidya_screen_height, in points rather than
pixels, because whoever asks is laying out and layout is in the units the
widgets use. Read off egui's last screen rect, so they answer between
frames as well as during one and follow a window being dragged. Zero before
the first frame, which is the honest answer to asking how big a window is
before it has been painted.

The width the window opened with was no answer: it is what was asked for
once, and nothing updated it afterwards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandi committed 2026-08-30T17:40:15-07:00 Browse files
42dabb0 parent: c90f8af
modified crates/jolt-vidya/include/vidya_tree.h +17 -0
@@ -132,6 +132,23 @@ VIDYA_API const char *vidya_tree_event_name(void);
132132 VIDYA_API const char *vidya_tree_event_text(void);
133133 VIDYA_API double vidya_tree_event_num(void);
134134
135+/* The window
136+ *
137+ * Its size in points — not pixels — because whoever asks is about to lay
138+ * something out, and layout is in the units the widgets use. 0 before the
139+ * first frame.
140+ *
141+ * A caller wanting something to be a share of the window rather than a fixed
142+ * size needs this: how many of them there are and how much gap goes between
143+ * them is the caller's arithmetic, not something one widget can work out from
144+ * the space it was handed.
145+ *
146+ * Reads what egui last saw, so it answers between frames as well as during
147+ * one, and follows the window when it is dragged.
148+ */
149+VIDYA_API float vidya_screen_width(void);
150+VIDYA_API float vidya_screen_height(void);
151+
135152 /* Live frames
136153 *
137154 * Hand the tree a frame of raw pixels under `key`; any `:image` node whose
@@ -132,6 +132,23 @@ VIDYA_API const char *vidya_tree_event_name(void);
132 VIDYA_API const char *vidya_tree_event_text(void);132 VIDYA_API const char *vidya_tree_event_text(void);
133 VIDYA_API double vidya_tree_event_num(void);133 VIDYA_API double vidya_tree_event_num(void);
134 134
135+/* The window
136+ *
137+ * Its size in points — not pixels — because whoever asks is about to lay
138+ * something out, and layout is in the units the widgets use. 0 before the
139+ * first frame.
140+ *
141+ * A caller wanting something to be a share of the window rather than a fixed
142+ * size needs this: how many of them there are and how much gap goes between
143+ * them is the caller's arithmetic, not something one widget can work out from
144+ * the space it was handed.
145+ *
146+ * Reads what egui last saw, so it answers between frames as well as during
147+ * one, and follows the window when it is dragged.
148+ */
149+VIDYA_API float vidya_screen_width(void);
150+VIDYA_API float vidya_screen_height(void);
151+
135 /* Live frames152 /* Live frames
136 *153 *
137 * Hand the tree a frame of raw pixels under `key`; any `:image` node whose154 * Hand the tree a frame of raw pixels under `key`; any `:image` node whose
modified crates/jolt-vidya/src/app.rs +20 -0
@@ -581,6 +581,26 @@ impl App {
581581 ///
582582 /// Returned together because widget calls need both, and they live in
583583 /// different fields — splitting the borrow here keeps the call sites plain.
584+ /// The window's size in points, as egui last saw it.
585+ ///
586+ /// Points rather than pixels: a caller sizing something against this is
587+ /// laying out, and layout is in the same units the widgets are. The
588+ /// `width`/`height` the window was opened with are no answer — they are
589+ /// what was asked for once, and say nothing about a window since dragged
590+ /// wider.
591+ ///
592+ /// egui keeps the last screen rect on its context, so this answers between
593+ /// frames as well as during one. Zero before the first frame, which is the
594+ /// honest answer to asking how big a window is before it has been painted.
595+ pub fn screen_size(&self) -> (f32, f32) {
596+ let rect = self.handler.egui_ctx.screen_rect();
597+ if rect.width().is_finite() && rect.height().is_finite() {
598+ (rect.width().max(0.0), rect.height().max(0.0))
599+ } else {
600+ (0.0, 0.0)
601+ }
602+ }
603+
584604 pub fn ui(&mut self) -> Option<(&mut egui::Ui, &Theme)> {
585605 let theme = &self.handler.theme;
586606 self.stack.top().map(|ui| (ui, theme))
@@ -581,6 +581,26 @@ impl App {
581 ///581 ///
582 /// Returned together because widget calls need both, and they live in582 /// Returned together because widget calls need both, and they live in
583 /// different fields — splitting the borrow here keeps the call sites plain.583 /// different fields — splitting the borrow here keeps the call sites plain.
584+ /// The window's size in points, as egui last saw it.
585+ ///
586+ /// Points rather than pixels: a caller sizing something against this is
587+ /// laying out, and layout is in the same units the widgets are. The
588+ /// `width`/`height` the window was opened with are no answer — they are
589+ /// what was asked for once, and say nothing about a window since dragged
590+ /// wider.
591+ ///
592+ /// egui keeps the last screen rect on its context, so this answers between
593+ /// frames as well as during one. Zero before the first frame, which is the
594+ /// honest answer to asking how big a window is before it has been painted.
595+ pub fn screen_size(&self) -> (f32, f32) {
596+ let rect = self.handler.egui_ctx.screen_rect();
597+ if rect.width().is_finite() && rect.height().is_finite() {
598+ (rect.width().max(0.0), rect.height().max(0.0))
599+ } else {
600+ (0.0, 0.0)
601+ }
602+ }
603+
584 pub fn ui(&mut self) -> Option<(&mut egui::Ui, &Theme)> {604 pub fn ui(&mut self) -> Option<(&mut egui::Ui, &Theme)> {
585 let theme = &self.handler.theme;605 let theme = &self.handler.theme;
586 self.stack.top().map(|ui| (ui, theme))606 self.stack.top().map(|ui| (ui, theme))
modified crates/jolt-vidya/src/lib.rs +23 -0
@@ -575,6 +575,29 @@ pub extern "C" fn vidya_tree_event_num() -> f64 {
575575 with_tree(0.0, |tree| tree.current().map_or(0.0, |e| e.num))
576576 }
577577
578+// ── The window ──────────────────────────────────────────────────────────────
579+
580+/// The window's width in points, or 0 before the first frame.
581+///
582+/// Points, not pixels: whoever asks is about to lay something out, and layout
583+/// is in the units the widgets use. A caller that wants a tile to be a share
584+/// of the window rather than a fixed number of points needs this, because the
585+/// arithmetic — how many tiles, how much gap between them — is theirs and not
586+/// something a single widget can work out from the space it was handed.
587+///
588+/// Reads what egui last saw, so it answers between frames as well as during
589+/// one, and follows the window when it is dragged.
590+#[no_mangle]
591+pub extern "C" fn vidya_screen_width() -> c_float {
592+ with_app(0.0, |app| app.screen_size().0)
593+}
594+
595+/// The window's height in points, or 0 before the first frame.
596+#[no_mangle]
597+pub extern "C" fn vidya_screen_height() -> c_float {
598+ with_app(0.0, |app| app.screen_size().1)
599+}
600+
578601 // ── Live frames ─────────────────────────────────────────────────────────────
579602
580603 /// Hand the tree a frame of raw pixels under `key`, painted by any `:image`
@@ -575,6 +575,29 @@ pub extern "C" fn vidya_tree_event_num() -> f64 {
575 with_tree(0.0, |tree| tree.current().map_or(0.0, |e| e.num))575 with_tree(0.0, |tree| tree.current().map_or(0.0, |e| e.num))
576 }576 }
577 577
578+// ── The window ──────────────────────────────────────────────────────────────
579+
580+/// The window's width in points, or 0 before the first frame.
581+///
582+/// Points, not pixels: whoever asks is about to lay something out, and layout
583+/// is in the units the widgets use. A caller that wants a tile to be a share
584+/// of the window rather than a fixed number of points needs this, because the
585+/// arithmetic — how many tiles, how much gap between them — is theirs and not
586+/// something a single widget can work out from the space it was handed.
587+///
588+/// Reads what egui last saw, so it answers between frames as well as during
589+/// one, and follows the window when it is dragged.
590+#[no_mangle]
591+pub extern "C" fn vidya_screen_width() -> c_float {
592+ with_app(0.0, |app| app.screen_size().0)
593+}
594+
595+/// The window's height in points, or 0 before the first frame.
596+#[no_mangle]
597+pub extern "C" fn vidya_screen_height() -> c_float {
598+ with_app(0.0, |app| app.screen_size().1)
599+}
600+
578 // ── Live frames ─────────────────────────────────────────────────────────────601 // ── Live frames ─────────────────────────────────────────────────────────────
579 602
580 /// Hand the tree a frame of raw pixels under `key`, painted by any `:image`603 /// Hand the tree a frame of raw pixels under `key`, painted by any `:image`
modified jolt/glimmer-vidya/src/glimmer_vidya/core.jolt +15 -0
@@ -292,6 +292,21 @@
292292 [path]
293293 (ffi/picked-image! path))
294294
295+(defn screen-size
296+ "The window's size in points, as `[width height]`. `[0 0]` before the first
297+ frame has been painted.
298+
299+ For laying something out as a share of the window — a row of tiles that
300+ should divide the width between them — where how many there are and how much
301+ gap goes between them is the caller's arithmetic, and not something one
302+ widget can work out from the space it was handed.
303+
304+ Follows the window as it is dragged, so a component that reads it wants to be
305+ re-rendered when it changes: keep it in a ratom rather than asking here at
306+ render time, or the layout will be whatever it was on the first frame."
307+ []
308+ [(ffi/screen-width) (ffi/screen-height)])
309+
295310 (defn frame-rgba!
296311 "Hand the backend a frame of live pixels under `key`. An `:image` node with
297312 `:feed key` paints the latest one.
@@ -292,6 +292,21 @@
292 [path]292 [path]
293 (ffi/picked-image! path))293 (ffi/picked-image! path))
294 294
295+(defn screen-size
296+ "The window's size in points, as `[width height]`. `[0 0]` before the first
297+ frame has been painted.
298+
299+ For laying something out as a share of the window — a row of tiles that
300+ should divide the width between them — where how many there are and how much
301+ gap goes between them is the caller's arithmetic, and not something one
302+ widget can work out from the space it was handed.
303+
304+ Follows the window as it is dragged, so a component that reads it wants to be
305+ re-rendered when it changes: keep it in a ratom rather than asking here at
306+ render time, or the layout will be whatever it was on the first frame."
307+ []
308+ [(ffi/screen-width) (ffi/screen-height)])
309+
295 (defn frame-rgba!310 (defn frame-rgba!
296 "Hand the backend a frame of live pixels under `key`. An `:image` node with311 "Hand the backend a frame of live pixels under `key`. An `:image` node with
297 `:feed key` paints the latest one.312 `:feed key` paints the latest one.
modified jolt/glimmer-vidya/src/glimmer_vidya/ffi.jolt +7 -0
@@ -60,6 +60,13 @@
6060 (ffi/defcfn event-text "vidya_tree_event_text" [] :string)
6161 (ffi/defcfn event-num "vidya_tree_event_num" [] :double)
6262
63+
64+;; --- the window --------------------------------------------------------------
65+;; Its size in points, following the window as it is dragged. Points rather
66+;; than pixels because a caller asking is about to lay something out.
67+(ffi/defcfn screen-width "vidya_screen_width" [] :float)
68+(ffi/defcfn screen-height "vidya_screen_height" [] :float)
69+
6370 ;; --- live frames -------------------------------------------------------------
6471 ;; Pixels pushed in under a name, painted by an `:image` whose `:feed` names it.
6572 ;; `rgba` is a foreign pointer to width*height*4 bytes, copied before the call
@@ -60,6 +60,13 @@
60 (ffi/defcfn event-text "vidya_tree_event_text" [] :string)60 (ffi/defcfn event-text "vidya_tree_event_text" [] :string)
61 (ffi/defcfn event-num "vidya_tree_event_num" [] :double)61 (ffi/defcfn event-num "vidya_tree_event_num" [] :double)
62 62
63+
64+;; --- the window --------------------------------------------------------------
65+;; Its size in points, following the window as it is dragged. Points rather
66+;; than pixels because a caller asking is about to lay something out.
67+(ffi/defcfn screen-width "vidya_screen_width" [] :float)
68+(ffi/defcfn screen-height "vidya_screen_height" [] :float)
69+
63 ;; --- live frames -------------------------------------------------------------70 ;; --- live frames -------------------------------------------------------------
64 ;; Pixels pushed in under a name, painted by an `:image` whose `:feed` names it.71 ;; Pixels pushed in under a name, painted by an `:image` whose `:feed` names it.
65 ;; `rgba` is a foreign pointer to width*height*4 bytes, copied before the call72 ;; `rgba` is a foreign pointer to width*height*4 bytes, copied before the call