1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
//! `MainPanel::stamp_frame_themes`: mirror each panel's effective theme
//! *background* onto its `<regular-layout-frame>`.
//!
//! The frames live in the viewer's shadow DOM, so the document theme rules
//! (`perspective-viewer [theme="X"]`) can never match them — the
//! `--psp--background-color` their `::part(container)` background resolves
//! (viewer.css) inherits down from the viewer host, i.e. always the *host*
//! theme. A frame is normally covered by its slotted plugin (which paints its
//! own per-panel themed background), but while the plugin is missing — not yet
//! mounted, first draw pending, or torn down — the host-theme container shows
//! through a panel themed differently, as a visible artifact.
//!
//! There is no native cascade channel from the light-DOM plugin to the frame
//! (siblings in the flattened tree), so the value is mirrored imperatively:
//! each panel's *plugin element* — light-DOM, slotted under the panel's slot,
//! mounted eagerly at panel creation (`create_panel_model` /
//! `Renderer::mount_active_plugin`) — is where the document theme rules
//! actually resolve, so its computed `--psp--background-color` is copied onto
//! the frame's inline style, where the frame's shadow parts inherit it. The
//! plugin is the ONLY sound source element:
//!
//! - An owned hidden probe child of the viewer does NOT work: an *unslotted*
//! light-DOM child of a shadow host is outside the flattened tree, and
//! `getComputedStyle` returns all-empty for it even though the document rules
//! match it syntactically (selector matching is DOM-tree; style computation
//! is flat-tree).
//! - The `<perspective-viewer-tab>` is slotted, but stamps its own `theme` attr
//! in `PanelTab::rendered` — an unordered sibling lifecycle relative to this
//! pass (the theme-stamp-lag class of bug).
//! - The plugin's `theme` attr, by contrast, is stamped *synchronously at the
//! mutation sites* (`update_theme`, `restorePanel`, …) before the events that
//! schedule this render, so it is current when this pass reads it.
//!
//! A read is trusted ONLY when the plugin's stamped attr equals the theme
//! being mirrored: a freshly-created panel's plugin is mounted *unstamped*
//! (the attr first lands inside its first locked dispatch), and reading it
//! early would silently mirror the HOST theme's values. Trusted reads seed
//! [`MainPanel::theme_backgrounds`], the fallback for frames with no readable
//! plugin (an unregistered plugin name stays lazily unmounted; plugin-switch
//! and teardown transients). A frame with neither leaves the pass gate
//! unlatched, so it retries on subsequent renders until the dispatch stamp
//! lands (the render that follows that dispatch's `update_count` bump).
//!
//! Unlike the plugin `theme`/`active` stamps (see the NOTE in [`reconcile`]),
//! the frame is pure viewer chrome — no plugin dispatch reads it — so
//! stamping it from this async `rendered` pass cannot split a plugin draw
//! across paints, and it needs no lock.
use *;
use *;
use MainPanel;
use cratePtrEqRc;
use cratePanelId;
/// The custom property mirrored onto each frame: what viewer.css's
/// `.rl-panel::part(container)` background resolves.
const BACKGROUND_VAR: &str = "--psp--background-color";
/// The inputs the frame backgrounds were last computed from; re-mirroring is
/// skipped while these are unchanged, so the forced style recalcs of
/// `getComputedStyle` don't run on every render (e.g. the per-update
/// `update_count` renders of a streaming table). `available_themes` is part of
/// the key because theme CSS registering late changes the *computed* value
/// under an unchanged theme name.
pub type FrameThemeSnapshot = ;
/// Read the computed [`BACKGROUND_VAR`] off `slot`'s plugin element — the
/// viewer light-DOM child mounted under exactly that slot name (the tab and
/// toolbar use `tab-`/`statusbar-extra-` prefixed slots). Requires the
/// plugin's `theme` attr to already equal `theme` — during a plugin switch
/// two elements briefly share the slot, and a freshly-mounted plugin is not
/// yet stamped; both are disambiguated by the attr check.