Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
view.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <atomic>
6#include <cstdint>
10#include <pulp/view/theme.hpp>
13#include <functional>
14#include <optional>
15#include <vector>
16#include <memory>
17#include <string>
18#include <string_view>
19
21
22namespace pulp::view {
23
24class WindowHost; // Forward declaration for View→Host back-reference
25class PluginViewHost;
26class WidgetBridge;
28class FrameClock;
29class WidgetPainter; // pulp/view/widget_painter.hpp — pluggable paint delegate
30class WidgetMetrics; // pulp/view/widget_metrics.hpp — pluggable sizing delegate
31class SelectableText; // pulp/view/selectable_text.hpp — cross-widget text selection
32class FrameClockBinding; // pulp/view/value_source_binding.hpp
33struct ViewValueBindings; // pulp/view/src/view.cpp — lazily allocated value-source bindings
34struct FileDragRequest; // pulp/view/drag_drop.hpp
35struct ActiveDrag; // pulp/view/drag_drop.hpp
36struct DropData; // pulp/view/drag_drop.hpp
37class ComboBox; // pulp/view/ui_components.hpp — held (as View*) in RootInteractionState
38class View;
39
46enum class RuntimeViewKind : std::uint8_t {
48};
49
57public:
58 void set(View* view) noexcept;
59 void reset() noexcept;
60 bool has_value() const noexcept { return view_ != nullptr; }
61 View* live_in(View& root) const noexcept;
62
63private:
64 View* view_ = nullptr;
65 std::uint64_t instance_id_ = 0;
66 mutable View* validated_root_ = nullptr;
67 mutable std::uint64_t validated_root_instance_id_ = 0;
68 mutable std::uint64_t validated_generation_ = 0;
69};
70
71// Base class for all UI elements
72// Views form a tree: each view has zero or more children and one optional parent
73class View {
74public:
76 virtual ~View();
77
78 View(const View&) = delete;
79 View& operator=(const View&) = delete;
80
81 // ── Bounds and layout ────────────────────────────────────────────────
82
83 // The view's bounds in its parent's coordinate space
84 Rect bounds() const { return bounds_; }
86
87 // The view's local bounds (origin at 0,0)
88 Rect local_bounds() const { return {0, 0, bounds_.width, bounds_.height}; }
89
90 // Flex layout style
91 FlexStyle& flex() { return flex_; }
92 const FlexStyle& flex() const { return flex_; }
93
94 GridStyle& grid() { return grid_; }
95 const GridStyle& grid() const { return grid_; }
96
97 void set_layout_mode(LayoutMode m) { layout_mode_ = m; }
98 LayoutMode layout_mode() const { return layout_mode_; }
99
104 void set_subpixel_layout(bool v) { subpixel_layout_ = v; }
105 bool subpixel_layout() const { return subpixel_layout_; }
108 captured_frame_root_ = v;
109 }
110 bool captured_frame_root() const {
111 return captured_frame_root_;
112 }
113
114 // ── Child management ─────────────────────────────────────────────────
115
119 std::unique_ptr<View> add_child(std::unique_ptr<View> child);
120 // Transactional variant used by structural adapters that must recover the
121 // owned child if an attach hook rejects it. On throw, `child` is restored.
122 // Returns false, with `child` untouched, when the child is refused.
123 bool add_child_transactional(std::unique_ptr<View>& child);
127 std::unique_ptr<View> remove_child(View* child);
128
138 bool move_child_to_index(View* child, size_t index);
139
149 void retire(std::unique_ptr<View> owned) noexcept;
150
154 static std::uint64_t structure_generation() noexcept;
158 std::uint64_t root_structure_generation() const noexcept;
159
160 size_t child_count() const { return children_.size(); }
161 View* child_at(size_t index) { return children_[index].get(); }
162 const View* child_at(size_t index) const { return children_[index].get(); }
163 View* parent() const { return parent_; }
164
165 // ── Reload state (live-swap item 1.4b) ───────────────────────────────
166 // A CUSTOM widget overrides these to carry its own state across a
167 // scripted-UI hot reload, beyond the built-in knob/fader/combo/segmented/
168 // toggle/checkbox/xy coverage the WidgetBridge snapshots by type.
169 // save_reload_state writes an opaque blob and returns true to OPT IN;
170 // restore_reload_state applies a blob previously written by the same widget
171 // type (matched by the script's widget id). Default: no custom state
172 // (returns false), so every existing widget is unaffected — the bridge only
173 // stores/restores a blob for widgets that opt in.
174 virtual bool save_reload_state(std::string& /*out_blob*/) const { return false; }
175 virtual bool restore_reload_state(std::string_view /*blob*/) { return false; }
176
177 // ── View recycling (ViewPool, planning 2.3) ──────────────────────────
178 // A recyclable View can be parked in a ViewPool when it scrolls out of a
179 // virtualized list/grid (or is torn down by a hot reload) and handed back
180 // later instead of being destroyed and rebuilt. Recycling is OPT-IN: a
181 // subclass must override supports_reuse() to return true, otherwise
182 // ViewPool::release() destroys it and adoption stays behavior-neutral.
183 //
184 // supports_reuse() advertises that prepare_for_reuse() leaves the instance
185 // in a safe, blank-slate state — no live callbacks into freed state, no
186 // stale bounds/selection/focus. Only override it once that contract holds.
187 virtual bool supports_reuse() const { return false; }
188
189 // Scrub every piece of per-instance state that must NOT survive into the
190 // next user of a recycled View. The ViewPool calls this on the acquire
191 // path, so a pooled view carries no live state while parked. Subclasses
192 // that add their own callbacks / cached state MUST override this, reset
193 // their own members, then call View::prepare_for_reuse() to run the base
194 // reset below. The base impl clears bounds/visibility/opacity/access
195 // labels/pointer+hover+focus state AND EVERY base-class callback — a
196 // recycled view firing a stale on_click/on_drag/etc. into a torn-down
197 // closure is the exact use-after-free this guards against.
198 //
199 // Precondition: the view must be detached (no parent) — a pooled view is
200 // never part of a live tree.
201 virtual void prepare_for_reuse();
202
203 // ── Hit testing ──────────────────────────────────────────────────────
204
205 // Find the deepest child containing the point. A detached root accepts
206 // painted root-local coordinates and peels its own scale; recursive calls
207 // receive the child's already-unscaled local coordinates.
208 virtual View* hit_test(Point local_point);
209
210 // ── Theme ────────────────────────────────────────────────────────────
211
212 void set_theme(const Theme& theme) { theme_ = theme; request_repaint(); }
213 const Theme& theme() const { return theme_; }
214
215 // Resolve a color: check own theme first, then walk up to parent
216 Color resolve_color(const std::string& name, Color fallback = {}) const;
217
222 void set_color(std::string name, Color c) {
223 theme_.colors[std::move(name)] = c;
225 }
226
227 // ── Paint delegate ───────────────────────────────────────────────────
228 //
229 // A WidgetPainter installed here supplies the pixels for the stock controls
230 // in this view AND its whole subtree, unless a descendant installs its own.
231 // See widget_painter.hpp. Each hook defaults to declining, so a delegate
232 // restyles only the controls it implements and the rest keep Pulp's look.
233
234 void set_painter(std::shared_ptr<WidgetPainter> p);
235 const std::shared_ptr<WidgetPainter>& painter() const { return painter_; }
236
240
241 // ── Metrics delegate ─────────────────────────────────────────────────
242 //
243 // The sizing sibling of the painter: same install, same subtree cascade,
244 // same decline-by-default hooks. Consulted during LAYOUT, where there is no
245 // canvas — which is why it is a separate object from the painter. Widgets
246 // reach it from `intrinsic_width()`/`intrinsic_height()` (the function the
247 // layout engine already calls to measure a leaf), or directly when they
248 // position themselves. See widget_metrics.hpp.
249
250 void set_metrics(std::shared_ptr<WidgetMetrics> m);
251 const std::shared_ptr<WidgetMetrics>& metrics() const { return metrics_; }
252
256
257 // ── CSS-style typography inheritance ─────────────────────────────────
258 //
259 // Mirrors CSS: setting `color: white` on a parent View cascades down
260 // to every text descendant unless overridden. These fields are stored
261 // on the View but DO NOT affect the View's own paint — they're picked
262 // up by Label::paint() (and other text widgets) when the widget has
263 // no explicit value of its own.
264 //
265 // The cascade order at paint time is:
266 // 1. Widget's own explicit value (e.g. Label::set_font_size on this Label)
267 // 2. inheritable_*() — walks up the parent chain returning the first
268 // ancestor that set the matching field
269 // 3. Theme token / widget default fallback (existing behavior)
270 //
271 // text_align uses int rather than LabelAlign to keep View free of a
272 // back-include of widgets.hpp; the int matches LabelAlign's enum
273 // order: 0 = left, 1 = center, 2 = right.
274
276 inh_text_color_ = c;
277 invalidate_subtree_caches_up();
278 }
279 void clear_inheritable_text_color() { inh_text_color_.reset(); }
281 std::optional<Color> inheritable_text_color() const;
282
283 // An inheritable typography value is read by every descendant Label that
284 // did not set its own, so it changes their measured boxes and must move
285 // the layout generation for the same reason Label's own setters do.
286 // Guarded on a real change so a replayed identical style stays clean.
287 void set_inheritable_font_size(float size) {
288 if (inh_font_size_ && *inh_font_size_ == size)
289 return;
290 inh_font_size_ = size;
292 }
293 void clear_inheritable_font_size() { inh_font_size_.reset(); }
294 std::optional<float> inheritable_font_size() const;
295
297 if (inh_letter_spacing_ && *inh_letter_spacing_ == sp)
298 return;
299 inh_letter_spacing_ = sp;
301 }
302 void clear_inheritable_letter_spacing() { inh_letter_spacing_.reset(); }
303 std::optional<float> inheritable_letter_spacing() const;
304
306 if (inh_font_weight_ && *inh_font_weight_ == w)
307 return;
308 inh_font_weight_ = w;
310 }
311 void clear_inheritable_font_weight() { inh_font_weight_.reset(); }
312 std::optional<int> inheritable_font_weight() const;
313
317 void set_inheritable_font_family(std::string f) {
318 if (inh_font_family_ && *inh_font_family_ == f)
319 return;
320 inh_font_family_ = std::move(f);
322 }
323 void clear_inheritable_font_family() { inh_font_family_.reset(); }
324 std::optional<std::string> inheritable_font_family() const;
325
327 void set_inheritable_text_align(int a) { inh_text_align_ = a; }
328 void clear_inheritable_text_align() { inh_text_align_.reset(); }
329 std::optional<int> inheritable_text_align() const;
330
331 // ── Visibility ───────────────────────────────────────────────────────
332
333 bool visible() const { return visible_; }
343 void set_visible(bool v) {
344 if (visibility_quarantine_count_ > 0) {
345 visible_after_quarantine_ = v;
346 return;
347 }
348 const bool changed = visible_ != v;
349 visible_ = v;
350 invalidate_subtree_caches_up();
351 if (changed) {
352 // Parent layout decides whether this child occupies space. Dirty
353 // the whole path so showing a child assigns fresh bounds and
354 // hiding it lets siblings close the gap before the repaint.
355 for (View* node = this; node; node = node->parent_)
356 node->invalidate_layout();
358 }
359 }
360
361 // ── Layout ───────────────────────────────────────────────────────────
362
363 // Perform flex layout on children (virtual so ScrollView can override)
364 virtual void layout_children();
374 bool layout_is_current() const noexcept {
375 return applied_layout_generation_ == tree_layout_generation();
376 }
377 void mark_layout_current() noexcept {
378 applied_layout_generation_ = tree_layout_generation();
379 }
380
384 std::uint64_t tree_layout_generation() const noexcept;
385 virtual bool owns_child_layout() const { return false; }
386
389 virtual float intrinsic_width() const { return 0; }
390 virtual float intrinsic_height() const; // default: sum of visible children for containers
391
392 // ── Painting ──────────────────────────────────────────────────────────
393
394 // Paint this view and all children into a canvas
396
397 // Last paint cycle's wall-clock cost.
398 // Updated by paint_all() at the end of each paint pass. Exposed so
399 // the inspector property panel can show per-view timing without
400 // adding new instrumentation per query.
401 //
402 // last_paint_self_ns() — time spent INSIDE this view's
403 // paint(canvas) override only.
404 // last_paint_with_children_ns() — time spent INSIDE paint(canvas)
405 // PLUS time recursively painting
406 // every descendant. The
407 // difference (with_children - self)
408 // attributes child cost cleanly.
409 //
410 // Both are 0 until the view has been painted at least once. Updated
411 // every frame; readers see the most recent sample. Storage is two
412 // uint32_t fields per view (cap at ~4s of paint time which is far
413 // beyond any realistic frame budget).
414 std::uint32_t last_paint_self_ns() const { return last_paint_self_ns_; }
415 std::uint32_t last_paint_with_children_ns() const { return last_paint_with_children_ns_; }
416
417 // ── Lifecycle (override in subclasses) ────────────────────────────────
418
419 virtual void paint(canvas::Canvas&) {}
420 virtual void on_resized() {}
421 virtual void on_attached() {}
422 virtual void on_detached() {}
427 virtual void advance_animations(float dt) { (void)dt; }
433 virtual void on_frame_clock_changed() {}
434
435 // ── Input events (rich, with modifiers and pointer ID) ──────────────
436
438 virtual void on_mouse_event(const MouseEvent& event) {
439 // An `overflow: scroll` container consumes the wheel the way
440 // ScrollView does — it is the scroll boundary, so the tick does not
441 // also reach the pointer callback.
442 if (event.is_wheel && handle_scroll_wheel(event))
443 return;
444 auto callback = on_pointer_event;
445 if (callback) callback(event);
446 }
447
450 bool handle_scroll_wheel(const MouseEvent& event);
454 virtual bool wants_wheel_value() const { return false; }
457 virtual void on_wheel(float delta_y) { (void)delta_y; }
463 virtual bool is_gesture_active() const { return false; }
469 virtual bool wants_wheel_scroll() const;
472 virtual bool wants_mouse_input() const { return false; }
475 virtual bool on_key_event(const KeyEvent& event) { (void)event; return false; }
477 virtual void on_text_input(const TextInputEvent& event) { (void)event; }
480 virtual void on_focus_changed(bool gained) { has_focus_ = gained; }
481
483 virtual void on_gesture_event(const GestureEvent& event) {
484 if (on_gesture_cb) on_gesture_cb(event);
485 }
486 GestureRecognizer& add_gesture_recognizer(std::unique_ptr<GestureRecognizer> recognizer);
487 void clear_gesture_recognizers(); size_t gesture_recognizer_count() const { return gesture_recognizers_.size(); }
489 bool dispatch_gesture_pointer_event(const MouseEvent& root_event, double timestamp_seconds = -1.0);
490 void advance_gesture_recognizers(double timestamp_seconds = -1.0); bool has_time_driven_gestures() const;
491
498 // ── Pointer capture (W3C setPointerCapture) ─────────────────────────
499
502 void set_pointer_capture(int pointer_id);
503 void release_pointer_capture(int pointer_id);
504 bool has_pointer_capture(int pointer_id) const;
505
506 // ── Legacy event handlers (kept for backward compatibility) ──────────
507
508 virtual void on_mouse_down(Point pos) { (void)pos; }
509 virtual void on_mouse_up(Point pos) { (void)pos; }
510 virtual void on_mouse_drag(Point pos) { (void)pos; }
511
515 virtual void on_mouse_cancel(Point pos) { on_mouse_up(pos); }
516 virtual void on_key_press(int key_code) { (void)key_code; }
517
518 // ── Hover events ──────────────────────────────────────────────────────
519
520 virtual void on_mouse_enter() {}
521 virtual void on_mouse_leave() {}
522
530 virtual void on_hover_move(Point local_pos) { (void)local_pos; }
531
532 bool is_hovered() const { return hovered_; }
533 void set_hovered(bool h);
534
541 default_hover_feedback_ = enabled;
542 }
543 bool default_hover_feedback() const { return default_hover_feedback_; }
544
545 // ── Frame clock ─────────────────────────────────────────────────────
546
554
557
558 // ── Live host→view value sources ────────────────────────────────────────
559 // The seam a view showing a live host value (a meter, a readout, a
560 // modulation ring) uses instead of hand-rolling a frame-clock-polled
561 // reader. nullptr unbinds. UI thread. Semantics, paint-safety, the
562 // frames-alive effect and the FrameClock lifetime contract are documented
563 // once in value_source_binding.hpp.
564
568 void set_meter_source(std::shared_ptr<MeterSource> source, int channel = 0);
569 bool has_meter_source() const;
571
577 const MeterFrame& meter_frame() const;
578
581 void set_scalar_source(std::shared_ptr<ScalarSource> source);
582 bool has_scalar_source() const;
583
586 float scalar_value() const;
587
592 virtual void on_meter_frame(const MeterFrame& frame, float dt) {
593 (void)frame;
594 (void)dt;
595 }
596
600 }
601
602 // ── Transient-animation glue ─────────────────────────────────────────────
603 // Tween/easing already exist; what a faithful port re-rolls every time is
604 // the View-lifecycle glue — self-(un)subscribing a FrameClock callback and
605 // repainting. animate() does exactly that: it interpolates a float from
606 // `from` to `to` over `duration_s` seconds through `ease`, applies each
607 // step via `apply`, and repaints. It auto-unsubscribes on completion AND on
608 // View destruction (so a fade that outlives its view can't use-after-free).
609 // Returns an animation id, or -1 if no FrameClock is reachable yet
610 // (previews/screenshots — the caller should just set the final value).
611 // A non-empty `tag` makes the animation self-cancelling: starting a new one
612 // with the same tag cancels the prior (e.g. re-hovering before a fade ends).
613 // `on_done` fires once when the tween reaches `to`, never when cancelled.
614 int animate(std::function<void(float)> apply, float from, float to,
615 float duration_s, std::function<float(float)> ease = {},
616 std::function<void()> on_done = {}, const std::string& tag = {});
617
619 void cancel_animation(int id);
621 int active_animation_count() const { return static_cast<int>(animations_.size()); }
622
623 // ── Theme dimension resolution ──────────────────────────────────────
624
626 float resolve_dimension(const std::string& name, float fallback) const;
627
641
642 // Dispatch a synthetic click to the deepest view at the given point
643 void simulate_click(Point root_pos);
644
647 void simulate_click(Point root_pos, const SimulatedPointer& pointer);
648
655
656 // Dispatch a synthetic drag from start to end
657 void simulate_drag(Point start, Point end, int steps = 10);
658
661 const SimulatedPointer& pointer);
662
663 // Dispatch a synthetic hover to the view at the given point
664 void simulate_hover(Point root_pos);
665
666 // ── Keyboard focus ───────────────────────────────────────────────────
667
668 bool focusable() const { return focusable_; }
669 void set_focusable(bool f) { focusable_ = f; }
670
678 virtual bool accepts_text_input() const { return false; }
679
685 return nullptr;
686 }
688 return const_cast<View*>(this)->as_selectable_text();
689 }
690
707 void set_text_selection_region(bool region) {
708 text_selection_region_ = region;
709 }
711 return text_selection_region_;
712 }
713
715 bool enabled() const { return enabled_; }
716 void set_enabled(bool e) { enabled_ = e; }
717
719 bool hit_testable() const { return hit_testable_; }
720 void set_hit_testable(bool h) { hit_testable_ = h; }
721
731 enum class PointerEvents { auto_, none, box_only, box_none };
732 void set_pointer_events(PointerEvents p) { pointer_events_ = p; }
733 PointerEvents pointer_events() const { return pointer_events_; }
734
758 struct HitSlop {
759 float top = 0.0f, right = 0.0f, bottom = 0.0f, left = 0.0f;
760 bool empty() const {
761 return top == 0.0f && right == 0.0f && bottom == 0.0f && left == 0.0f;
762 }
763 };
764 void set_hit_slop(float uniform) { hit_slop_ = {uniform, uniform, uniform, uniform}; }
765 void set_hit_slop(float top, float right, float bottom, float left) {
766 hit_slop_ = {top, right, bottom, left};
767 }
768 void set_hit_slop(HitSlop s) { hit_slop_ = s; }
769 HitSlop hit_slop() const { return hit_slop_; }
770
773 Rect hit_bounds() const {
774 Rect b = local_bounds();
775 return Rect{b.x - hit_slop_.left, b.y - hit_slop_.top,
776 b.width + hit_slop_.left + hit_slop_.right,
777 b.height + hit_slop_.top + hit_slop_.bottom};
778 }
779
783 bool backface_visible() const { return backface_visible_; }
785 backface_visible_ = v;
786 invalidate_subtree_caches_up();
787 }
788
802 bool requires_gpu_host() const { return requires_gpu_host_; }
803 void set_requires_gpu_host(bool v) { requires_gpu_host_ = v; }
804
813 bool contains_native_overlay() const { return contains_native_overlay_; }
814 void set_contains_native_overlay(bool v) { contains_native_overlay_ = v; }
815
821 virtual std::vector<uint8_t> capture_native_overlay_png(uint32_t /*width*/,
822 uint32_t /*height*/) {
823 return {};
824 }
825
826 // ── Layout generation ───────────────────────────────────────────────
827 //
828 // A process-wide monotonic counter bumped by ANY mutation that can change
829 // computed geometry. It exists so a reader (the JS bridge's geometry
830 // queries) can answer "has anything moved since I last laid out?" without
831 // running a tree walk to find out.
832 //
833 // Why not the per-View `layout_dirty_` flag: invalidation does NOT
834 // propagate upward. `invalidate_layout()` marks the view it is called on,
835 // so a flex change on a deep child leaves `root.layout_dirty()` FALSE while
836 // the tree is genuinely stale. A guard reading the root's flag would skip a
837 // needed pass and hand back stale (often 0x0) bounds — the exact failure
838 // `getLayoutRect`'s comment exists to prevent.
839 //
840 // The bump lives inside the invalidators themselves rather than at the
841 // bridge's entry points, so any mutation path is automatically correct —
842 // including host resizes, C++-side widget code, and invalidators written
843 // after this. OVER-invalidating costs one redundant layout; UNDER-
844 // invalidating is a correctness bug, so the counter is deliberately eager.
845 //
846 // Starts at 1 so a reader initialised to 0 always lays out once.
847 static std::uint64_t layout_generation() noexcept {
848 return layout_generation_.load(std::memory_order_relaxed);
849 }
850 static void bump_layout_generation() noexcept {
851 layout_generation_.fetch_add(1, std::memory_order_relaxed);
852 }
853
864 static std::uint64_t damage_request_count() noexcept {
865 return damage_request_count_.load(std::memory_order_relaxed);
866 }
867 static std::uint64_t unmarked_paint_mutation_count() noexcept {
868 return unmarked_paint_mutation_count_.load(std::memory_order_relaxed);
869 }
870
871 static void note_unmarked_paint_mutation() noexcept {
872 unmarked_paint_mutation_count_.fetch_add(1, std::memory_order_relaxed);
873 }
874
882
883 static std::uint64_t layout_pass_count() noexcept {
884 return layout_pass_count_.load(std::memory_order_relaxed);
885 }
886
890 static std::uint64_t constructed_count() noexcept {
891 return constructed_count_.load(std::memory_order_relaxed);
892 }
893 static std::uint64_t destroyed_count() noexcept {
894 return destroyed_count_.load(std::memory_order_relaxed);
895 }
896
899 layout_dirty_ = true;
900 note_layout_mutation();
901 }
902 bool layout_dirty() const { return layout_dirty_; }
903 void clear_layout_dirty() { layout_dirty_ = false; }
904
917
922
933 void request_repaint(const Rect& local_dirty);
934
939 void request_repaint_self(float halo = 4.0f);
940
945 bool start_file_drag(const FileDragRequest& request);
946
947 // ── In-tree drag source (drag_drop.hpp) ──────────────────────────────
948 //
949 // Begin a drag whose payload stays in this process and in this view tree.
950 // The source view owns the gesture: start_drag() on press-and-move,
951 // drag_to() on each motion tick, drop_here() on release.
952 //
953 // void on_mouse_drag(Point p) override {
954 // if (!drag_active()) { DropData d; d.text = id_; start_drag(d); }
955 // drag_to(local_to_root(p));
956 // }
957 // void on_mouse_up(Point p) override { drop_here(local_to_root(p)); }
958 //
959 // All three take ROOT coordinates, the space the drop dispatch works in.
960
962 void drag_to(Point root_pos);
963 bool drop_here(Point root_pos);
965 bool drag_active() const;
966 bool has_focus() const { return has_focus_; }
967 void set_focus(bool f) { has_focus_ = f; }
968
969 // Move focus to next/previous focusable widget
970 static View* focus_next(View& root, View* current);
971 static View* focus_prev(View& root, View* current);
972
973 // ── Accessibility ────────────────────────────────────────────────────
974
988 enum class AccessRole {
989 none = 0, slider, toggle, label, group, meter, image, // frozen 0-6
990 button, link, checkbox, radio, text_field, combo_box,
991 list, list_item, table, row, cell, tab, tab_list,
992 menu, menu_item, progress_bar, dialog, heading, scroll_bar,
993 };
994
995 void set_access_role(AccessRole role) { access_role_ = role; }
996 AccessRole access_role() const { return access_role_; }
998 implicit_access_role_ = role;
999 access_role_ = role;
1000 }
1002 access_role_ = implicit_access_role_;
1003 }
1004
1010 void set_access_label(std::string label) { access_label_ = std::move(label); }
1011
1020 void set_derived_access_label(std::string label) {
1021 derived_access_label_ = std::move(label);
1022 }
1023
1025 const std::string& access_label() const {
1026 return access_label_.empty() ? derived_access_label_ : access_label_;
1027 }
1028
1031 bool has_explicit_access_label() const { return !access_label_.empty(); }
1032
1034 const std::string& derived_access_label() const { return derived_access_label_; }
1035
1036 void set_access_value(std::string value) { access_value_ = std::move(value); }
1037 const std::string& access_value() const { return access_value_; }
1038
1039 // ARIA state attributes. Tri-state semantics per the ARIA 1.2 spec
1040 // (`true` / `false` / `mixed` / unset). We store the raw string the JS shim
1041 // hands us so platform accessibility bridges can read it back verbatim.
1042 // Setting the empty string clears the state.
1043 void set_access_pressed(std::string s) { access_pressed_ = std::move(s); }
1044 void set_access_checked(std::string s) { access_checked_ = std::move(s); }
1045 void set_access_disabled(std::string s) { access_disabled_ = std::move(s); }
1046 void set_access_hidden(std::string s) { access_hidden_ = std::move(s); }
1047 const std::string& access_pressed() const { return access_pressed_; }
1048 const std::string& access_checked() const { return access_checked_; }
1049 const std::string& access_disabled() const { return access_disabled_; }
1050 const std::string& access_hidden() const { return access_hidden_; }
1051
1054 virtual void on_accessibility_adjust(float delta) { (void)delta; }
1055
1056 // ── Identity ─────────────────────────────────────────────────────────
1057
1058 void set_id(std::string id) { id_ = std::move(id); }
1059 const std::string& id() const { return id_; }
1060
1068 void set_anchor_id(std::string anchor) { anchor_id_ = std::move(anchor); }
1069 const std::string& anchor_id() const { return anchor_id_; }
1070
1074 std::uint64_t import_binding_instance_id() const { return import_binding_instance_id_; }
1075 std::weak_ptr<const std::uint64_t> import_binding_lifetime_token() const {
1076 return import_binding_lifetime_token_;
1077 }
1078
1090 std::string file;
1091 int line = 0;
1092 int col = 0;
1093
1094 bool valid() const { return !file.empty(); }
1095 };
1096
1097 void set_source_loc(SourceLocation loc) { source_loc_ = std::move(loc); }
1098 void clear_source_loc() { source_loc_.reset(); }
1099 bool has_source_loc() const { return source_loc_.has_value(); }
1103 static const SourceLocation kEmpty{};
1104 return source_loc_ ? *source_loc_ : kEmpty;
1105 }
1106
1107 // ── Visual properties (CSS Box Model) ────────────────────────────────
1108
1110 // Opacity is applied by the live compositing layer, outside any cached
1111 // recording, so it stales no cache -- but it is a paint change nobody
1112 // marked, which a batched repaint decision has to see.
1113 void set_opacity(float o) {
1114 opacity_ = std::clamp(o, 0.0f, 1.0f);
1116 }
1117 float opacity() const { return opacity_; }
1118
1120 // The paint setters below skip a write that changes nothing: a script
1121 // that re-applies the same style every frame must not read as an
1122 // unmarked paint change (which costs a whole-surface repaint).
1124 if (has_bg_ && bg_color_ == c)
1125 return;
1126 bg_color_ = c;
1127 has_bg_ = true;
1128 invalidate_subtree_caches_up();
1129 }
1131 if (!has_bg_)
1132 return;
1133 has_bg_ = false;
1134 invalidate_subtree_caches_up();
1135 }
1136 bool has_background_color() const { return has_bg_; }
1137 Color background_color() const { return bg_color_; }
1138
1143 void set_captured_box_paint_rect(float left, float top, float right,
1144 float bottom, float device_scale) {
1145 captured_box_paint_left_ = left;
1146 captured_box_paint_top_ = top;
1147 captured_box_paint_right_ = right;
1148 captured_box_paint_bottom_ = bottom;
1149 captured_box_paint_scale_ = device_scale > 0.0f ? device_scale : 0.0f;
1150 }
1152 return captured_box_paint_scale_ > 0.0f;
1153 }
1154 float captured_box_paint_left() const { return captured_box_paint_left_; }
1155 float captured_box_paint_top() const { return captured_box_paint_top_; }
1156 float captured_box_paint_right() const { return captured_box_paint_right_; }
1157 float captured_box_paint_bottom() const { return captured_box_paint_bottom_; }
1161
1168 void set_background_repeat(std::string kw) {
1169 background_repeat_ = std::move(kw);
1170 invalidate_subtree_caches_up();
1171 }
1172 const std::string& background_repeat() const { return background_repeat_; }
1173
1175 void set_border(Color c, float width, float radius = 0) {
1176 border_color_ = c; border_width_ = width; corner_radius_ = radius; has_border_ = true;
1177 invalidate_subtree_caches_up();
1178 }
1179 void clear_border() { has_border_ = false; invalidate_subtree_caches_up(); }
1180 bool has_border() const { return has_border_; }
1181 Color border_color() const { return border_color_; }
1182 float border_width() const { return border_width_; }
1183 float corner_radius() const { return corner_radius_; }
1184
1189 if (has_border_ && border_color_ == c)
1190 return;
1191 border_color_ = c;
1192 has_border_ = true;
1193 invalidate_subtree_caches_up();
1194 }
1195 void set_border_width(float w) {
1196 if (has_border_ && border_width_ == w)
1197 return;
1198 border_width_ = w;
1199 has_border_ = true;
1200 invalidate_subtree_caches_up();
1201 }
1202 void set_border_radius(float r) {
1203 if (corner_radius_ == r && corner_radius_pct_ == 0)
1204 return;
1205 corner_radius_ = r;
1206 corner_radius_pct_ = 0;
1207 invalidate_subtree_caches_up();
1208 }
1209
1211 void set_border_radius_pct(float pct) {
1212 if (corner_radius_pct_ == pct)
1213 return;
1214 corner_radius_pct_ = pct;
1215 invalidate_subtree_caches_up();
1216 }
1217 float corner_radius_pct() const { return corner_radius_pct_; }
1218
1224 enum class BorderCurve { circular, continuous };
1225 void set_border_curve(BorderCurve c) { border_curve_ = c; invalidate_subtree_caches_up(); }
1226 BorderCurve border_curve() const { return border_curve_; }
1229 float effective_corner_radius(float width, float height) const {
1230 if (corner_radius_pct_ > 0.0f) {
1231 return corner_radius_pct_ * 0.01f * std::min(width, height);
1232 }
1233 return corner_radius_;
1234 }
1235
1239 enum class BorderStyle {
1240 solid,
1241 dashed,
1242 dotted,
1243 double_,
1244 groove,
1245 ridge,
1246 inset,
1247 outset,
1250 };
1251 void set_border_style(BorderStyle s) { border_style_ = s; invalidate_subtree_caches_up(); }
1252 BorderStyle border_style() const { return border_style_; }
1253
1258 enum class ListStyleType {
1260 disc,
1261 circle,
1262 square,
1263 decimal,
1264 // CSS Counter Styles Level 3 keywords. Storage-only today; View itself
1265 // does not paint the marker glyphs. The slots exist so the bridge can
1266 // round-trip the consumer's keyword honestly. Underscored C++
1267 // identifiers map to hyphenated CSS keywords (e.g. lower_roman ↔
1268 // "lower-roman").
1269 decimal_leading_zero,
1270 lower_roman,
1271 upper_roman,
1272 lower_alpha,
1273 upper_alpha,
1274 lower_latin,
1275 upper_latin,
1276 lower_greek,
1277 armenian,
1278 georgian,
1279 };
1281 outside,
1282 inside,
1283 };
1284 void set_list_style_type(ListStyleType t) { list_style_type_ = t; }
1285 ListStyleType list_style_type() const { return list_style_type_; }
1286 void set_list_style_image(std::string url) { list_style_image_ = std::move(url); }
1287 const std::string& list_style_image() const { return list_style_image_; }
1288 void set_list_style_position(ListStylePosition p) { list_style_position_ = p; }
1289 ListStylePosition list_style_position() const { return list_style_position_; }
1290
1299 outline_color_ = c;
1300 invalidate_subtree_caches_up();
1301 }
1303 outline_offset_ = px;
1304 invalidate_subtree_caches_up();
1305 }
1307 outline_style_ = s;
1308 invalidate_subtree_caches_up();
1309 }
1310 void set_outline_width(float px) {
1311 outline_width_ = px;
1312 invalidate_subtree_caches_up();
1313 }
1314 Color outline_color() const { return outline_color_; }
1315 float outline_offset() const { return outline_offset_; }
1316 BorderStyle outline_style() const { return outline_style_; }
1317 float outline_width() const { return outline_width_; }
1318
1319
1326 void set_border_top(Color c, float w) { border_top_ = {c, w}; border_top_set_ = true; border_top_color_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1327 void set_border_right(Color c, float w) { border_right_ = {c, w}; border_right_set_ = true; border_right_color_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1328 void set_border_bottom(Color c, float w) { border_bottom_ = {c, w}; border_bottom_set_ = true; border_bottom_color_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1329 void set_border_left(Color c, float w) { border_left_ = {c, w}; border_left_set_ = true; border_left_color_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1334 void set_border_top_color(Color c) { border_top_.color = c; border_top_color_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1335 void set_border_right_color(Color c) { border_right_.color = c; border_right_color_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1336 void set_border_bottom_color(Color c) { border_bottom_.color = c; border_bottom_color_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1337 void set_border_left_color(Color c) { border_left_.color = c; border_left_color_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1341 void set_border_top_width(float w) { border_top_.width = w; border_top_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1342 void set_border_right_width(float w) { border_right_.width = w; border_right_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1343 void set_border_bottom_width(float w) { border_bottom_.width = w; border_bottom_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1344 void set_border_left_width(float w) { border_left_.width = w; border_left_set_ = true; has_border_sides_ = true; invalidate_subtree_caches_up(); }
1348 Color border_top_color() const { return border_top_.color; }
1349 float border_top_width() const { return border_top_.width; }
1350 Color border_right_color() const { return border_right_.color; }
1351 float border_right_width() const { return border_right_.width; }
1352 Color border_bottom_color() const { return border_bottom_.color; }
1353 float border_bottom_width() const { return border_bottom_.width; }
1354 Color border_left_color() const { return border_left_.color; }
1355 float border_left_width() const { return border_left_.width; }
1356 bool has_border_sides() const { return has_border_sides_; }
1360 bool has_border_top_set() const { return border_top_set_; }
1361 bool has_border_right_set() const { return border_right_set_; }
1362 bool has_border_bottom_set() const { return border_bottom_set_; }
1363 bool has_border_left_set() const { return border_left_set_; }
1369 bool has_border_top_color_set() const { return border_top_color_set_; }
1370 bool has_border_right_color_set() const { return border_right_color_set_; }
1371 bool has_border_bottom_color_set() const { return border_bottom_color_set_; }
1372 bool has_border_left_color_set() const { return border_left_color_set_; }
1373
1379 void set_corner_radius_tl(float r) { promote_uniform_to_per_corner(); corner_radii_[0] = r; corner_radii_pct_[0] = 0; has_corner_radii_ = true; invalidate_subtree_caches_up(); }
1380 void set_corner_radius_tr(float r) { promote_uniform_to_per_corner(); corner_radii_[1] = r; corner_radii_pct_[1] = 0; has_corner_radii_ = true; invalidate_subtree_caches_up(); }
1381 void set_corner_radius_bl(float r) { promote_uniform_to_per_corner(); corner_radii_[2] = r; corner_radii_pct_[2] = 0; has_corner_radii_ = true; invalidate_subtree_caches_up(); }
1382 void set_corner_radius_br(float r) { promote_uniform_to_per_corner(); corner_radii_[3] = r; corner_radii_pct_[3] = 0; has_corner_radii_ = true; invalidate_subtree_caches_up(); }
1385 void set_corner_radius_tl_pct(float pct) { promote_uniform_to_per_corner(); corner_radii_pct_[0] = pct; has_corner_radii_ = true; invalidate_subtree_caches_up(); }
1386 void set_corner_radius_tr_pct(float pct) { promote_uniform_to_per_corner(); corner_radii_pct_[1] = pct; has_corner_radii_ = true; invalidate_subtree_caches_up(); }
1387 void set_corner_radius_bl_pct(float pct) { promote_uniform_to_per_corner(); corner_radii_pct_[2] = pct; has_corner_radii_ = true; invalidate_subtree_caches_up(); }
1388 void set_corner_radius_br_pct(float pct) { promote_uniform_to_per_corner(); corner_radii_pct_[3] = pct; has_corner_radii_ = true; invalidate_subtree_caches_up(); }
1389 float corner_radius_tl_pct() const { return corner_radii_pct_[0]; }
1390 float corner_radius_tr_pct() const { return corner_radii_pct_[1]; }
1391 float corner_radius_bl_pct() const { return corner_radii_pct_[2]; }
1392 float corner_radius_br_pct() const { return corner_radii_pct_[3]; }
1394 float effective_corner_radius_tl(float w, float h) const { return corner_radii_pct_[0] > 0 ? corner_radii_pct_[0] * 0.01f * std::min(w,h) : corner_radii_[0]; }
1395 float effective_corner_radius_tr(float w, float h) const { return corner_radii_pct_[1] > 0 ? corner_radii_pct_[1] * 0.01f * std::min(w,h) : corner_radii_[1]; }
1396 float effective_corner_radius_bl(float w, float h) const { return corner_radii_pct_[2] > 0 ? corner_radii_pct_[2] * 0.01f * std::min(w,h) : corner_radii_[2]; }
1397 float effective_corner_radius_br(float w, float h) const { return corner_radii_pct_[3] > 0 ? corner_radii_pct_[3] * 0.01f * std::min(w,h) : corner_radii_[3]; }
1399 bool has_corner_radii() const { return has_corner_radii_; }
1400 float corner_radius_tl() const { return corner_radii_[0]; }
1401 float corner_radius_tr() const { return corner_radii_[1]; }
1402 float corner_radius_bl() const { return corner_radii_[2]; }
1403 float corner_radius_br() const { return corner_radii_[3]; }
1404
1408 struct BoxShadow {
1409 float offset_x = 0, offset_y = 2;
1410 float blur = 4;
1411 float spread = 0;
1412 Color color{0, 0, 0, 80};
1413 bool inset = false;
1414 };
1415
1418 void set_box_shadow(float ox, float oy, float blur, float spread, Color c,
1419 bool inset = false) {
1420 shadows_.assign(1, BoxShadow{ox, oy, blur, spread, c, inset});
1421 invalidate_subtree_caches_up();
1422 }
1423
1429 void add_box_shadow(float ox, float oy, float blur, float spread, Color c,
1430 bool inset = false) {
1431 shadows_.push_back(BoxShadow{ox, oy, blur, spread, c, inset});
1432 invalidate_subtree_caches_up();
1433 }
1434 void clear_box_shadow() { shadows_.clear(); invalidate_subtree_caches_up(); }
1435 bool has_box_shadow() const { return !shadows_.empty(); }
1439 const BoxShadow& box_shadow() const {
1440 static const BoxShadow kEmpty{};
1441 return shadows_.empty() ? kEmpty : shadows_.front();
1442 }
1443
1444 const std::vector<BoxShadow>& box_shadows() const { return shadows_; }
1445
1458 first_box_shadow().color = c;
1459 invalidate_subtree_caches_up();
1460 }
1461 void set_box_shadow_offset(float ox, float oy) {
1462 auto& s = first_box_shadow(); s.offset_x = ox; s.offset_y = oy;
1463 invalidate_subtree_caches_up();
1464 }
1466 // RN's shadowOpacity is 0..1; overwrite the shadow color's normalized
1467 // alpha channel while preserving the existing RGB channels.
1468 first_box_shadow().color.a = a;
1469 invalidate_subtree_caches_up();
1470 }
1472 first_box_shadow().blur = r;
1473 invalidate_subtree_caches_up();
1474 }
1475
1476 std::function<void()> on_click;
1477 std::function<void(const MouseEvent&)> on_pointer_event;
1478 std::function<void(const MouseEvent&, bool)> on_dom_pointer_event;
1479 std::function<void(const MouseEvent&, bool)> on_dom_pointer_move_event;
1483 std::function<void(const MouseEvent&, bool is_dom_origin)> on_dom_wheel_event;
1484 std::function<void(Point)> on_drag;
1492 std::function<void(const MouseEvent&)> on_pointer_move;
1493 std::function<void(const GestureEvent&)> on_gesture_cb;
1496 std::function<void(Point position)> on_context_menu;
1497
1500 std::function<void(const std::string& type, const std::string& data, float x, float y)> on_drop;
1501
1503 std::function<void()> on_hover_enter;
1504 std::function<void()> on_hover_leave;
1505
1506 // ── Overlay painting ────────────────────────────────────────────────
1510 std::function<void(canvas::Canvas&)> paint_fn;
1511 View* owner = nullptr;
1512 };
1513 static std::vector<OverlayRequest>& overlay_queue();
1523 static void paint_overlays(canvas::Canvas& canvas, View* painting_root = nullptr);
1524
1532 std::function<void(canvas::Canvas&, View* painting_root)> hook);
1533 static void set_inspector_key_hook(std::function<bool(const KeyEvent&)> hook);
1535
1547 std::function<bool(const MouseEvent&, View* event_root)> hook);
1549 View* event_root = nullptr);
1550
1561 std::function<bool(const TextInputEvent&, View* event_root)> hook);
1563 View* event_root = nullptr);
1564
1581 std::function<int(const MouseEvent&, View* event_root)> hook);
1583 View* event_root = nullptr);
1584
1585 // ── Generalized overlay-click routing ────────────────────────────────
1586 //
1587 // ComboBox already uses a `static ComboBox* active_popup_` pointer so
1588 // the platform window-host layer can short-circuit hit-testing for
1589 // paint-only overlays (the dropdown items render OUTSIDE the
1590 // ComboBox's hit_test bounds). React popovers built from
1591 // `<View position="absolute">` + nested buttons hit the same problem
1592 // but have no widget-specific shortcut, so clicks fall through to
1593 // whatever sibling/ancestor pixel is under the overlay.
1594 //
1595 // `active_overlay_` is the per-View opt-in equivalent: any View can
1596 // claim itself as the global click-eligible overlay. The window host
1597 // checks this AFTER `ComboBox::active_popup_` (so the ComboBox path
1598 // stays exact-as-was) and BEFORE the regular tree hit_test. If the
1599 // click falls inside the overlay's window-rect, it routes to the
1600 // overlay; otherwise the overlay is auto-released and the click
1601 // continues to the tree.
1602 //
1603 // The @pulp/react host config calls `claim_overlay()` from a JSX
1604 // `<View overlay>` mount and `release_overlay()` from its unmount.
1605 //
1606 // ── Per-root interaction state (pulp #6223 S11) ───────────────────────
1607 //
1608 // focused_input, active_overlay, the overlay paint queue, and (migrated in
1609 // ui_components.hpp) the ComboBox popup slot were process-wide statics. Two
1610 // Pulp editors in one host process — the documented shared-AUHostingService
1611 // case — then shared ONE focus and ONE open popup: focusing a field in
1612 // editor B stole editor A's keyboard, and opening a dropdown in one closed
1613 // the other's. The in-tree drag source already solved this by hanging its
1614 // in-flight record off the ROOT View (see `active_drag_`); this mirrors that
1615 // precedent so each editor's tree owns its own interaction slots.
1616 //
1617 // Reached via `interaction()`: walk to `tree_root()` and lazily allocate the
1618 // struct on the root. Two DISTINCT parented roots never share. A DETACHED
1619 // widget (no parent AND no children — e.g. a bare headless widget) has no
1620 // root of its own, so it resolves to one process-global FALLBACK slot; that
1621 // fallback is the documented shim preserving the historical single-focus /
1622 // single-popup behavior for unhosted widgets. See view.cpp `interaction()`.
1626 ComboBox* active_popup = nullptr; // wired from ui_components (migrated last)
1627 std::vector<OverlayRequest> overlay_queue;
1637 std::vector<View*> overlay_stack;
1640 std::uint64_t pending_overlay_opener = 0;
1641 };
1642
1651
1652 // The historical statics are retained as process-global SHIM MIRRORS,
1653 // written through on every claim/release so the platform hosts that read
1654 // them directly (and already scope the read to their own root — see
1655 // plugin_view_host_mac.mm `pulp_focus_under_root`) keep working unchanged.
1656 // `active_overlay_` / `focused_input_` reflect the most-recently-acted slot
1657 // process-wide; `interaction()` is the per-root source of truth.
1677 void claim_overlay(const View* stacks_on = nullptr);
1680 std::size_t overlay_depth() const;
1682 overlay_consumes_outside_click_ = consume;
1683 }
1685 return overlay_consumes_outside_click_;
1686 }
1687
1688 bool overlay_nests_on(const View* below) const { return below && overlay_nested_on_ == below; }
1701 void set_overlay_trigger(bool is_trigger) { overlay_trigger_ = is_trigger; }
1702 bool overlay_trigger() const { return overlay_trigger_; }
1706 void set_overlay_anchor(const View* anchor);
1708 std::uint64_t overlay_anchor_id() const { return overlay_anchor_id_; }
1736 std::function<void()> on_overlay_dismissed;
1740 bool overlay_contains(Point window_pt) const;
1741
1743 std::function<void(const std::string& id, uint16_t modifiers)> on_global_click;
1744
1747 std::function<bool(const KeyEvent&)> on_global_key;
1750 std::function<bool(const KeyEvent&)> on_navigation_key;
1751
1753 enum class Position { static_, relative, absolute, fixed, sticky };
1754 // Position and the four edge offsets feed the Yoga pass, so a change here
1755 // changes what a geometry query returns and must move the layout
1756 // generation — geometry readers (the script bridge, the host paint path)
1757 // lay out only when that generation moved, and would otherwise answer from
1758 // the pre-move box. Guarded on equality because the design-import replay
1759 // re-applies captured position metadata on every commit; dirtying the tree
1760 // for a write that changed nothing would force a whole-tree pass per
1761 // re-applied binding.
1763 if (position_ == p) return;
1764 position_ = p;
1766 }
1767 Position position() const { return position_; }
1768
1769 // top/right/bottom/left accept either a px value (the single-arg setter) or
1770 // a percent value (the two-arg setter that records the unit). The Yoga
1771 // adapter dispatches on `top_unit_` / etc. and routes percent values through
1772 // YGNodeStyleSetPositionPercent, mirroring the FlexStyle::dim_width pattern
1773 // for the View positional fields.
1778 void set_top(float v, DimensionUnit unit) {
1779 if (has_top_ && top_ == v && top_unit_ == unit) return;
1780 top_ = v; has_top_ = true; top_unit_ = unit;
1782 }
1783 void set_right(float v, DimensionUnit unit) {
1784 if (has_right_ && right_ == v && right_unit_ == unit) return;
1785 right_ = v; has_right_ = true; right_unit_ = unit;
1787 }
1788 void set_bottom(float v, DimensionUnit unit) {
1789 if (has_bottom_ && bottom_ == v && bottom_unit_ == unit) return;
1790 bottom_ = v; has_bottom_ = true; bottom_unit_ = unit;
1792 }
1793 void set_left(float v, DimensionUnit unit) {
1794 if (has_left_ && left_ == v && left_unit_ == unit) return;
1795 left_ = v; has_left_ = true; left_unit_ = unit;
1797 }
1798 float top() const { return top_; }
1799 float right() const { return right_; }
1800 float bottom() const { return bottom_; }
1801 float left() const { return left_; }
1802 DimensionUnit top_unit() const { return top_unit_; }
1803 DimensionUnit right_unit() const { return right_unit_; }
1804 DimensionUnit bottom_unit() const { return bottom_unit_; }
1805 DimensionUnit left_unit() const { return left_unit_; }
1806 bool has_top() const { return has_top_; }
1807 bool has_right() const { return has_right_; }
1808 bool has_bottom() const { return has_bottom_; }
1809 bool has_left() const { return has_left_; }
1810 void set_z_index(int z) {
1811 z_index_ = z;
1812 invalidate_subtree_caches_up();
1813 }
1814 int z_index() const { return z_index_; }
1815
1817 std::vector<View*> sorted_children_by_z_index() const;
1820
1826 enum class Overflow { hidden, visible, scroll };
1828 overflow_ = o;
1829 // A box that no longer scrolls has no scroll position (CSS collapses
1830 // scrollTop to 0 too); a stale offset would keep translating children
1831 // after the clip that justified it was removed.
1832 if (o != Overflow::scroll) {
1833 scroll_offset_x_ = 0.0f;
1834 scroll_offset_y_ = 0.0f;
1835 }
1836 }
1837 Overflow overflow() const { return overflow_; }
1838
1839 // ── Scrollable overflow (`overflow: scroll`, CSS `auto`) ─────────────
1840 //
1841 // A plain View with `Overflow::scroll` is a scroll container: it clips to
1842 // its box, offsets its children by `-scroll_offset`, and consumes the
1843 // wheel. `ScrollView` is the richer widget over the same notion (animated
1844 // offset, scrollbar chrome, drag) and overrides these so one query serves
1845 // either. ONE function backs paint and hit-testing —
1846 // `child_paint_offset()` — so they cannot disagree about where a child is
1847 // (see its doc below).
1848
1851 virtual bool is_scroll_container() const {
1852 return overflow_ == Overflow::scroll;
1853 }
1854
1858 virtual float scroll_offset_x() const {
1859 return scroll_offset_x_;
1860 }
1861 virtual float scroll_offset_y() const {
1862 return scroll_offset_y_;
1863 }
1864
1870
1873 float max_scroll_offset_x() const;
1874 float max_scroll_offset_y() const;
1875
1880 virtual bool set_scroll_offset(float x, float y);
1881 bool scroll_offset_by(float dx, float dy) {
1882 return set_scroll_offset(scroll_offset_x() + dx, scroll_offset_y() + dy);
1883 }
1884
1894 void set_clip_marker_tolerance(bool on) { clip_marker_tolerance_ = on; }
1895 bool clip_marker_tolerance() const { return clip_marker_tolerance_; }
1896
1898 void set_scale(float s) {
1899 if (scale_ == s) return;
1900 scale_ = s; invalidate_subtree_caches_up();
1901 }
1902 float scale() const { return scale_; }
1903
1904 void set_translate(float x, float y) {
1905 if (translate_x_ == x && translate_y_ == y) return;
1906 translate_x_ = x; translate_y_ = y; invalidate_subtree_caches_up();
1907 }
1908 float translate_x() const { return translate_x_; }
1909 float translate_y() const { return translate_y_; }
1910
1911 void set_rotation(float deg) {
1912 if (rotation_deg_ == deg) return;
1913 rotation_deg_ = deg; invalidate_subtree_caches_up();
1914 }
1915 float rotation() const { return rotation_deg_; }
1916
1917 void set_skew(float x_deg, float y_deg) {
1918 if (skew_x_ == x_deg && skew_y_ == y_deg) return;
1919 skew_x_ = x_deg; skew_y_ = y_deg; invalidate_subtree_caches_up();
1920 }
1921
1927 void set_transform_origin(float x, float y) {
1928 if (origin_explicit_ && origin_x_ == x && origin_y_ == y) return;
1929 origin_x_ = x; origin_y_ = y; origin_explicit_ = true;
1930 invalidate_subtree_caches_up();
1931 }
1932 float transform_origin_x() const { return origin_x_; }
1933 float transform_origin_y() const { return origin_y_; }
1934 bool transform_origin_explicit() const { return origin_explicit_; }
1935
1947 void set_transform_matrix(float a, float b, float c,
1948 float d, float e, float f) {
1949 if (has_transform_matrix_ && transform_matrix_a_ == a
1950 && transform_matrix_b_ == b && transform_matrix_c_ == c
1951 && transform_matrix_d_ == d && transform_matrix_e_ == e
1952 && transform_matrix_f_ == f)
1953 return;
1954 transform_matrix_a_ = a;
1955 transform_matrix_b_ = b;
1956 transform_matrix_c_ = c;
1957 transform_matrix_d_ = d;
1958 transform_matrix_e_ = e;
1959 transform_matrix_f_ = f;
1960 has_transform_matrix_ = true;
1961 invalidate_subtree_caches_up();
1962 }
1964 if (!has_transform_matrix_) return;
1965 has_transform_matrix_ = false;
1966 invalidate_subtree_caches_up();
1967 }
1968 bool has_transform_matrix() const { return has_transform_matrix_; }
1969
1975 return has_transform_matrix_ || scale_ != 1.0f || rotation_deg_ != 0.0f ||
1976 translate_x_ != 0.0f || translate_y_ != 0.0f ||
1977 skew_x_ != 0.0f || skew_y_ != 0.0f;
1978 }
1979
1984 bool has_filter_effect() const {
1985 return has_filter_chain() || filter_blur_ > 0.0f;
1986 }
1987
1996 virtual bool applies_child_paint_offset() const {
1997 return scroll_offset_x_ != 0.0f || scroll_offset_y_ != 0.0f;
1998 }
1999
2015 virtual Point child_paint_offset(const View& child) const {
2016 if (scroll_offset_x_ == 0.0f && scroll_offset_y_ == 0.0f)
2017 return Point{0.0f, 0.0f};
2018 // A `position: sticky` child stays pinned vertically while the content
2019 // scrolls beneath it — same rule ScrollView applies.
2020 if (child.position() == Position::sticky)
2021 return Point{-scroll_offset_x_, 0.0f};
2022 return Point{-scroll_offset_x_, -scroll_offset_y_};
2023 }
2024
2027 void get_transform_matrix(float& a, float& b, float& c,
2028 float& d, float& e, float& f) const {
2029 a = transform_matrix_a_; b = transform_matrix_b_; c = transform_matrix_c_;
2030 d = transform_matrix_d_; e = transform_matrix_e_; f = transform_matrix_f_;
2031 }
2032
2036 void set_filter_blur(float radius) { filter_blur_ = radius; }
2037 float filter_blur() const { return filter_blur_; }
2038
2047 struct FilterOp {
2048 enum class Kind {
2049 blur,
2050 brightness,
2051 contrast,
2052 grayscale,
2053 hue_rotate,
2054 invert,
2056 saturate,
2057 sepia,
2058 drop_shadow,
2059 };
2061 float amount = 0.0f;
2062 float angle_deg = 0.0f;
2063 // drop-shadow extras
2064 float ds_offset_x = 0.0f;
2065 float ds_offset_y = 0.0f;
2066 float ds_blur = 0.0f;
2068 };
2069 void set_filter_chain(std::vector<FilterOp> chain) { filter_chain_ = std::move(chain); }
2070 void clear_filter_chain() { filter_chain_.clear(); }
2071 const std::vector<FilterOp>& filter_chain() const { return filter_chain_; }
2072 bool has_filter_chain() const { return !filter_chain_.empty(); }
2073
2078 void set_transitions(std::vector<TransitionSpec> ts) { transitions_ = std::move(ts); }
2079 void clear_transitions() { transitions_.clear(); }
2080 const std::vector<TransitionSpec>& transitions() const { return transitions_; }
2081 bool has_transitions() const { return !transitions_.empty(); }
2082
2087 const TransitionSpec* find_transition_for(const std::string& property) const {
2088 const TransitionSpec* match = nullptr;
2089 for (const auto& t : transitions_) {
2090 if (t.property_name == "all") match = &t;
2091 if (t.property_name == property) { match = &t; }
2092 }
2093 return match;
2094 }
2095
2098 std::vector<CssAnimation>& active_animations() { return active_animations_; }
2099 const std::vector<CssAnimation>& active_animations() const { return active_animations_; }
2100
2110 int tick_animations(float dt) {
2111 if (animation_play_state_ == "paused") return 0;
2112 int finished = 0;
2113 for (auto& a : active_animations_) {
2114 if (!a.active) continue;
2115 const bool was_active = a.active;
2116 a.tick(dt);
2117 if (was_active && !a.active) ++finished;
2118 }
2119 return finished;
2120 }
2121
2131 std::string name;
2132 float duration_seconds = 0.0f;
2133 float delay_seconds = 0.0f;
2135 float iterations = 1.0f;
2136 std::string direction = "normal";
2137 std::string fill_mode;
2138 };
2139 StagedAnimation& staged_animation() { return style_extras().staged_animation; }
2141 static const StagedAnimation kEmpty;
2142 return style_extras_ ? style_extras_->staged_animation : kEmpty;
2143 }
2144
2148 void set_backdrop_blur(float radius) { style_extras().backdrop_blur = radius; }
2149 float backdrop_blur() const { return style_extras_ ? style_extras_->backdrop_blur : 0.0f; }
2150
2159 void set_backdrop_filter_chain(std::vector<FilterOp> chain) {
2160 style_extras().backdrop_filter_chain = std::move(chain);
2161 }
2162 const std::vector<FilterOp>& backdrop_filter_chain() const {
2163 static const std::vector<FilterOp> kEmpty;
2164 return style_extras_ ? style_extras_->backdrop_filter_chain : kEmpty;
2165 }
2166
2187 void set_ancestor_clip_rect(Rect r) { style_extras().ancestor_clip = r; }
2188 const std::optional<Rect>& ancestor_clip_rect() const {
2189 static const std::optional<Rect> kNone;
2190 return style_extras_ ? style_extras_->ancestor_clip : kNone;
2191 }
2192
2200 void set_ancestor_clip_radii(float tl, float tr, float br, float bl) {
2201 style_extras().ancestor_clip_radii = {tl, tr, br, bl};
2202 }
2203 const std::array<float, 4>& ancestor_clip_radii() const {
2204 static const std::array<float, 4> kNone{0.0f, 0.0f, 0.0f, 0.0f};
2205 return style_extras_ ? style_extras_->ancestor_clip_radii : kNone;
2206 }
2207
2208 void set_clip_path(const std::string& svg_path_d) { style_extras().clip_path = svg_path_d; }
2209 const std::string& clip_path() const {
2210 static const std::string kEmpty;
2211 return style_extras_ ? style_extras_->clip_path : kEmpty;
2212 }
2213 bool has_clip_path() const { return style_extras_ && !style_extras_->clip_path.empty(); }
2214
2219 void set_mask_image(const std::string& value) { style_extras().mask_image = value; }
2220 const std::string& mask_image() const {
2221 static const std::string kEmpty;
2222 return style_extras_ ? style_extras_->mask_image : kEmpty;
2223 }
2224
2228 void set_mask(const std::string& value) { style_extras().mask = value; }
2229 const std::string& mask() const {
2230 static const std::string kEmpty;
2231 return style_extras_ ? style_extras_->mask : kEmpty;
2232 }
2233
2237 void set_mask_size(const std::string& value) { style_extras().mask_size = value; }
2238 const std::string& mask_size() const {
2239 static const std::string kEmpty;
2240 return style_extras_ ? style_extras_->mask_size : kEmpty;
2241 }
2242
2250 void set_appearance(const std::string& value) { style_extras().appearance = value; }
2251 const std::string& appearance() const {
2252 static const std::string kEmpty;
2253 return style_extras_ ? style_extras_->appearance : kEmpty;
2254 }
2255
2261 void set_object_fit(const std::string& value) { style_extras().object_fit = value; }
2262 const std::string& object_fit() const {
2263 static const std::string kEmpty;
2264 return style_extras_ ? style_extras_->object_fit : kEmpty;
2265 }
2266
2271 void set_object_position(const std::string& value) { style_extras().object_position = value; }
2272 const std::string& object_position() const {
2273 static const std::string kEmpty;
2274 return style_extras_ ? style_extras_->object_position : kEmpty;
2275 }
2276
2287 void set_background_attachment(std::string kw) { style_extras().background_attachment = std::move(kw); }
2288 const std::string& background_attachment() const {
2289 static const std::string kEmpty;
2290 return style_extras_ ? style_extras_->background_attachment : kEmpty;
2291 }
2292 void set_background_clip(std::string kw) { style_extras().background_clip = std::move(kw); }
2293 const std::string& background_clip() const {
2294 static const std::string kEmpty;
2295 return style_extras_ ? style_extras_->background_clip : kEmpty;
2296 }
2297 void set_background_origin(std::string kw) { style_extras().background_origin = std::move(kw); }
2298 const std::string& background_origin() const {
2299 static const std::string kEmpty;
2300 return style_extras_ ? style_extras_->background_origin : kEmpty;
2301 }
2302
2315 void set_background_position(std::string kw) { style_extras().background_position = std::move(kw); }
2316 const std::string& background_position() const {
2317 static const std::string kEmpty;
2318 return style_extras_ ? style_extras_->background_position : kEmpty;
2319 }
2320 void set_background_size(std::string kw) { style_extras().background_size = std::move(kw); }
2321 const std::string& background_size() const {
2322 static const std::string kEmpty;
2323 return style_extras_ ? style_extras_->background_size : kEmpty;
2324 }
2325
2326 // Storage-only slots for CSS properties that the bridge accepts but View
2327 // does not fully consume. Each slot is round-trippable so harness tests can
2328 // verify the bridge accepts the value, and so a paint path can honor it
2329 // later without a JS-side change. Catalog status documents the
2330 // implementation depth (`partial` / `noop` / `wontfix`).
2331 void set_text_indent(float v) { text_indent_ = v; }
2332 float text_indent() const { return text_indent_; }
2333 void set_word_break(std::string kw) { word_break_ = std::move(kw); }
2334 const std::string& word_break() const { return word_break_; }
2335
2343 void set_scroll_behavior(std::string kw) { scroll_behavior_ = std::move(kw); }
2344 const std::string& scroll_behavior() const { return scroll_behavior_; }
2345 void set_overscroll_behavior(std::string kw) { overscroll_behavior_ = std::move(kw); }
2346 const std::string& overscroll_behavior() const { return overscroll_behavior_; }
2347
2354 void set_include_font_padding(bool v) { include_font_padding_ = v; }
2355 bool include_font_padding() const { return include_font_padding_; }
2356
2357 void set_font_variant(std::string kw) { font_variant_ = std::move(kw); }
2358 const std::string& font_variant() const { return font_variant_; }
2359 void set_writing_mode(std::string kw) { writing_mode_ = std::move(kw); }
2360 const std::string& writing_mode() const { return writing_mode_; }
2361 void set_isolation(std::string kw) { isolation_ = std::move(kw); }
2362 const std::string& isolation() const { return isolation_; }
2363 void set_resize(std::string kw) { resize_ = std::move(kw); }
2364 const std::string& resize() const { return resize_; }
2368 void set_animation_play_state(std::string kw) { animation_play_state_ = std::move(kw); }
2369 const std::string& animation_play_state() const { return animation_play_state_; }
2370
2373 void set_continuous_repaint(bool on) { wants_continuous_repaint_ = on; }
2374 bool wants_continuous_repaint() const { return wants_continuous_repaint_; }
2375
2376 RuntimeViewKind runtime_view_kind() const noexcept { return runtime_view_kind_; }
2377
2378protected:
2379 void mark_runtime_view_kind(RuntimeViewKind kind) { runtime_view_kind_ = kind; }
2380
2381public:
2387 void set_text_shadow_color(std::string c) { text_shadow_color_ = std::move(c); }
2388 const std::string& text_shadow_color() const { return text_shadow_color_; }
2389 void set_text_shadow_offset(float dx, float dy){ text_shadow_dx_ = dx; text_shadow_dy_ = dy; }
2390 float text_shadow_offset_x() const { return text_shadow_dx_; }
2391 float text_shadow_offset_y() const { return text_shadow_dy_; }
2392 void set_text_shadow_radius(float r) { text_shadow_radius_ = r; }
2393 float text_shadow_radius() const { return text_shadow_radius_; }
2394
2395
2398 void set_needs_layer(bool v) { needs_layer_ = v; }
2399 bool needs_layer() const { return needs_layer_; }
2400
2433 bool subtree_cached() const { return subtree_cached_; }
2434
2443
2445 void set_effect(std::shared_ptr<canvas::ViewEffect> effect) { effect_ = std::move(effect); }
2446 const std::shared_ptr<canvas::ViewEffect>& effect() const { return effect_; }
2447
2454 WindowHost* window_host() const { return window_host_; }
2455
2461 PluginViewHost* plugin_view_host() const { return plugin_view_host_; }
2462
2471 virtual bool accepts_navigation_input() const {
2472 return scripted_navigation_input_;
2473 }
2474
2482 HostParamSurface* host_params() const { return host_params_; }
2483
2487 HostActionSurface* host_actions() const { return host_actions_; }
2488
2496 int type = 0; // 0=none, 1=linear, 2=radial, 3=conic
2497 // Index in the AUTHOR'S background-image list. `none` entries do
2498 // not paint and are intentionally absent from bg_gradients_, but they
2499 // still consume a background-size/repeat/position list slot.
2500 std::size_t css_image_layer_index = 0;
2501 float x0 = 0, y0 = 0, x1 = 0, y1 = 1;
2502 float radius = 0.7071f; // radial: fraction of max(w,h)
2503 float angle = 0.0f; // conic: start angle in radians
2504 float sweep_turns = 1.0f; // conic: turns the stop list spans
2505 std::vector<Color> colors;
2506 std::vector<float> positions;
2507
2508 // ── Geometry only a laid-out box can resolve ────────────────────
2509 //
2510 // CSS gradient geometry is a function of the box: an angle's endpoints
2511 // depend on the aspect ratio, and a radial's radii are percentages of
2512 // the width and height. Style is applied BEFORE the box is sized —
2513 // the design importer runs the whole style pass ahead of Yoga — so
2514 // anything resolved when the CSS is parsed is resolved against a
2515 // degenerate 1x1 box, which silently turns every angled gradient the
2516 // wrong way and gives every radial the wrong radius. These slots carry
2517 // the CSS intent forward instead, and the painter resolves them
2518 // against the real bounds.
2519
2523 enum class LinearFrom { endpoints, angle, corner };
2527 float linear_angle = 0.0f;
2530 float corner_x = 1.0f, corner_y = 1.0f;
2531
2537 float linear_repeat = 0.0f;
2543 enum class RepeatUnit { px, line_fraction };
2545
2559 bool positions_in_px = false;
2560
2565 enum class RadialSize {
2566 max_side, farthest_corner, farthest_side, closest_corner,
2567 closest_side, explicit_radii,
2568 };
2573 bool radial_circle = false;
2578 float radial_rx = 0.0f, radial_ry = 0.0f;
2579 float radial_rx_px = 0.0f, radial_ry_px = 0.0f;
2581 };
2582
2584 struct ResolvedRadial { float cx, cy, rx, ry; };
2585
2590 float w, float h);
2591
2593 void set_background_gradient_layers(std::vector<BackgroundGradient> layers) {
2594 bg_gradients_ = std::move(layers);
2595 invalidate_subtree_caches_up();
2596 }
2597 const std::vector<BackgroundGradient>& background_gradient_layers() const {
2598 return bg_gradients_;
2599 }
2600
2602 void set_background_gradient_linear(float x0, float y0, float x1, float y1,
2603 const std::vector<Color>& colors,
2604 const std::vector<float>& positions) {
2606 g.type = 1; // linear
2607 g.x0 = x0; g.y0 = y0; g.x1 = x1; g.y1 = y1;
2608 g.colors = colors;
2609 g.positions = positions;
2610 set_background_gradient_layers({std::move(g)});
2611 }
2612
2614 void set_background_gradient_radial(float cx, float cy, float radius_frac,
2615 const std::vector<Color>& colors,
2616 const std::vector<float>& positions) {
2618 g.type = 2; // radial
2619 g.x0 = cx; g.y0 = cy;
2620 g.radius = radius_frac;
2621 g.colors = colors;
2622 g.positions = positions;
2623 set_background_gradient_layers({std::move(g)});
2624 }
2625
2631 void set_background_gradient_conic(float cx, float cy, float start_angle,
2632 const std::vector<Color>& colors,
2633 const std::vector<float>& positions,
2634 float sweep_turns = 1.0f) {
2636 g.type = 3; // conic / sweep
2637 g.x0 = cx; g.y0 = cy;
2638 g.angle = start_angle;
2639 g.sweep_turns = sweep_turns;
2640 g.colors = colors;
2641 g.positions = positions;
2642 set_background_gradient_layers({std::move(g)});
2643 }
2644 // The queries below report the TOP layer — the one CSS lists first. They
2645 // predate layering and every caller means "the gradient this view shows".
2649 return bg_gradients_.empty() ? 1.0f : bg_gradients_.front().sweep_turns;
2650 }
2652 bg_gradients_.clear();
2653 invalidate_subtree_caches_up();
2654 }
2655 bool has_background_gradient() const { return !bg_gradients_.empty(); }
2658 return bg_gradients_.empty() ? 0 : bg_gradients_.front().type;
2659 }
2660
2666 return bg_gradients_.empty() ? 0.7071f : bg_gradients_.front().radius;
2667 }
2668
2670 void set_text_overflow_ellipsis(bool e) { text_ellipsis_ = e; }
2671 bool text_overflow_ellipsis() const { return text_ellipsis_; }
2672
2679 enum class WritingDirection { ltr, rtl, auto_ };
2680 void set_direction(WritingDirection d) { direction_ = d; }
2681 WritingDirection direction() const { return direction_; }
2686 return direction_ == WritingDirection::auto_ ? WritingDirection::ltr : direction_;
2687 }
2688
2695 // Full CSS `white-space` enum. Replaces the nowrap-only bool with the
2696 // spec's 6 keywords. Per CSS Text
2697 // Module Level 3 §3:
2698 // normal collapse drop_nl wrap
2699 // nowrap collapse drop_nl nowrap
2700 // pre preserve preserve nowrap
2701 // pre_wrap preserve preserve wrap
2702 // pre_line collapse preserve wrap
2703 // break_spaces preserve preserve wrap (extra break opps)
2704 enum class WhiteSpaceMode {
2705 normal, nowrap, pre, pre_wrap, pre_line, break_spaces
2706 };
2707 // set_white_space_nowrap() also keeps the WhiteSpaceMode enum in sync so
2708 // callers using the legacy setter don't leave white_space_mode() stale.
2709 // The enum is pinned to nowrap (true) or normal (false); we can't infer
2710 // pre/pre-wrap/etc. from a bool, so the legacy setter only ever produces
2711 // these two modes.
2713 white_space_nowrap_ = n;
2714 white_space_mode_ = n ? WhiteSpaceMode::nowrap : WhiteSpaceMode::normal;
2715 }
2716 bool white_space_nowrap() const { return white_space_nowrap_; }
2717
2719 white_space_mode_ = m;
2720 // `pre` also pins nowrap: it preserves newlines and spaces while
2721 // disabling soft wrapping.
2722 white_space_nowrap_ = (m == WhiteSpaceMode::nowrap || m == WhiteSpaceMode::pre);
2723 }
2724 WhiteSpaceMode white_space_mode() const { return white_space_mode_; }
2725
2735 canvas::Canvas::BlendMode mix_blend_mode() const { return mix_blend_mode_; }
2737 return mix_blend_mode_ != canvas::Canvas::BlendMode::normal;
2738 }
2739
2741 enum class CursorStyle {
2742 default_, pointer, crosshair, text, grab, grabbing, not_allowed,
2744 horizontal_resize,
2745 vertical_resize,
2746 top_left_resize,
2747 top_right_resize,
2748 bottom_left_resize,
2749 bottom_right_resize,
2750 multi_directional_resize,
2751 // CSS cursor keywords with native macOS NSCursor mappings. Other CSS
2752 // keywords without dedicated visuals (wait / help / progress / cell)
2753 // stay catalog-unsupported because no native cursor exists on macOS.
2754 alias,
2755 copy,
2756 zoom_in,
2757 zoom_out,
2759 };
2760 void set_cursor(CursorStyle c) { cursor_ = c; }
2761 CursorStyle cursor() const { return cursor_; }
2762
2767 enum class UserSelect { auto_, none, text, all, contain };
2768 void set_user_select(UserSelect s) { user_select_ = s; }
2769 UserSelect user_select() const { return user_select_; }
2770
2771private:
2775 static std::uint32_t overlay_claims_live_;
2778 static bool detach_overlay(RootInteractionState& state, View* victim);
2781 static void republish_overlay(RootInteractionState& state);
2784 bool is_overlay_descendant_of(const View* ancestor) const;
2789 bool paint_children_overlay_last(canvas::Canvas& canvas);
2790 friend class WidgetBridge;
2791 friend class ViewCapture;
2792 friend class ScrollView;
2793 friend class DispatchLease;
2794 friend Point point_to_local(Point root_pos, View* target, View* root);
2795
2796 void note_layout_mutation() noexcept;
2797
2800 void drain_retired() noexcept;
2802 void deliver_frame_clock_hooks() noexcept;
2806 void walk_frame_clock(std::uint64_t epoch, std::uint64_t sequence) noexcept;
2807
2811 bool inverse_scale_transform(Point& point) const noexcept;
2812
2813 void begin_visibility_quarantine() noexcept {
2814 if (visibility_quarantine_count_++ == 0)
2815 visible_after_quarantine_ = visible_;
2816 set_visible_from_quarantine(false);
2817 }
2818 void refresh_visibility_quarantine() noexcept {
2819 set_visible_from_quarantine(false);
2820 }
2821 void end_visibility_quarantine() {
2822 if (visibility_quarantine_count_ == 0)
2823 return;
2824 --visibility_quarantine_count_;
2825 if (visibility_quarantine_count_ == 0)
2826 set_visible(visible_after_quarantine_);
2827 }
2828 void set_visible_from_quarantine(bool visible) noexcept {
2829 visible_ = visible;
2830 invalidate_subtree_caches_up();
2831 }
2832 static void set_subtree_detaching(View& view, bool detaching) noexcept;
2833 void publish_structure_change() noexcept;
2834 std::vector<GestureRecognizer*> collect_realm_reset_gestures() const;
2835 void prepare_children_for_realm_reset(
2836 const std::vector<GestureRecognizer*>& removed_recognizers) noexcept;
2837 void disconnect_frame_clock_for_realm_reset() noexcept;
2838 void finish_realm_reset_detach() noexcept;
2839 void retire_interaction_state_for_realm_reset(
2840 std::unique_ptr<ActiveDrag>& retired_drag,
2841 std::unique_ptr<RootInteractionState>& retired_interaction) noexcept;
2842 std::unique_ptr<View> extract_child_for_realm_reset(View* child) noexcept;
2843 void adopt_child_for_realm_reset(std::unique_ptr<View> child) noexcept;
2844 void retire_children_for_realm_reset(
2845 std::vector<std::unique_ptr<View>>& retired) noexcept;
2846
2850 void notify_frame_clock_changed() noexcept;
2851
2858 void sync_value_bindings();
2859
2862 void register_value_binding(FrameClockBinding* b);
2863 void unregister_value_binding(FrameClockBinding* b);
2864 friend class FrameClockBinding;
2865
2869 void promote_uniform_to_per_corner() {
2870 if (!has_corner_radii_ && corner_radius_ > 0.0f) {
2871 corner_radii_[0] = corner_radius_;
2872 corner_radii_[1] = corner_radius_;
2873 corner_radii_[2] = corner_radius_;
2874 corner_radii_[3] = corner_radius_;
2875 }
2876 }
2877
2878 // ── paint_all decomposition (behavior-preserving) ─────────────────────
2879 // paint_all() is an orchestrator over these private helpers. The one
2880 // load-bearing invariant is the compositing-layer imbalance: every helper
2881 // enters and leaves the canvas at the SAME save depth it does today,
2882 // EXCEPT push_effect_layers / pop_effect_layers, which own the imbalance by
2883 // contract — push returns the exact count/flag it opened and pop consumes
2884 // it, so the push/pop pair is auditable in isolation. Splitting the monolith
2885 // this way also gives FU-3's subtree cache a clean "content" seam
2886 // (paint_content) that excludes the effect/opacity layer wrappers.
2887 struct EffectLayerState {
2888 int layers_pushed = 0;
2889 bool backdrop_pushed = false;
2890 };
2891 void apply_canvas_transforms(canvas::Canvas& canvas);
2892 EffectLayerState push_effect_layers(canvas::Canvas& canvas);
2893 void pop_effect_layers(canvas::Canvas& canvas, const EffectLayerState& layers);
2894 // The FU-3 cache-capture unit: everything painted INSIDE the effect layers
2895 // (shadows, clip, background/border, paint(), children, decorations).
2896 // children_ns receives the recursive child-paint time for self-time attrib.
2897 void paint_content(canvas::Canvas& canvas, const EffectLayerState& layers,
2898 std::int64_t& children_ns);
2899 // FU-3 wrapper around paint_content: replays the cached scene when caching
2900 // is on, the backend supports it, and the cache is valid; otherwise records
2901 // (on a miss) or paints directly. Called from the paint_all orchestrator in
2902 // place of paint_content so the effect/opacity layers stay outside the cache.
2903 void paint_content_maybe_cached(canvas::Canvas& canvas,
2904 const EffectLayerState& layers,
2905 std::int64_t& children_ns);
2906 // Clear the scene cache on this view and every ancestor that has caching
2907 // enabled (a mutation anywhere in a cached subtree stales that subtree's
2908 // recording). Walks parent_ links; O(depth), and skipped entirely via a
2909 // process-global counter when no view anywhere has caching enabled.
2910 void invalidate_subtree_caches_up();
2911 void paint_outset_shadows(canvas::Canvas& canvas);
2912 void apply_overflow_clip(canvas::Canvas& canvas);
2913 void apply_clip_path(canvas::Canvas& canvas);
2914 void paint_background_and_border(canvas::Canvas& canvas);
2919 using CornerPathBuilder =
2920 std::function<void(float w, float h, float tl, float tr,
2921 float bl, float br)>;
2922 void paint_border(canvas::Canvas& canvas, float paint_w, float paint_h,
2923 bool use_per_corner,
2924 const CornerPathBuilder& build_corner_path,
2925 float eff_r, float eff_tl, float eff_tr,
2926 float eff_bl, float eff_br);
2927 void paint_children_in_order(canvas::Canvas& canvas);
2928 void paint_post_decorations(canvas::Canvas& canvas, const EffectLayerState& layers);
2929
2930 Rect bounds_{};
2931 FlexStyle flex_{};
2932 GridStyle grid_{};
2933 LayoutMode layout_mode_ = LayoutMode::flex;
2934 bool subpixel_layout_ = false;
2935 bool captured_frame_root_ = false;
2936 Theme theme_;
2937 std::shared_ptr<WidgetPainter> painter_;
2938 std::shared_ptr<WidgetMetrics> metrics_;
2941 std::unique_ptr<ActiveDrag> active_drag_;
2945 std::unique_ptr<RootInteractionState> interaction_state_;
2946 // Only the root's value is observed and bumped. Atomic prevents a native
2947 // provider's incidental read from racing the owner-thread detach publish.
2948 std::atomic<std::uint64_t> structure_generation_{1};
2949 // Set across an entire subtree before the first virtual detach callback.
2950 // ViewCapture treats this as already absent even while on_detached() still
2951 // needs the old parent link to release parent-owned resources.
2952 std::atomic<bool> detaching_{false};
2953 // ── Mutation/lifetime gate (view_lifecycle.hpp) ──────────────────────
2954 // Number of DispatchLeases open anywhere on this tree. Only the ROOT's
2955 // copy is raised; retirement drains when it falls back to zero.
2956 std::uint32_t lease_depth_ = 0;
2957 // Leases naming THIS view specifically. Non-zero means a callback on it is
2958 // executing, so destroying it now would free a live frame.
2959 std::uint16_t dispatch_depth_ = 0;
2960 // Set for the duration of ~View so a child destroyed as part of its
2961 // parent's teardown does not trip the "destroyed while attached" assert.
2962 bool destroying_ = false;
2963 // True while a frame-clock walk is in flight on this ROOT. Children added
2964 // during a walk are stamped as already-visited so they wait for the next
2965 // pass instead of being visited mid-mutation.
2966 bool clock_walk_active_ = false;
2967 // Root-only. Set when a hook requests propagation during an active walk;
2968 // the outermost caller runs one more bounded pass to service it.
2969 bool clock_walk_pending_ = false;
2970 // Root-only, and meaningful only while a walk is in flight: the traversal
2971 // token of the pass currently running, published so a mid-pass attach can
2972 // stamp the incoming subtree as belonging to it.
2973 std::uint64_t clock_epoch_ = 0;
2974 // Per view. The traversal stamp makes a pass visit each node at most once
2975 // even while hooks mutate children_; the delivery stamp makes the whole
2976 // call notify each node at most once across all of its passes. They are
2977 // separate because a later pass must be free to walk THROUGH an
2978 // already-notified node to reach a descendant attached mid-pass.
2979 //
2980 // Both hold PROCESS-GLOBAL monotonic tokens, never per-root counters. A
2981 // view outlives its root — remove_child hands a detached subtree its own
2982 // root and notifies it immediately — so a stamp must mean the same thing in
2983 // every tree. See next_clock_walk_token() in view.cpp.
2984 std::uint64_t clock_walk_epoch_ = 0;
2985 std::uint64_t clock_delivery_sequence_ = 0;
2986 // Intrusive owning retirement chain. Root-only head; each retired view
2987 // carries the link to the next, so parking one allocates nothing.
2988 std::unique_ptr<View> retired_head_;
2989 std::unique_ptr<View> retired_next_;
2990 View* parent_ = nullptr;
2991 std::vector<std::unique_ptr<View>> children_;
2992 std::string id_;
2993 // Design-import anchor identity. Empty for views not constructed from an
2994 // imported tree. See set_anchor_id().
2995 std::string anchor_id_;
2996 std::uint64_t import_binding_instance_id_ = 0;
2997 std::shared_ptr<const std::uint64_t> import_binding_lifetime_token_;
2998 // Authored-source location (JSX file:line:col) from the React reconciler's
2999 // `__source` prop. Unset for non-imported views.
3000 std::optional<SourceLocation> source_loc_;
3001 // Last-paint-cycle timing. Both 0 until paint_all() has executed at least
3002 // once.
3003 std::uint32_t last_paint_self_ns_ = 0;
3004 std::uint32_t last_paint_with_children_ns_ = 0;
3005 AccessRole access_role_ = AccessRole::none;
3006 AccessRole implicit_access_role_ = AccessRole::none;
3007 RuntimeViewKind runtime_view_kind_ = RuntimeViewKind::generic;
3008 std::string access_label_; // author-set (aria-label) — wins
3009 std::string derived_access_label_; // content-derived (visible text)
3010 std::string access_value_;
3011 // ARIA state attributes (tri-state per spec).
3012 std::string access_pressed_;
3013 std::string access_checked_;
3014 std::string access_disabled_;
3015 std::string access_hidden_;
3016 bool visible_ = true;
3017 std::size_t visibility_quarantine_count_ = 0;
3018 bool visible_after_quarantine_ = true;
3019 bool focusable_ = false;
3020 bool enabled_ = true;
3021 bool layout_dirty_ = false;
3022 std::uint64_t applied_layout_generation_ = 0;
3023 std::uint64_t tree_layout_generation_ = 1;
3024 static std::atomic<std::uint64_t> layout_generation_;
3025 static std::atomic<std::uint64_t> layout_pass_count_;
3026 static std::atomic<std::uint64_t> damage_request_count_;
3027 static std::atomic<std::uint64_t> unmarked_paint_mutation_count_;
3028 static std::atomic<std::uint64_t> constructed_count_;
3029 static std::atomic<std::uint64_t> destroyed_count_;
3032 void stale_subtree_caches_up();
3033 bool has_focus_ = false;
3034 // WidgetBridge may lend the root focus slot to a materialized document
3035 // while that document has an explicit, bounded navigation interaction.
3036 // This is intentionally private: ordinary roots must never become general
3037 // keyboard sinks, and the bridge clears the capability on release/teardown.
3038 bool scripted_navigation_input_ = false;
3039 bool hovered_ = false;
3040 bool default_hover_feedback_ = false;
3041 bool hit_testable_ = true;
3042 bool text_selection_region_ = false;
3043 HitSlop hit_slop_{};
3044 PointerEvents pointer_events_ = PointerEvents::auto_;
3045 bool backface_visible_ = true;
3046 bool requires_gpu_host_ = false;
3047 bool contains_native_overlay_ = false;
3048 bool overlay_consumes_outside_click_ = false;
3049 const View* overlay_nested_on_ = nullptr; // compared only; see claim_overlay
3050 bool overlay_trigger_ = false;
3051 bool overlay_anchor_explicit_ = false;
3052 std::uint64_t overlay_anchor_id_ = 0; // instance id; see set_overlay_anchor
3053 FrameClock* frame_clock_ = nullptr;
3054 // Lazily allocated on the first set_meter_source / set_scalar_source, so a
3055 // view that shows no live value costs one null pointer.
3056 std::unique_ptr<ViewValueBindings> value_bindings_;
3057 // Head of the intrusive list of every FrameClockBinding owned by this view —
3058 // the two above plus any a subclass holds (DesignFrameView's per-element
3059 // scalars). Intrusive so enrolling a binding never allocates.
3060 FrameClockBinding* value_binding_head_ = nullptr;
3061
3062 // Visual properties
3063 float opacity_ = 1.0f;
3064 Color bg_color_{};
3065 bool has_bg_ = false;
3066 Color border_color_{};
3067 float border_width_ = 0;
3068 float corner_radius_ = 0;
3069 // borderRadius % support. When > 0, paint code resolves
3070 // effective radius as `corner_radius_pct_ * 0.01 * min(width, height)`.
3071 // 0 means "use plain corner_radius_ in px". Same pattern for the
3072 // per-corner radii_pct_ slots below.
3073 float corner_radius_pct_ = 0;
3074 // RN `borderCurve` corner shape.
3075 BorderCurve border_curve_ = BorderCurve::circular;
3076 bool has_border_ = false;
3077 BorderStyle border_style_ = BorderStyle::solid;
3078 // list-style cluster slots. Stored verbatim; paint-
3079 // time marker rendering is deferred. Defaults match CSS spec
3080 // (`disc` for the type, `outside` for the position, empty image).
3081 ListStyleType list_style_type_ = ListStyleType::disc;
3082 std::string list_style_image_{};
3083 ListStylePosition list_style_position_ = ListStylePosition::outside;
3084 // CSS / RN outline cluster. Defaults: outline_style_
3085 // is `none` so paint short-circuits unless JS opts in via
3086 // setOutlineStyle. width=0 also short-circuits as a belt-and-braces
3087 // guard. Color defaults to fully-transparent black; bridge writes
3088 // the parsed setter value before paint.
3089 Color outline_color_{};
3090 float outline_offset_ = 0.0f;
3091 float outline_width_ = 0.0f;
3092 BorderStyle outline_style_ = BorderStyle::none;
3093 // Per-side borders
3094 struct BorderSide { Color color{}; float width = 0; };
3095 BorderSide border_top_{}, border_right_{}, border_bottom_{}, border_left_{};
3096 bool has_border_sides_ = false;
3097 // Per-edge "explicitly set" flags, parallel to has_top_
3098 // / has_right_ / etc. for inset edges. Required so an explicit
3099 // borderTopWidth=0 overrides the uniform borderWidth=10 shorthand
3100 // (CSS / RN semantics). Plain `width == 0` is ambiguous because the
3101 // BorderSide default-initializes to 0.
3102 bool border_top_set_ = false;
3103 bool border_right_set_ = false;
3104 bool border_bottom_set_ = false;
3105 bool border_left_set_ = false;
3106 // Parallel flags for the per-edge COLOR longhands. Separate from the width
3107 // flags because CSS treats them as independent: `border-top-color` alone
3108 // must not make the top edge's width explicit.
3109 bool border_top_color_set_ = false;
3110 bool border_right_color_set_ = false;
3111 bool border_bottom_color_set_ = false;
3112 bool border_left_color_set_ = false;
3113 // Per-corner radii
3114 float corner_radii_[4] = {0, 0, 0, 0}; // TL, TR, BL, BR
3115 // % support paired with corner_radii_. >0 means use pct
3116 // resolution, 0 means use the px slot above. Sized 4 (TL, TR, BL, BR).
3117 float corner_radii_pct_[4] = {0, 0, 0, 0};
3118 bool has_corner_radii_ = false;
3119 Position position_ = Position::static_;
3120 float top_ = 0, right_ = 0, bottom_ = 0, left_ = 0;
3121 bool has_top_ = false, has_right_ = false, has_bottom_ = false, has_left_ = false;
3122 // Per-edge inset unit. `px` is the default; `percent` flows through to
3123 // YGNodeStyleSetPositionPercent in yoga_layout.cpp. Other DimensionUnit
3124 // values (vw/vh/etc.) round down to px at the bridge boundary today.
3125 DimensionUnit top_unit_ = DimensionUnit::px;
3126 DimensionUnit right_unit_ = DimensionUnit::px;
3127 DimensionUnit bottom_unit_ = DimensionUnit::px;
3128 DimensionUnit left_unit_ = DimensionUnit::px;
3129 int z_index_ = 0;
3130 // Default is `visible` to match CSS. Pulp previously
3131 // defaulted to `hidden`, which clipped absolutely-positioned children
3132 // (popovers, dropdowns, tooltips) to the parent's content bounds and
3133 // made them invisible whenever they extended outside. Plugins that
3134 // intentionally need clipping must call set_overflow(Overflow::hidden)
3135 // explicitly — same opt-in as `overflow:hidden` in CSS.
3136 Overflow overflow_ = Overflow::visible;
3139 float scroll_offset_x_ = 0.0f, scroll_offset_y_ = 0.0f;
3142 bool clip_marker_tolerance_ = false;
3144 std::vector<BoxShadow> shadows_;
3147 BoxShadow& first_box_shadow() {
3148 if (shadows_.empty()) shadows_.emplace_back();
3149 return shadows_.front();
3150 }
3151 float scale_ = 1.0f;
3152 float translate_x_ = 0, translate_y_ = 0;
3153 float rotation_deg_ = 0;
3154 float skew_x_ = 0, skew_y_ = 0;
3155 float origin_x_ = 0.5f, origin_y_ = 0.5f; // transform-origin (normalized)
3156 bool origin_explicit_ = false; // has set_transform_origin been called?
3157 // Full 2D affine matrix. Identity by default; only applied
3158 // when has_transform_matrix_ is true. Stored in CanvasRenderingContext2D
3159 // (a,b,c,d,e,f) order: [a c e / b d f / 0 0 1].
3160 float transform_matrix_a_ = 1.0f, transform_matrix_b_ = 0.0f,
3161 transform_matrix_c_ = 0.0f, transform_matrix_d_ = 1.0f,
3162 transform_matrix_e_ = 0.0f, transform_matrix_f_ = 0.0f;
3163 bool has_transform_matrix_ = false;
3164 float filter_blur_ = 0;
3165 std::vector<FilterOp> filter_chain_{};
3166 // CSS-compat storage-only style slots, lazily allocated. Native View
3167 // trees never set these, so keeping them behind a pointer avoids ~14
3168 // empty std::strings + floats per View instance. Allocated on first
3169 // write via style_extras(); readers fall back to defaults when null.
3170 // Paint-time consumption: clip_path via Canvas::clip_path_svg
3171 // (SkPath::FromSVGString on Skia, no-op fallback elsewhere); mask_image /
3172 // mask via mask-capable backends; the rest round-trip through storage.
3173 struct ViewStyleExtras {
3174 StagedAnimation staged_animation{};
3175 float backdrop_blur = 0.0f;
3177 std::vector<FilterOp> backdrop_filter_chain;
3178 // Import-resolved clip on this view's OWN ink; see
3179 // set_ancestor_clip_rect for why it does not descend.
3180 std::optional<Rect> ancestor_clip;
3181 // Corner radii of that clip, clockwise from top-left; see
3182 // set_ancestor_clip_radii.
3183 std::array<float, 4> ancestor_clip_radii{0.0f, 0.0f, 0.0f, 0.0f};
3184 std::string clip_path;
3185 std::string mask_image;
3186 std::string mask;
3187 std::string mask_size; // CSS mask-size paired with mask_image
3188 std::string appearance; // CSS appearance — storage-only no-op for Pulp custom widgets
3189 std::string object_fit; // CSS object-fit consumed by ImageView paint
3190 std::string object_position; // CSS object-position paired with object-fit
3191 std::string background_attachment; // noop today
3192 std::string background_clip; // partial (text deferred)
3193 std::string background_origin; // gradient tile box; content-box partial
3194 std::string background_position; // repeating gradient tile phase; raster bg deferred
3195 std::string background_size; // storage-only (raster bg deferred)
3196 };
3197 std::unique_ptr<ViewStyleExtras> style_extras_;
3198 ViewStyleExtras& style_extras() {
3199 if (!style_extras_) style_extras_ = std::make_unique<ViewStyleExtras>();
3200 return *style_extras_;
3201 }
3203 std::vector<TransitionSpec> transitions_{};
3204 std::vector<CssAnimation> active_animations_{};
3205
3206 // Storage-only catalog slots.
3207 float text_indent_ = 0.0f; // partial (paint deferred)
3208 std::string word_break_; // partial (HarfBuzz feature deferred)
3209 std::string scroll_behavior_; // ScrollView consumes
3210 std::string overscroll_behavior_; // ScrollView clamp consumes
3211 bool include_font_padding_ = true; // Android legacy round-trip slot (paint ignores)
3212 std::string font_variant_; // partial (HarfBuzz feature deferred)
3213 std::string writing_mode_; // noop (Pulp horizontal-only)
3214 std::string isolation_; // wontfix (no z-buffer)
3215 std::string resize_; // noop (no resize handles)
3216 std::string animation_play_state_; // partial (tick_animations consumes)
3217 bool wants_continuous_repaint_ = false; // opt-in per-vsync repaint
3218 // RN textShadow* per-attribute storage slots. SkPaint shadow integration
3219 // deferred; storage path is round-trippable.
3220 std::string text_shadow_color_;
3221 float text_shadow_dx_ = 0.0f;
3222 float text_shadow_dy_ = 0.0f;
3223 float text_shadow_radius_ = 0.0f;
3224 bool needs_layer_ = false;
3225 // FU-3 subtree scene cache. `subtree_cached_` is the opt-in flag;
3226 // `scene_cache_` holds the recorded scene (shared_ptr so it survives across
3227 // frames until invalidated); `scene_cache_valid_` gates replay vs re-record.
3228 bool subtree_cached_ = false;
3229 bool scene_cache_valid_ = false;
3230 std::shared_ptr<canvas::SceneRecording> scene_cache_;
3231 WindowHost* window_host_ = nullptr;
3232 PluginViewHost* plugin_view_host_ = nullptr;
3233 HostParamSurface* host_params_ = nullptr;
3234 HostActionSurface* host_actions_ = nullptr;
3235
3236 // Running animate() tweens: our returned id is the FrameClock subscription
3237 // id; `tag` supports self-cancelling animations. Unsubscribed in ~View.
3238 // `clock` is cached at subscribe time so ~View can unsubscribe even after
3239 // this view is detached (frame_clock() walks parent_, which a removed child
3240 // has cleared to null — see the detached-child UAF the cache fixes).
3241 struct RunningAnimation { int clock_id = -1; std::string tag; FrameClock* clock = nullptr; };
3242 std::vector<RunningAnimation> animations_;
3243 std::shared_ptr<canvas::ViewEffect> effect_;
3244 // Background-image layers, first on top (CSS paint order).
3245 std::vector<BackgroundGradient> bg_gradients_;
3246 std::string background_repeat_;
3247 float captured_box_paint_left_ = 0.0f;
3248 float captured_box_paint_top_ = 0.0f;
3249 float captured_box_paint_right_ = 0.0f;
3250 float captured_box_paint_bottom_ = 0.0f;
3251 float captured_box_paint_scale_ = 0.0f;
3252 bool text_ellipsis_ = false;
3253 bool white_space_nowrap_ = false;
3254 WhiteSpaceMode white_space_mode_ = WhiteSpaceMode::normal;
3255 CursorStyle cursor_ = CursorStyle::default_;
3256 UserSelect user_select_ = UserSelect::auto_;
3257 WritingDirection direction_ = WritingDirection::auto_;
3258 // CSS / RN mix-blend-mode. Default kSrcOver (canvas
3259 // BlendMode::normal) is a paint-time no-op; any non-default value
3260 // forces a saveLayer() at paint time so the subtree composites back
3261 // through the requested blend mode.
3263
3264 // Pointer capture: pointer_id → this view receives all events for that pointer
3265 std::vector<int> captured_pointers_;
3266 std::vector<std::unique_ptr<GestureRecognizer>> gesture_recognizers_; std::unique_ptr<GestureArbiter> gesture_arbiter_;
3267
3268 // CSS-style typography inheritance. Unset by default; only
3269 // populated when the bridge / app calls a set_inheritable_* setter.
3270 // These do not affect the View's own paint — only descendant Labels
3271 // (and other text widgets) consult them.
3272 std::optional<Color> inh_text_color_;
3273 std::optional<float> inh_font_size_;
3274 std::optional<float> inh_letter_spacing_;
3275 std::optional<int> inh_font_weight_;
3276 std::optional<int> inh_text_align_;
3277 std::optional<std::string> inh_font_family_;
3278};
3279
3280// Expand min/max window-coord extents to cover `v` and every transitive
3281// descendant reachable through an unbroken chain of `overflow:visible` views —
3282// i.e. the true painted bounding box, since an `overflow:hidden` ancestor
3283// clips whatever is below it. `parent_abs_x/y` are the absolute window-coord
3284// origin of `v`'s parent. Shared by View::overlay_contains and
3285// ScrollView::hit_test so both size an overflow:visible child's interactive
3286// area from its actual painted extent rather than a blanket margin.
3288 float parent_abs_x,
3289 float parent_abs_y,
3290 float& min_x,
3291 float& min_y,
3292 float& max_x,
3293 float& max_y);
3294
3295// Expand `right` / `bottom` to cover every visible laid-out descendant box of
3296// `parent`, in `parent`'s coordinate space offset by `parent_x/y`. Sets
3297// `found` when it measured at least one child, so a childless container is
3298// distinguishable from one whose content genuinely ends at the origin.
3299//
3300// The walk STOPS at a nested `is_scroll_container()` child: that child owns
3301// its own private overflow and clips it, so the outer container measures the
3302// nested viewport box rather than content the inner one already scrolls.
3303//
3304// Single implementation shared by `View::scroll_content_size()` and
3305// `ScrollView::update_automatic_content_size()` — two content measurements
3306// that disagreed would clamp the two scrollers to different ranges.
3307void accumulate_scroll_content_extent(const View& parent, float parent_x, float parent_y,
3308 float& right, float& bottom, bool& found);
3309
3310// ── Accessibility exposure gate ──────────────────────────────────────────────
3311//
3312// See is_accessibility_element() in <pulp/view/accessibility.hpp> — the single
3313// predicate every platform bridge calls. It lives there because it has to look
3314// for the value/text interfaces, which are declared there. This file only
3315// classifies the ROLES.
3316
3322 switch (role) {
3330 return true;
3331 default:
3332 return false;
3333 }
3334}
3335
3336} // namespace pulp::view
Definition canvas.hpp:240
BlendMode
Indices 0..15 match the existing W3C "advanced" composite ops and must stay stable — set_blend_mode i...
Definition canvas.hpp:527
@ normal
Definition canvas.hpp:529
A framework-agnostic host command channel.
Definition host_surfaces.hpp:180
A framework-agnostic, native-view-facing runtime parameter accessor.
Definition host_surfaces.hpp:40
Drop-down selector for enumerated parameters.
Definition ui_components.hpp:43
Subscription lifecycle for a view that pulls a value once per frame.
Definition value_source_binding.hpp:45
Definition frame_clock.hpp:14
Definition gesture.hpp:272
Definition gesture.hpp:28
Definition plugin_view_host.hpp:64
A widget whose painted text can join a document-level selection.
Definition selectable_text.hpp:58
Identity-safe reference to a View captured across native event boundaries.
Definition view.hpp:56
void set(View *view) noexcept
bool has_value() const noexcept
Definition view.hpp:60
View * live_in(View &root) const noexcept
void reset() noexcept
Definition view.hpp:73
std::function< bool(const KeyEvent &)> on_navigation_key
Root-scoped callback installed only while a materialized document owns the bounded navigation-focus c...
Definition view.hpp:1750
void request_frame()
Ask the host for a frame without marking any damage: the frame's own work (a queued requestAnimationF...
GestureRecognizer * gesture_recognizer_at(size_t index)
void set_box_shadow_opacity(float a)
Definition view.hpp:1465
void set_scale(float s)
CSS transform properties.
Definition view.hpp:1898
void set_background_color(Color c)
Background color (optional — if set, painted before children).
Definition view.hpp:1123
void set_corner_radius_bl_pct(float pct)
Definition view.hpp:1387
const std::string & access_label() const
The resolved accessible name: author-set if present, else content-derived.
Definition view.hpp:1025
bool move_child_to_index(View *child, size_t index)
Moves an existing child to index in this view's child order — the one order both layout and paint wal...
virtual void on_frame_clock_changed()
The FrameClock reachable from this view (via frame_clock()) may have changed — a clock was installed ...
Definition view.hpp:433
const std::string & access_disabled() const
Definition view.hpp:1049
ListStyleType
CSS / RN list-style cluster.
Definition view.hpp:1258
virtual bool is_gesture_active() const
True while the user is actively manipulating this widget's value with a pointer drag (knob turn,...
Definition view.hpp:463
void clear_box_shadow()
Definition view.hpp:1434
const std::string & overscroll_behavior() const
Definition view.hpp:2346
virtual void paint_all(canvas::Canvas &canvas)
void retire(std::unique_ptr< View > owned) noexcept
Destroys owned at the first moment it is safe to do so.
WindowHost * window_host() const
Definition view.hpp:2454
float corner_radius_tr_pct() const
Definition view.hpp:1390
float text_shadow_radius() const
Definition view.hpp:2393
void clear_inheritable_font_family()
Definition view.hpp:323
int background_gradient_type() const
0=none, 1=linear, 2=radial, 3=conic. Exposed for tests/inspection.
Definition view.hpp:2657
void set_bottom(float v, DimensionUnit unit)
Definition view.hpp:1788
const std::vector< FilterOp > & filter_chain() const
Definition view.hpp:2071
DimensionUnit top_unit() const
Definition view.hpp:1802
void set_mask_image(const std::string &value)
CSS mask-image: ....
Definition view.hpp:2219
bool has_box_shadow() const
Definition view.hpp:1435
float text_indent() const
Definition view.hpp:2332
void clear_inheritable_font_size()
Definition view.hpp:293
std::function< void()> on_hover_leave
Definition view.hpp:1504
virtual void advance_animations(float dt)
Advance any per-widget non-CSS animation state (hover glows, thumb tweens, spinner phase) by dt secon...
Definition view.hpp:427
void set_subpixel_layout(bool v)
Opt this view's layout pass out of Yoga's whole-pixel grid rounding.
Definition view.hpp:104
bool wants_continuous_repaint() const
Definition view.hpp:2374
bool has_time_driven_gestures() const
void set_outline_color(Color c)
CSS / RN outline cluster.
Definition view.hpp:1298
static void set_inspector_cursor_hook(std::function< int(const MouseEvent &, View *event_root)> hook)
Inspector cursor-affordance hook.
std::function< void(Point position)> on_context_menu
Right-click context menu callback.
Definition view.hpp:1496
float corner_radius_bl_pct() const
Definition view.hpp:1391
float border_right_width() const
Definition view.hpp:1351
static std::uint64_t constructed_count() noexcept
Views constructed and destroyed since process start.
Definition view.hpp:890
PointerEvents pointer_events() const
Definition view.hpp:733
void set_hovered(bool h)
View * child_at(size_t index)
Definition view.hpp:161
void set_anchor_id(std::string anchor)
Stable anchor identity from the design-import IR.
Definition view.hpp:1068
Overflow
Overflow mode.
Definition view.hpp:1826
@ scroll
Definition view.hpp:1826
std::vector< CssAnimation > & active_animations()
Active running animations on this View.
Definition view.hpp:2098
const std::string & font_variant() const
Definition view.hpp:2358
float effective_corner_radius_tl(float w, float h) const
Compute effective per-corner radius (px) against given bounds.
Definition view.hpp:1394
void clear_inheritable_letter_spacing()
Definition view.hpp:302
virtual bool set_scroll_offset(float x, float y)
Set / advance the offset, clamped into [0, max_scroll_offset_*]: a container that fits stays at 0 and...
void release_input_focus()
Guarded release — clears the root slot AND the shim mirror only when this currently holds them.
AccessRole access_role() const
Definition view.hpp:996
void set_ancestor_clip_rect(Rect r)
CSS clip-path: path("...").
Definition view.hpp:2187
void set_background_origin(std::string kw)
Definition view.hpp:2297
bool focusable() const
Definition view.hpp:668
void set_text_selection_region(bool region)
Mark this view as a TEXT CONTENT region — prose the reader may select, as opposed to controls they op...
Definition view.hpp:707
Rect self_paint_bounds() const
The rect, in local coordinates, this box's own paint covers: the snapped captured rect when it is rec...
bool overlay_nests_on(const View *below) const
True if this overlay was claimed nested on below; see claim_overlay.
Definition view.hpp:1688
bool has_render_transform() const
True when this view paints under any non-identity render transform (scale / rotation / translate / sk...
Definition view.hpp:1974
virtual void on_key_press(int key_code)
Definition view.hpp:516
void set_pointer_events(PointerEvents p)
Definition view.hpp:732
LayoutMode layout_mode() const
Definition view.hpp:98
Rect map_rect_through_own_transform(const Rect &local) const
Map a rect in this view's local (painted) coordinates through the paint transforms this view applies ...
void clear_background_gradient()
Definition view.hpp:2651
virtual float intrinsic_width() const
Intrinsic content size (override in widgets that know their natural size).
Definition view.hpp:389
friend Point point_to_local(Point root_pos, View *target, View *root)
Convert root_pos (root-local, i.e.
void set_transitions(std::vector< TransitionSpec > ts)
CSS transitions + animations.
Definition view.hpp:2078
bool simulate_context_click(Point root_pos)
Dispatch a synthetic CONTEXT (right-button) press the way the platform hosts do, via route_context_pr...
float effective_corner_radius_bl(float w, float h) const
Definition view.hpp:1396
void set_implicit_access_role(AccessRole role)
Definition view.hpp:997
void mark_layout_current() noexcept
Definition view.hpp:377
static std::uint64_t layout_pass_count() noexcept
Definition view.hpp:883
std::uint64_t overlay_anchor_id() const
Instance id of the anchor (never a recyclable address), or 0 for none.
Definition view.hpp:1708
GridStyle & grid()
Definition view.hpp:94
std::optional< int > inheritable_font_weight() const
static std::uint64_t structure_generation() noexcept
Process-wide compatibility generation retained for existing SDK users.
void set_skew(float x_deg, float y_deg)
Definition view.hpp:1917
float transform_origin_y() const
Definition view.hpp:1933
Size scroll_content_size() const
Union of the laid-out descendant boxes, never smaller than the viewport.
void restore_implicit_access_role()
Definition view.hpp:1001
void set_top(float v, DimensionUnit unit)
Definition view.hpp:1778
std::function< void(const std::string &type, const std::string &data, float x, float y)> on_drop
Drop callback — fired when files or text are dropped on this view.
Definition view.hpp:1500
const BoxShadow & box_shadow() const
The first (topmost) layer, or a default-constructed shadow when the stack is empty — callers that onl...
Definition view.hpp:1439
void set_list_style_image(std::string url)
Definition view.hpp:1286
bool has_source_loc() const
Definition view.hpp:1099
std::function< void(const GestureEvent &)> on_gesture_cb
JS gesture event callback.
Definition view.hpp:1493
void set_overflow(Overflow o)
Definition view.hpp:1827
std::unique_ptr< View > add_child(std::unique_ptr< View > child)
Attaches child and returns nullptr.
bool has_border_right_color_set() const
Definition view.hpp:1370
WritingDirection direction() const
Definition view.hpp:2681
static View * focus_prev(View &root, View *current)
void set_text_overflow_ellipsis(bool e)
Text overflow: ellipsis (CSS text-overflow: ellipsis).
Definition view.hpp:2670
void set_position(Position p)
Definition view.hpp:1762
const std::string & clip_path() const
Definition view.hpp:2209
void set_layout_mode(LayoutMode m)
Definition view.hpp:97
void set_text_indent(float v)
Definition view.hpp:2331
bool dispatch_gesture_pointer_event(const MouseEvent &root_event, double timestamp_seconds=-1.0)
bool scroll_offset_by(float dx, float dy)
Definition view.hpp:1881
void set_raster_cached(bool enabled)
Retain rendered pixels for static leaf content inside its bounds.
int tick_animations(float dt)
Advance every active CSS animation by dt seconds.
Definition view.hpp:2110
void set_access_label(std::string label)
The AUTHOR-SET accessible name (what aria-label maps to).
Definition view.hpp:1010
void request_repaint_self(float halo=4.0f)
Invalidate only THIS view's own rect, overscanned by halo so a glow, focus ring or modulation arc pai...
void set_list_style_type(ListStyleType t)
Definition view.hpp:1284
virtual bool accepts_text_input() const
Does this widget consume printable character keys for text entry?
Definition view.hpp:678
void set_host_actions(HostActionSurface *surface)
The runtime host command channel for this view tree, or nullptr.
std::uint64_t tree_layout_generation() const noexcept
Geometry generation scoped to this View's attached tree.
void clear_source_loc()
Definition view.hpp:1098
static View * focused_input_
Global input-focus shim slot.
Definition view.hpp:1665
virtual void on_gesture_event(const GestureEvent &event)
Gesture event (pinch/rotate from multi-touch or trackpad).
Definition view.hpp:483
void set_corner_radius_tl(float r)
Per-corner border-radius (CSS border-top-left-radius, etc.).
Definition view.hpp:1379
bool has_focus() const
Definition view.hpp:966
HitSlop hit_slop() const
Definition view.hpp:769
std::vector< View * > sorted_children_by_z_index() const
Children stably sorted by z_index() ascending — paint order (higher-z on top); hit_test walks it reve...
static ResolvedRadial resolve_radial(const BackgroundGradient &g, float w, float h)
Resolve a radial layer's CSS sizing against a box of w x h.
virtual void on_meter_frame(const MeterFrame &frame, float dt)
A new MeterFrame was snapshotted this frame, dt seconds after the last.
Definition view.hpp:592
bool has_border_top_set() const
Per-edge "explicitly set" probes.
Definition view.hpp:1360
std::function< void(Point)> on_drag
JS pointermove during drag callback.
Definition view.hpp:1484
const std::string & access_checked() const
Definition view.hpp:1048
bool drop_here(Point root_pos)
std::uint32_t last_paint_with_children_ns() const
Definition view.hpp:415
bool start_file_drag(const FileDragRequest &request)
Drag existing on-disk files out of this view to another app (e.g.
StagedAnimation & staged_animation()
Definition view.hpp:2139
BorderCurve border_curve() const
Definition view.hpp:1226
void set_border_right_width(float w)
Definition view.hpp:1342
virtual void on_text_input(const TextInputEvent &event)
Text input from keyboard/IME (separate from key events).
Definition view.hpp:477
bool captured_frame_root() const
Definition view.hpp:110
std::function< void(const MouseEvent &)> on_pointer_event
JS pointer event callback.
Definition view.hpp:1477
void set_border_left(Color c, float w)
Definition view.hpp:1329
void set_overlay_trigger(bool is_trigger)
Mark this view as a control that OPENS an overlay — a dropdown field, a menu button,...
Definition view.hpp:1701
void set_background_gradient_linear(float x0, float y0, float x1, float y1, const std::vector< Color > &colors, const std::vector< float > &positions)
Background gradient (CSS background: linear-gradient / radial-gradient).
Definition view.hpp:2602
virtual void on_mouse_cancel(Point pos)
Pointer / touch cancellation (iOS touchesCancelled, etc.).
Definition view.hpp:515
bool include_font_padding() const
Definition view.hpp:2355
bool add_child_transactional(std::unique_ptr< View > &child)
Color resolve_color(const std::string &name, Color fallback={}) const
float translate_x() const
Definition view.hpp:1908
void set_background_position(std::string kw)
CSS background-position / background-size.
Definition view.hpp:2315
Color border_top_color() const
Per-side getters.
Definition view.hpp:1348
void set_writing_mode(std::string kw)
Definition view.hpp:2359
static void set_inspector_key_hook(std::function< bool(const KeyEvent &)> hook)
void set_overscroll_behavior(std::string kw)
Definition view.hpp:2345
virtual void on_wheel(float delta_y)
Adjust the widget's value by a scroll-wheel delta (delta_y positive = scrolled down).
Definition view.hpp:457
const std::vector< CssAnimation > & active_animations() const
Definition view.hpp:2099
void set_contains_native_overlay(bool v)
Definition view.hpp:814
virtual bool restore_reload_state(std::string_view)
Definition view.hpp:175
static bool call_inspector_key_hook(const KeyEvent &e)
void set_box_shadow(float ox, float oy, float blur, float spread, Color c, bool inset=false)
Replaces the whole stack with one layer.
Definition view.hpp:1418
void set_rotation(float deg)
Definition view.hpp:1911
const std::string & mask() const
Definition view.hpp:2229
float corner_radius_tl() const
Definition view.hpp:1400
bool has_left() const
Definition view.hpp:1809
float border_top_width() const
Definition view.hpp:1349
void set_hit_slop(float uniform)
Definition view.hpp:764
std::optional< std::string > inheritable_font_family() const
float transform_origin_x() const
Definition view.hpp:1932
bool overlay_contains(Point window_pt) const
Bounds-test in window (root) coordinates.
static void set_inspector_text_hook(std::function< bool(const TextInputEvent &, View *event_root)> hook)
Inspector text-input hook for inline Text-tool editing.
std::function< void()> on_hover_enter
Hover callbacks (CSS :hover equivalent). Fired by set_hovered().
Definition view.hpp:1503
float text_shadow_offset_y() const
Definition view.hpp:2391
static std::uint64_t unmarked_paint_mutation_count() noexcept
Definition view.hpp:867
void set_scroll_behavior(std::string kw)
CSS scroll-behavior + overscroll-behavior.
Definition view.hpp:2343
bool has_captured_box_paint_rect() const
Definition view.hpp:1151
static void set_inspector_paint_hook(std::function< void(canvas::Canvas &, View *painting_root)> hook)
Inspector hooks — set by the inspector module to intercept input and paint without a circular depende...
std::optional< float > inheritable_letter_spacing() const
void set_theme(const Theme &theme)
Definition view.hpp:212
bool has_clip_path() const
Definition view.hpp:2213
void set_border_style(BorderStyle s)
Definition view.hpp:1251
bool text_selection_region() const
Definition view.hpp:710
float opacity() const
Definition view.hpp:1117
void add_box_shadow(float ox, float oy, float blur, float spread, Color c, bool inset=false)
Appends a layer, preserving CSS author order: box-shadow: A, B is set_box_shadow(A) followed by add_b...
Definition view.hpp:1429
virtual SelectableText * as_selectable_text()
This view's painted text can join a cross-widget selection; null for the vast majority of views,...
Definition view.hpp:684
size_t child_count() const
Definition view.hpp:160
static void dismiss_active_overlay()
Dismiss-path release.
void set_user_select(UserSelect s)
Definition view.hpp:2768
const std::string & mask_image() const
Definition view.hpp:2220
virtual void on_focus_changed(bool gained)
Called when this view gains or loses focus.
Definition view.hpp:480
const std::string & background_position() const
Definition view.hpp:2316
void set_direction(WritingDirection d)
Definition view.hpp:2680
Color border_bottom_color() const
Definition view.hpp:1352
bool has_top() const
Definition view.hpp:1806
const std::string & background_repeat() const
Definition view.hpp:1172
void set_border_right(Color c, float w)
Definition view.hpp:1327
float corner_radius_tr() const
Definition view.hpp:1401
const Theme & theme() const
Definition view.hpp:213
bool has_non_default_blend_mode() const
Definition view.hpp:2736
bool has_border_right_set() const
Definition view.hpp:1361
bool overlay_anchored_at(const View *candidate) const
void set_background_repeat(std::string kw)
CSS background-repeat keyword.
Definition view.hpp:1168
void set_corner_radius_tr_pct(float pct)
Definition view.hpp:1386
float backdrop_blur() const
Definition view.hpp:2149
void set_list_style_position(ListStylePosition p)
Definition view.hpp:1288
void set_mask(const std::string &value)
CSS mask shorthand.
Definition view.hpp:2228
void set_border_left_color(Color c)
Definition view.hpp:1337
bool has_background_color() const
Definition view.hpp:1136
void set_border_curve(BorderCurve c)
Definition view.hpp:1225
static View * active_overlay_
Definition view.hpp:1658
void set_border_color(Color c)
Standalone border setters for RN parity.
Definition view.hpp:1188
void set_color(std::string name, Color c)
Override ONE named color token on this view without replacing the rest of its theme.
Definition view.hpp:222
bool has_explicit_access_label() const
True when an author explicitly named this view (set_access_label / aria-label), as opposed to the nam...
Definition view.hpp:1031
virtual void on_detached()
Definition view.hpp:422
void set_transform_matrix(float a, float b, float c, float d, float e, float f)
Full 2D affine transform matrix on the View.
Definition view.hpp:1947
void set_border_bottom_color(Color c)
Definition view.hpp:1336
Position position() const
Definition view.hpp:1767
void set_id(std::string id)
Definition view.hpp:1058
float background_gradient_sweep_turns() const
Turns of the circle the conic stop list spans; < 1 means it repeats.
Definition view.hpp:2648
void set_isolation(std::string kw)
Definition view.hpp:2361
const SelectableText * as_selectable_text() const
Definition view.hpp:687
virtual void paint(canvas::Canvas &)
Definition view.hpp:419
bool has_pointer_capture(int pointer_id) const
const SourceLocation & source_loc() const
Returns the recorded source location, or an empty (!valid()) SourceLocation when none has been set.
Definition view.hpp:1102
void set_left(float v, DimensionUnit unit)
Definition view.hpp:1793
virtual bool wants_mouse_input() const
True if this widget handles mouse down/drag through virtual methods even when it does not expose JS p...
Definition view.hpp:472
void simulate_drag(Point start, Point end, int steps=10)
void set_outline_offset(float px)
Definition view.hpp:1302
Color background_color() const
Definition view.hpp:1137
void set_text_shadow_radius(float r)
Definition view.hpp:2392
static int call_inspector_cursor_hook(const MouseEvent &e, View *event_root=nullptr)
std::size_t overlay_depth() const
Number of overlays currently open under this view's root.
float resolve_dimension(const std::string &name, float fallback) const
Resolve a dimension token: check own theme, walk up to parent.
void set_hit_slop(float top, float right, float bottom, float left)
Definition view.hpp:765
bool has_meter_source() const
void set_backdrop_blur(float radius)
CSS backdrop-filter: blur(px) — frosted-glass blur applied to whatever is behind this View when it pa...
Definition view.hpp:2148
WhiteSpaceMode
White-space: nowrap (CSS white-space: nowrap).
Definition view.hpp:2704
@ pre
Definition view.hpp:2705
@ nowrap
Definition view.hpp:2705
@ normal
Definition view.hpp:2705
void set_inheritable_letter_spacing(float sp)
Definition view.hpp:296
void layout_children_if_needed()
Lay out only when a geometry mutation has happened since this root's last completed pass.
Definition view.hpp:369
void set_captured_frame_root(bool v)
Root of an imported frame: captured text snaps baselines to its grid.
Definition view.hpp:107
std::function< void()> on_click
Generic click callback (fires on mouse-down, if set).
Definition view.hpp:1476
void request_repaint()
Request that this view's host invalidate and schedule a repaint.
float captured_box_paint_bottom() const
Definition view.hpp:1157
float outline_width() const
Definition view.hpp:1317
virtual void on_hover_move(Point local_pos)
Pointer moved over this view with no button held, reported in this view's LOCAL coordinates.
Definition view.hpp:530
void set_visible(bool v)
Show or hide this view.
Definition view.hpp:343
void set_clip_marker_tolerance(bool on)
Import-only accommodation.
Definition view.hpp:1894
void set_transform_origin(float x, float y)
Transform origin (0-1 normalized, default 0.5,0.5 = center).
Definition view.hpp:1927
float scalar_value() const
The latest scalar snapshotted on the clock.
const std::vector< FilterOp > & backdrop_filter_chain() const
Definition view.hpp:2162
WhiteSpaceMode white_space_mode() const
Definition view.hpp:2724
bool is_hovered() const
Definition view.hpp:532
const std::string & appearance() const
Definition view.hpp:2251
void set_border_left_width(float w)
Definition view.hpp:1344
void get_transform_matrix(float &a, float &b, float &c, float &d, float &e, float &f) const
Returns the six affine components in (a,b,c,d,e,f) order; meaningful only when has_transform_matrix()...
Definition view.hpp:2027
int z_index() const
Definition view.hpp:1814
bool contains_native_overlay() const
True when this view (or its subtree) attaches a NATIVE child overlay — a WebView / NSView / HWND that...
Definition view.hpp:813
void set_font_variant(std::string kw)
Definition view.hpp:2357
std::function< bool(const KeyEvent &)> on_global_key
Global key callback.
Definition view.hpp:1747
void set_border_radius(float r)
Definition view.hpp:1202
void simulate_hover(Point root_pos)
BorderStyle outline_style() const
Definition view.hpp:1316
bool subpixel_layout() const
Definition view.hpp:105
virtual void set_window_host(WindowHost *host)
Back-reference to the WindowHost that owns this view tree.
static void set_inspector_mouse_hook(std::function< bool(const MouseEvent &, View *event_root)> hook)
Inspector mouse hook.
void clear_layout_dirty()
Definition view.hpp:903
static std::vector< OverlayRequest > & overlay_queue()
void set_frame_clock(FrameClock *clock)
Set the frame clock on the root view.
static std::uint64_t damage_request_count() noexcept
Number of layout_children() calls since process start.
Definition view.hpp:864
friend class WidgetBridge
Definition view.hpp:2790
std::optional< int > inheritable_text_align() const
RootInteractionState * existing_interaction()
Resolved interaction state WITHOUT lazily allocating — the root's slot if one exists,...
void simulate_click(Point root_pos, const SimulatedPointer &pointer)
As above, driven by an explicit pointer device.
void set_subtree_cached(bool v)
Cache this subtree's painted CONTENT (its outset shadows, clip, background/border,...
bool has_scalar_source() const
void set_background_size(std::string kw)
Definition view.hpp:2320
const std::array< float, 4 > & ancestor_clip_radii() const
Definition view.hpp:2203
void set_white_space_mode(WhiteSpaceMode m)
Definition view.hpp:2718
const View * child_at(size_t index) const
Definition view.hpp:162
bool clip_marker_tolerance() const
Definition view.hpp:1895
UserSelect user_select() const
Definition view.hpp:2769
std::uint32_t last_paint_self_ns() const
Definition view.hpp:414
void set_scalar_source(std::shared_ptr< ScalarSource > source)
Bind a ScalarSource — one cached number (a readout, a modulation ring's modulated position).
void set_background_gradient_radial(float cx, float cy, float radius_frac, const std::vector< Color > &colors, const std::vector< float > &positions)
Radial gradient.
Definition view.hpp:2614
const std::string & id() const
Definition view.hpp:1059
float corner_radius_br_pct() const
Definition view.hpp:1392
void set_requires_gpu_host(bool v)
Definition view.hpp:803
UserSelect
CSS user-select.
Definition view.hpp:2767
WidgetMetrics * effective_metrics() const
The metrics delegate that governs THIS view: its own if it has one, else the nearest ancestor's,...
const std::optional< Rect > & ancestor_clip_rect() const
Definition view.hpp:2188
virtual bool wants_wheel_scroll() const
True if this widget is itself a scroll container that should consume wheel input before an ancestor s...
void set_top(float v)
Definition view.hpp:1774
void set_host_params(HostParamSurface *surface)
The runtime host-parameter accessor for this view tree, or nullptr in previews/screenshots (a view de...
float max_scroll_offset_x() const
Scrollable range, content - viewport clamped at 0.
void set_bottom(float v)
Definition view.hpp:1776
void set_box_shadow_offset(float ox, float oy)
Definition view.hpp:1461
void request_repaint(const Rect &local_dirty)
Bounded repaint: invalidate only local_dirty (this view's local coordinates), mapped to root space,...
const GridStyle & grid() const
Definition view.hpp:95
void set_cursor(CursorStyle c)
Definition view.hpp:2760
bool default_hover_feedback() const
Definition view.hpp:543
std::function< void(const MouseEvent &, bool is_dom_origin)> on_dom_wheel_event
Bridge wheel delivery.
Definition view.hpp:1483
virtual bool save_reload_state(std::string &) const
Definition view.hpp:174
std::optional< float > inheritable_font_size() const
AccessRole
Screen-reader role.
Definition view.hpp:988
@ list
Definition view.hpp:991
@ menu
Definition view.hpp:992
@ dialog
Definition view.hpp:992
@ tab_list
Definition view.hpp:991
@ table
Definition view.hpp:991
@ group
Definition view.hpp:989
@ row
Definition view.hpp:991
HostActionSurface * host_actions() const
Definition view.hpp:2487
bool hit_testable() const
CSS pointer-events: none — view is invisible to hit testing.
Definition view.hpp:719
std::unique_ptr< View > remove_child(View *child)
Detaches child and returns its ownership, or nullptr when child is no longer this parent's child unde...
void set_filter_chain(std::vector< FilterOp > chain)
Definition view.hpp:2069
float max_scroll_offset_y() const
void set_right(float v, DimensionUnit unit)
Definition view.hpp:1783
const TransitionSpec * find_transition_for(const std::string &property) const
Find the matching transition for a given property name.
Definition view.hpp:2087
void drag_to(Point root_pos)
size_t gesture_recognizer_count() const
Definition view.hpp:487
void set_text_shadow_color(std::string c)
RN textShadow per-attribute storage.
Definition view.hpp:2387
void set_metrics(std::shared_ptr< WidgetMetrics > m)
void set_effect(std::shared_ptr< canvas::ViewEffect > effect)
Attach a GPU post-processing effect to this View's compositing layer.
Definition view.hpp:2445
bool has_corner_radii() const
Per-corner radius accessors. corner_radii_[0..3] = TL, TR, BL, BR.
Definition view.hpp:1399
PluginViewHost * plugin_view_host() const
Definition view.hpp:2461
float corner_radius() const
Definition view.hpp:1183
void advance_gesture_recognizers(double timestamp_seconds=-1.0)
bool has_transitions() const
Definition view.hpp:2081
Color border_color() const
Definition view.hpp:1181
float rotation() const
Definition view.hpp:1915
virtual Point child_paint_offset(const View &child) const
The translation this container applies to ONE child's paint, in the container's own coordinate space.
Definition view.hpp:2015
virtual void layout_children()
Color border_right_color() const
Definition view.hpp:1350
void set_word_break(std::string kw)
Definition view.hpp:2333
std::optional< Color > inheritable_text_color() const
Walks own value, then parent chain. nullopt if no ancestor set it.
virtual void set_plugin_view_host(PluginViewHost *host)
Back-reference to the PluginViewHost that owns this editor tree.
void set_backdrop_filter_chain(std::vector< FilterOp > chain)
CSS backdrop-filter with its full function list — saturate(), brightness(), invert(),...
Definition view.hpp:2159
void clear_gesture_recognizers()
float captured_box_paint_left() const
Definition view.hpp:1154
void set_painter(std::shared_ptr< WidgetPainter > p)
PointerEvents
React Native pointerEvents.
Definition view.hpp:731
float captured_box_paint_right() const
Definition view.hpp:1156
void set_include_font_padding(bool v)
RN's Android-only includeFontPadding.
Definition view.hpp:2354
void set_filter_blur(float radius)
CSS filter: blur(px) — per-element blur.
Definition view.hpp:2036
const std::string & anchor_id() const
Definition view.hpp:1069
void set_access_value(std::string value)
Definition view.hpp:1036
const std::string & list_style_image() const
Definition view.hpp:1287
float translate_y() const
Definition view.hpp:1909
bool subtree_cached() const
Definition view.hpp:2433
virtual void on_mouse_drag(Point pos)
Definition view.hpp:510
void set_inheritable_text_color(Color c)
Definition view.hpp:275
void clear_inheritable_text_align()
Definition view.hpp:328
Color border_left_color() const
Definition view.hpp:1354
void set_background_gradient_layers(std::vector< BackgroundGradient > layers)
Replace the background-image stack, first layer on top.
Definition view.hpp:2593
View(const View &)=delete
const std::string & object_fit() const
Definition view.hpp:2262
void set_corner_radius_br_pct(float pct)
Definition view.hpp:1388
bool has_border_bottom_color_set() const
Definition view.hpp:1371
const std::string & access_pressed() const
Definition view.hpp:1047
const std::string & mask_size() const
Definition view.hpp:2238
ListStylePosition list_style_position() const
Definition view.hpp:1289
std::function< void()> on_overlay_dismissed
Fired when the active overlay is dismissed via a framework auto-dismissal path (ESC / outside-click).
Definition view.hpp:1736
bool has_filter_chain() const
Definition view.hpp:2072
void set_border_top(Color c, float w)
Per-side borders (CSS border-top, border-right, etc.).
Definition view.hpp:1326
std::weak_ptr< const std::uint64_t > import_binding_lifetime_token() const
Definition view.hpp:1075
bool visible() const
Definition view.hpp:333
void set_default_hover_feedback(bool enabled)
Baseline pointer feedback for semantic controls that keep an authored painter (for example imported l...
Definition view.hpp:540
HostParamSurface * host_params() const
Definition view.hpp:2482
float text_shadow_offset_x() const
Definition view.hpp:2390
static void note_unmarked_paint_mutation() noexcept
Record a paint change that requested no repaint of its own.
Definition view.hpp:871
void set_derived_access_label(std::string label)
The CONTENT-DERIVED accessible name: a widget's visible text (Label::set_text, Knob/Fader/Toggleset_l...
Definition view.hpp:1020
virtual void on_mouse_event(const MouseEvent &event)
Mouse down with full event context.
Definition view.hpp:438
virtual bool is_scroll_container() const
True when this view scrolls its own content; ScrollView always does.
Definition view.hpp:1851
void set_background_gradient_conic(float cx, float cy, float start_angle, const std::vector< Color > &colors, const std::vector< float > &positions, float sweep_turns=1.0f)
Conic (CSS conic-gradient / Figma angular).
Definition view.hpp:2631
virtual bool owns_child_layout() const
Definition view.hpp:385
void set_appearance(const std::string &value)
CSS appearance — controls native form-widget rendering.
Definition view.hpp:2250
DimensionUnit left_unit() const
Definition view.hpp:1805
virtual void on_mouse_enter()
Definition view.hpp:520
std::uint64_t import_binding_instance_id() const
Stable for this View object's lifetime.
Definition view.hpp:1074
bool has_bottom() const
Definition view.hpp:1808
bool has_right() const
Definition view.hpp:1807
float bottom() const
Definition view.hpp:1800
const StagedAnimation & staged_animation() const
Definition view.hpp:2140
void set_object_fit(const std::string &value)
CSS object-fit — controls how an <img> content's intrinsic size is fitted into its layout box.
Definition view.hpp:2261
void clear_filter_chain()
Definition view.hpp:2070
static void bump_layout_generation() noexcept
Definition view.hpp:850
void set_captured_box_paint_rect(float left, float top, float right, float bottom, float device_scale)
Browser-compatible device-space paint rectangle for this box's own paint (Chromium's CSS-edge snap,...
Definition view.hpp:1143
canvas::Canvas::BlendMode mix_blend_mode() const
Definition view.hpp:2735
friend class ViewCapture
Definition view.hpp:2791
bool overlay_consumes_outside_click() const
Definition view.hpp:1684
void mark_runtime_view_kind(RuntimeViewKind kind)
Definition view.hpp:2379
bool start_drag(DropData data)
void set_inheritable_font_weight(int w)
Definition view.hpp:305
void set_border_width(float w)
Definition view.hpp:1195
virtual void on_attached()
Definition view.hpp:421
void set_meter_source(std::shared_ptr< MeterSource > source, int channel=0)
Bind a MeterSource.
void set_corner_radius_br(float r)
Definition view.hpp:1382
virtual void on_mouse_leave()
Definition view.hpp:521
Color outline_color() const
Definition view.hpp:1314
const std::string & word_break() const
Definition view.hpp:2334
void set_inheritable_text_align(int a)
0 = left, 1 = center, 2 = right (matches LabelAlign).
Definition view.hpp:327
const std::string & background_origin() const
Definition view.hpp:2298
void set_clip_path(const std::string &svg_path_d)
Definition view.hpp:2208
virtual std::vector< uint8_t > capture_native_overlay_png(uint32_t, uint32_t)
When this view owns a native overlay (a WebView pane), it overrides this to return an in-process PNG ...
Definition view.hpp:821
void dismiss_claimed_overlay()
Dismiss this exact overlay when it owns its root's overlay slot.
float effective_corner_radius_tr(float w, float h) const
Definition view.hpp:1395
const std::shared_ptr< WidgetPainter > & painter() const
Definition view.hpp:235
void set_border_bottom(Color c, float w)
Definition view.hpp:1328
bool handle_scroll_wheel(const MouseEvent &event)
Applies a wheel tick to this view's scroll offset; true when a scroll container with range consumed i...
BorderStyle
CSS / RN border-style.
Definition view.hpp:1239
void simulate_click(Point root_pos)
void clear_inheritable_text_color()
Definition view.hpp:279
bool needs_layer() const
Definition view.hpp:2399
CursorStyle
Cursor style hint (CSS cursor property).
Definition view.hpp:2741
void set_resize(std::string kw)
Definition view.hpp:2363
RuntimeViewKind runtime_view_kind() const noexcept
Definition view.hpp:2376
float corner_radius_tl_pct() const
Definition view.hpp:1389
void set_border_radius_pct(float pct)
Set corner radius as percent of min(width,height).
Definition view.hpp:1211
CursorStyle cursor() const
Definition view.hpp:2761
bool requires_gpu_host() const
GPU-host capability signal.
Definition view.hpp:802
int meter_source_channel() const
bool drag_active() const
void clear_inheritable_font_weight()
Definition view.hpp:311
bool text_overflow_ellipsis() const
Definition view.hpp:2671
float effective_corner_radius_br(float w, float h) const
Definition view.hpp:1397
virtual void on_mouse_up(Point pos)
Definition view.hpp:509
void set_left(float v)
Definition view.hpp:1777
std::function< void(const MouseEvent &, bool)> on_dom_pointer_move_event
Definition view.hpp:1479
void set_outline_width(float px)
Definition view.hpp:1310
void claim_input_focus()
Claim focus / overlay for this view's tree.
void set_text_shadow_offset(float dx, float dy)
Definition view.hpp:2389
void set_access_pressed(std::string s)
Definition view.hpp:1043
const std::string & text_shadow_color() const
Definition view.hpp:2388
static View * focus_next(View &root, View *current)
bool has_border_left_color_set() const
Definition view.hpp:1372
void set_enabled(bool e)
Definition view.hpp:716
static std::uint64_t destroyed_count() noexcept
Definition view.hpp:893
const std::string & access_hidden() const
Definition view.hpp:1050
void set_access_disabled(std::string s)
Definition view.hpp:1045
bool layout_is_current() const noexcept
Definition view.hpp:374
const std::vector< BoxShadow > & box_shadows() const
Every layer, in CSS author order (first paints on top).
Definition view.hpp:1444
void set_translate(float x, float y)
Definition view.hpp:1904
void set_bounds(Rect r)
float border_bottom_width() const
Definition view.hpp:1353
void set_animation_play_state(std::string kw)
Animation play-state.
Definition view.hpp:2368
WritingDirection
Writing direction (CSS direction / RN writingDirection).
Definition view.hpp:2679
@ ltr
Definition view.hpp:2679
@ auto_
Definition view.hpp:2679
void set_hit_testable(bool h)
Definition view.hpp:720
const std::string & background_attachment() const
Definition view.hpp:2288
void invalidate_layout()
Mark layout as needing recalculation (auto-invalidation).
Definition view.hpp:898
virtual float intrinsic_height() const
void set_ancestor_clip_radii(float tl, float tr, float br, float bl)
Corner radii for the ancestor clip, clockwise from top-left.
Definition view.hpp:2200
float corner_radius_br() const
Definition view.hpp:1403
std::uint64_t root_structure_generation() const noexcept
Generation of the top-level tree containing this view.
void set_border_bottom_width(float w)
Definition view.hpp:1343
void set_continuous_repaint(bool on)
Opt a custom view into per-vsync repaints — required for live content (meters/spectrum,...
Definition view.hpp:2373
const std::string & access_value() const
Definition view.hpp:1037
int animate(std::function< void(float)> apply, float from, float to, float duration_s, std::function< float(float)> ease={}, std::function< void()> on_done={}, const std::string &tag={})
bool has_border_sides() const
Definition view.hpp:1356
void clear_transitions()
Definition view.hpp:2079
bool has_background_gradient() const
Definition view.hpp:2655
void set_inheritable_font_family(std::string f)
Inheritable font-family cascade.
Definition view.hpp:317
void set_hit_slop(HitSlop s)
Definition view.hpp:768
const std::string & writing_mode() const
Definition view.hpp:2360
FlexStyle & flex()
Definition view.hpp:91
void cancel_animation(int id)
Cancel a running animation by id (no-op if already finished/unknown).
WritingDirection resolved_direction() const
Resolve auto_ → ltr (LTR fallback, until first-strong-character detection is wired).
Definition view.hpp:2685
void set_border(Color c, float width, float radius=0)
Border (optional — painted on top of background).
Definition view.hpp:1175
void set_right(float v)
Definition view.hpp:1775
const FlexStyle & flex() const
Definition view.hpp:92
void set_border_top_color(Color c)
Color-only setters.
Definition view.hpp:1334
static std::uint64_t layout_generation() noexcept
Definition view.hpp:847
float corner_radius_pct() const
Definition view.hpp:1217
float top() const
Definition view.hpp:1798
virtual void on_resized()
Definition view.hpp:420
void set_access_role(AccessRole role)
Definition view.hpp:995
ListStyleType list_style_type() const
Definition view.hpp:1285
void set_object_position(const std::string &value)
CSS object-position — alignment of the object inside its content box when object-fit leaves blank spa...
Definition view.hpp:2271
void release_pointer_capture(int pointer_id)
float border_width() const
Definition view.hpp:1182
void set_mask_size(const std::string &value)
CSS mask-size (pairs with mask-image).
Definition view.hpp:2237
const std::string & scroll_behavior() const
Definition view.hpp:2344
const std::shared_ptr< WidgetMetrics > & metrics() const
Definition view.hpp:251
void set_box_shadow_color(Color c)
RN iOS-legacy shadow* longhand setters.
Definition view.hpp:1457
void set_box_shadow_radius(float r)
Definition view.hpp:1471
void set_needs_layer(bool v)
Force this View's subtree to render into a compositing layer.
Definition view.hpp:2398
float captured_box_paint_top() const
Definition view.hpp:1155
static void paint_overlays(canvas::Canvas &canvas, View *painting_root=nullptr)
Paint queued overlays + the inspector paint hook.
void set_access_checked(std::string s)
Definition view.hpp:1044
bool has_transform_matrix() const
Definition view.hpp:1968
float background_gradient_radius() const
The legacy single-radius slot, as a fraction of max(w,h).
Definition view.hpp:2665
bool has_border_left_set() const
Definition view.hpp:1363
DimensionUnit right_unit() const
Definition view.hpp:1803
virtual void on_meter_snapshot_changed()
meter_frame() changed: repaint this view (a live binding alone does not composite).
Definition view.hpp:598
bool enabled() const
CSS :disabled equivalent — blocks input, reduces opacity.
Definition view.hpp:715
void set_pointer_capture(int pointer_id)
Capture pointer events for this view — all events for pointer_id route here regardless of hit-test un...
View & operator=(const View &)=delete
float right() const
Definition view.hpp:1799
RootInteractionState & interaction()
Root-owned interaction state for this view's tree.
const std::string & derived_access_label() const
The content-derived name on its own, ignoring any author-set name.
Definition view.hpp:1034
const std::string & object_position() const
Definition view.hpp:2272
virtual void prepare_for_reuse()
void clear_background_color()
Definition view.hpp:1130
bool children_in_z_order() const
True iff children_ is already in that order — paint_all's fast path then iterates children_ directly,...
void set_corner_radius_bl(float r)
Definition view.hpp:1381
std::function< void(const MouseEvent &)> on_pointer_move
JS pointermove carrying full pointer identity (id + type + pressure).
Definition view.hpp:1492
void set_opacity(float o)
Opacity (0.0 = transparent, 1.0 = opaque). Applied as layer alpha.
Definition view.hpp:1113
friend class ScrollView
Definition view.hpp:2792
const std::string & resize() const
Definition view.hpp:2364
bool backface_visible() const
React Native backfaceVisibility.
Definition view.hpp:783
void set_focusable(bool f)
Definition view.hpp:669
const MeterFrame & meter_frame() const
The latest MeterFrame snapshotted on the clock.
friend class DispatchLease
Definition view.hpp:2793
virtual bool wants_wheel_value() const
True if this widget adjusts its VALUE on a scroll-wheel over it (knobs, faders, sliders,...
Definition view.hpp:454
void set_corner_radius_tr(float r)
Definition view.hpp:1380
virtual void on_accessibility_adjust(float delta)
Called by platform accessibility when VoiceOver increment/decrement is triggered.
Definition view.hpp:1054
const std::vector< BackgroundGradient > & background_gradient_layers() const
Definition view.hpp:2597
float corner_radius_bl() const
Definition view.hpp:1402
void set_mix_blend_mode(canvas::Canvas::BlendMode m)
CSS / RN mix-blend-mode.
Definition view.hpp:2734
void set_backface_visible(bool v)
Definition view.hpp:784
virtual View * hit_test(Point local_point)
void set_background_clip(std::string kw)
Definition view.hpp:2292
View * parent() const
Definition view.hpp:163
void set_overlay_anchor(const View *anchor)
Declare the control that OPENED this overlay.
Overflow overflow() const
Definition view.hpp:1837
float effective_corner_radius(float width, float height) const
Compute the effective uniform corner radius in px against the given bounds (called by paint code).
Definition view.hpp:1229
void release_overlay()
Clear the overlay if (and only if) this currently holds it.
bool overlay_trigger() const
Definition view.hpp:1702
void set_background_attachment(std::string kw)
CSS background sub-properties.
Definition view.hpp:2287
WidgetPainter * effective_painter() const
The painter that governs THIS view: its own if it has one, else the nearest ancestor's,...
float outline_offset() const
Definition view.hpp:1315
virtual bool applies_child_paint_offset() const
True when this container translates its CHILDREN's paint in a way a plain bounds-offset walk cannot m...
Definition view.hpp:1996
bool gesture_claimed_pointer() const
True when a gesture recognizer ACTIVELY claimed the last pointer event.
virtual bool on_key_event(const KeyEvent &event)
Key event with modifiers and up/down state.
Definition view.hpp:475
float left() const
Definition view.hpp:1801
std::function< void(const std::string &id, uint16_t modifiers)> on_global_click
Global click callback (fires on any view click with widget id). Set on root.
Definition view.hpp:1743
virtual bool supports_reuse() const
Definition view.hpp:187
bool transform_origin_explicit() const
Definition view.hpp:1934
void simulate_drag(Point start, Point end, int steps, const SimulatedPointer &pointer)
As above, driven by an explicit pointer device.
void set_border_top_width(float w)
Width-only setters.
Definition view.hpp:1341
const RootInteractionState & interaction() const
BorderStyle border_style() const
Definition view.hpp:1252
static bool call_inspector_text_hook(const TextInputEvent &e, View *event_root=nullptr)
void clear_transform_matrix()
Definition view.hpp:1963
void set_overlay_consumes_outside_click(bool consume)
Definition view.hpp:1681
virtual void on_mouse_down(Point pos)
Definition view.hpp:508
void set_white_space_nowrap(bool n)
Definition view.hpp:2712
bool layout_dirty() const
Definition view.hpp:902
const std::string & background_size() const
Definition view.hpp:2321
friend class FrameClockBinding
Definition view.hpp:2864
void set_access_hidden(std::string s)
Definition view.hpp:1046
Position
CSS position property.
Definition view.hpp:1753
@ sticky
Definition view.hpp:1753
bool has_border_top_color_set() const
Per-edge colour "explicitly set" probes.
Definition view.hpp:1369
const std::shared_ptr< canvas::ViewEffect > & effect() const
Definition view.hpp:2446
std::function< void(const MouseEvent &, bool)> on_dom_pointer_event
One DOM origin.
Definition view.hpp:1478
bool has_filter_effect() const
True when this view paints under a pixel-spreading filter (blur or a filter-chain op) — it re-samples...
Definition view.hpp:1984
ListStylePosition
Definition view.hpp:1280
void set_corner_radius_tl_pct(float pct)
Per-corner percent setters.
Definition view.hpp:1385
bool white_space_nowrap() const
Definition view.hpp:2716
bool has_border_bottom_set() const
Definition view.hpp:1362
FrameClock * frame_clock() const
Get the frame clock (walks up parent chain to find it).
const std::vector< TransitionSpec > & transitions() const
Definition view.hpp:2080
void set_inheritable_font_size(float size)
Definition view.hpp:287
float filter_blur() const
Definition view.hpp:2037
static bool call_inspector_mouse_hook(const MouseEvent &e, View *event_root=nullptr)
void claim_overlay(const View *stacks_on=nullptr)
Open this view as an overlay under its root.
virtual bool accepts_navigation_input() const
Does this widget temporarily need host-delivered navigation keys?
Definition view.hpp:2471
const std::string & animation_play_state() const
Definition view.hpp:2369
void set_focus(bool f)
Definition view.hpp:967
void set_source_loc(SourceLocation loc)
Definition view.hpp:1097
GestureRecognizer & add_gesture_recognizer(std::unique_ptr< GestureRecognizer > recognizer)
Rect bounds() const
Definition view.hpp:84
Rect hit_bounds() const
local_bounds() grown by hit_slop().
Definition view.hpp:773
float scale() const
Definition view.hpp:1902
void set_border_right_color(Color c)
Definition view.hpp:1335
float border_left_width() const
Definition view.hpp:1355
const std::string & background_clip() const
Definition view.hpp:2293
virtual float scroll_offset_y() const
Definition view.hpp:1861
Rect local_bounds() const
Definition view.hpp:88
void set_z_index(int z)
Definition view.hpp:1810
void clear_border()
Definition view.hpp:1179
void set_outline_style(BorderStyle s)
Definition view.hpp:1306
DimensionUnit bottom_unit() const
Definition view.hpp:1804
int active_animation_count() const
Number of animations currently running on this view. For tests.
Definition view.hpp:621
virtual float scroll_offset_x() const
Scroll offset in px, always within [0, max_scroll_offset_*].
Definition view.hpp:1858
bool has_border() const
Definition view.hpp:1180
const std::string & isolation() const
Definition view.hpp:2362
static void dismiss_active_overlay(View &scope)
Hosted variant acts only on scope's interaction slot.
BorderCurve
RN's borderCurve: corner shape selection.
Definition view.hpp:1224
Definition widget_bridge.hpp:59
Install on a View to supply the SIZES of the controls in its subtree.
Definition widget_metrics.hpp:91
Install on a View to supply the pixels for the controls in its subtree.
Definition widget_painter.hpp:158
Definition window_host.hpp:113
Forward declarations for the editor data plane, plus their pulp::view spellings.
Input event types with modifier keys and pointer IDs.
@ Overflow
Definition sample_preload_contract.hpp:15
Definition affine_transform.hpp:24
@ backdrop_filter_chain
save_backdrop_filter_chain honors the colour ops too.
Definition canvas_capability.hpp:30
Bounded event contracts shared by host ingress and graph-authored nodes.
Definition anticipation_eligibility.hpp:9
Definition host_transport_projector.hpp:8
@ width
Definition config.hpp:225
SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the ...
Definition audio_device_manager.hpp:48
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
@ dialog
Modal or modeless dialog.
Definition window_manager.hpp:22
@ normal
Definition design_ir.hpp:450
@ text
Plain text (default color).
Definition code_editor_tokenizer.hpp:37
@ link
Markdown / hyperlink span.
Definition code_editor_tokenizer.hpp:50
@ type
Built-in / common type name (e.g. int, Number).
Definition code_editor_tokenizer.hpp:39
@ heading
Markdown heading (#, ##, …).
Definition code_editor_tokenizer.hpp:49
constexpr bool is_structural_access_role(View::AccessRole role)
Structural roles: a container announces the children underneath it, so it is meaningful without a nam...
Definition view.hpp:3321
@ bottom
Definition border_style.hpp:31
@ right
Definition border_style.hpp:31
@ none
Definition appearance_defects.hpp:53
@ invisible
the node or an ancestor is not visible
Definition appearance_defects.hpp:54
LayoutMode
Definition geometry.hpp:348
@ flex
Definition geometry.hpp:348
DimensionUnit
Definition geometry.hpp:392
@ px
Absolute pixels.
Definition geometry.hpp:393
canvas::Color Color
Definition theme.hpp:12
@ fader
Definition design_ir.hpp:261
@ toggle
Definition design_ir.hpp:272
@ knob
Definition design_ir.hpp:260
MouseButton
Mouse button identifiers.
Definition input_events.hpp:67
@ left
Definition input_events.hpp:69
PointerType
Pointer device type (W3C PointerEvent.pointerType).
Definition input_events.hpp:75
@ mouse
Mouse cursor (default).
Definition input_events.hpp:76
void accumulate_overflow_extent(const View *v, float parent_abs_x, float parent_abs_y, float &min_x, float &min_y, float &max_x, float &max_y)
@ image
Definition design_fidelity.hpp:37
@ value
the widget's primary value (Knob, Fader, RangeSlider, Toggle, ProgressBar)
Definition binding_diagnostics.hpp:19
@ scope
a block of samples for a SpectrumView / WaveformView
Definition binding_diagnostics.hpp:21
@ meter
a Meter's level
Definition binding_diagnostics.hpp:20
@ uniform
a custom shader uniform
Definition binding_diagnostics.hpp:22
@ scroll
Content clipped, scrollbar shown when needed.
Definition geometry.hpp:386
@ visible
Content renders beyond bounds (default for views).
Definition geometry.hpp:384
@ hidden
Content clipped to bounds.
Definition geometry.hpp:385
@ s
Definition input_events.hpp:41
@ a
Definition input_events.hpp:39
@ h
Definition input_events.hpp:39
@ y
Definition input_events.hpp:42
@ c
Definition input_events.hpp:39
@ r
Definition input_events.hpp:41
@ m
Definition input_events.hpp:40
@ n
Definition input_events.hpp:40
@ d
Definition input_events.hpp:39
@ p
Definition input_events.hpp:40
@ f
Definition input_events.hpp:39
@ b
Definition input_events.hpp:39
@ x
Definition input_events.hpp:41
@ v
Definition input_events.hpp:41
@ g
Definition input_events.hpp:39
@ o
Definition input_events.hpp:40
@ e
Definition input_events.hpp:39
@ t
Definition input_events.hpp:41
@ tab
Definition input_events.hpp:57
@ w
Definition input_events.hpp:41
@ z
Definition input_events.hpp:42
@ row
Definition design_ir.hpp:53
@ colors
colors: map — hex string values.
Definition token_lock.hpp:63
@ candidate
Definition waveform_editor_primitives.hpp:193
@ end
Definition geometry.hpp:370
@ auto_
Definition geometry.hpp:370
@ start
Definition geometry.hpp:370
RuntimeViewKind
Internal concrete-type hint for the two whole-tree hot paths.
Definition view.hpp:46
@ design_frame
Definition view.hpp:47
@ generic
Definition view.hpp:47
@ eq_curve
Definition view.hpp:47
@ color
Definition css_animation.hpp:121
@ height
Definition css_animation.hpp:128
@ width
Definition css_animation.hpp:127
void accumulate_scroll_content_extent(const View &parent, float parent_x, float parent_y, float &right, float &bottom, bool &found)
@ context_menu
Right button.
Definition press_reach.hpp:64
@ changed
Definition gesture.hpp:17
@ below
Definition callout_box.hpp:34
@ fixed
Definition design_ir.hpp:61
@ text_field
Definition design_ir.hpp:477
@ on
Definition accessibility.hpp:132
STL namespace.
Definition gradient_interpolation.hpp:43
A single multi-channel meter reading.
Definition value_source.hpp:39
Definition drag_drop.hpp:234
CSS easing function — maps a normalized progress t ∈ [0,1] to an eased progress p ∈ [0,...
Definition css_animation.hpp:29
Definition drag_drop.hpp:14
Definition drag_drop.hpp:109
Definition geometry.hpp:445
High-level gesture event for pinch (scale) and rotate.
Definition input_events.hpp:181
Grid layout properties (CSS Grid Level 1 subset).
Definition geometry.hpp:642
Rich key event with key code, modifiers, and repeat state.
Definition input_events.hpp:193
Rich mouse/pointer event with position, modifiers, button state, pointer ID, and stylus properties.
Definition input_events.hpp:104
bool is_wheel
True for scroll wheel events.
Definition input_events.hpp:114
Definition geometry.hpp:20
Axis-aligned rectangle in continuous (float) coordinates.
Definition geometry.hpp:52
Definition geometry.hpp:28
Text input from IME or keyboard composition (separate from KeyEvent).
Definition input_events.hpp:210
Definition theme.hpp:32
One transition spec — one CSS property with its own duration / delay / easing.
Definition css_animation.hpp:147
One background-image layer.
Definition view.hpp:2495
LinearFrom
Where a linear gradient's endpoints come from.
Definition view.hpp:2523
float radius
Definition view.hpp:2502
float y0
Definition view.hpp:2501
float y1
Definition view.hpp:2501
RepeatUnit
What linear_repeat is measured in.
Definition view.hpp:2543
bool positions_in_px
True when positions still hold raw px LENGTHS rather than 0..1 parameters, because every stop named o...
Definition view.hpp:2559
float x1
Definition view.hpp:2501
float corner_y
Definition view.hpp:2530
float linear_repeat
The band a repeating-linear-gradient tiles; 0 when the gradient does not repeat.
Definition view.hpp:2537
bool radial_circle
A circle has one radius resolved against the box's diagonal-ish metric; an ellipse gets a separate ra...
Definition view.hpp:2573
RadialSize
How a radial gradient's radii are sized, per css-images-3.
Definition view.hpp:2565
float radial_ry_px
Definition view.hpp:2579
float radial_rx
RadialSize::explicit_radii: radii as fractions of width and height, plus an absolute term.
Definition view.hpp:2578
float angle
Definition view.hpp:2503
int type
Definition view.hpp:2496
float radial_ry
Definition view.hpp:2578
float linear_angle
CSS angle in radians, clockwise from "to top".
Definition view.hpp:2527
LinearFrom linear_from
Definition view.hpp:2524
std::size_t css_image_layer_index
Definition view.hpp:2500
canvas::GradientInterpolation interpolation
CSS in <space> [<hue> hue].
Definition view.hpp:2580
std::vector< float > positions
Definition view.hpp:2506
float radial_rx_px
Definition view.hpp:2579
float corner_x
Signs of the named corner for LinearFrom::corner: x is +1 for right, -1 for left; y is +1 for bottom,...
Definition view.hpp:2530
std::vector< Color > colors
Definition view.hpp:2505
RadialSize radial_size
Definition view.hpp:2569
float x0
Definition view.hpp:2501
RepeatUnit linear_repeat_unit
Definition view.hpp:2544
float sweep_turns
Definition view.hpp:2504
Box shadow (CSS-like: offset, blur, spread, color, inset).
Definition view.hpp:1408
Color color
Definition view.hpp:1412
float blur
Definition view.hpp:1410
float offset_y
Definition view.hpp:1409
float offset_x
Definition view.hpp:1409
bool inset
Definition view.hpp:1413
float spread
Definition view.hpp:1411
Full CSS filter chain.
Definition view.hpp:2047
float angle_deg
hue-rotate only
Definition view.hpp:2062
float ds_offset_x
Definition view.hpp:2064
Kind kind
Definition view.hpp:2060
Kind
Definition view.hpp:2048
@ blur
Definition view.hpp:2049
float amount
blur radius in px (blur), 0..1+ amount otherwise
Definition view.hpp:2061
float ds_offset_y
Definition view.hpp:2065
Color ds_color
Definition view.hpp:2067
float ds_blur
Definition view.hpp:2066
React Native hitSlop — extra hit-test area OUTSIDE the painted box.
Definition view.hpp:758
float left
Definition view.hpp:759
float bottom
Definition view.hpp:759
float right
Definition view.hpp:759
bool empty() const
Definition view.hpp:760
float top
Definition view.hpp:759
Deferred overlay paint callback.
Definition view.hpp:1509
std::function< void(canvas::Canvas &)> paint_fn
Definition view.hpp:1510
View * owner
Definition view.hpp:1511
A radial gradient's centre and radii in pixels, resolved against a box.
Definition view.hpp:2584
float ry
Definition view.hpp:2584
float cy
Definition view.hpp:2584
float rx
Definition view.hpp:2584
float cx
Definition view.hpp:2584
std::uint64_t pending_overlay_opener
Instance id of the trigger the latest press reached (0: none); a claim with no anchor of its own adop...
Definition view.hpp:1640
std::vector< OverlayRequest > overlay_queue
Definition view.hpp:1627
View * active_overlay
Definition view.hpp:1625
View * focused_input
Definition view.hpp:1624
std::vector< View * > overlay_stack
Open overlays, bottom-first; active_overlay mirrors .back().
Definition view.hpp:1637
ComboBox * active_popup
Definition view.hpp:1626
Device identity of a synthesized pointer gesture.
Definition view.hpp:634
float pressure
Definition view.hpp:636
int pointer_id
Definition view.hpp:639
std::uint16_t modifiers
Definition view.hpp:637
MouseButton button
Definition view.hpp:638
PointerType type
Definition view.hpp:635
Authored-source location for this view.
Definition view.hpp:1089
bool valid() const
Definition view.hpp:1094
int line
1-based line; 0 = unknown.
Definition view.hpp:1091
int col
1-based column; 0 = unknown.
Definition view.hpp:1092
std::string file
Source file path (as authored).
Definition view.hpp:1090
Staged CSS animation control tokens.
Definition view.hpp:2130
float iterations
Definition view.hpp:2135
float duration_seconds
Definition view.hpp:2132
float delay_seconds
Definition view.hpp:2133
std::string direction
Definition view.hpp:2136
std::string name
Definition view.hpp:2131
std::string fill_mode
Definition view.hpp:2137
CssEasing easing
Definition view.hpp:2134