1use std::rc::Rc;
5
6use super::RenderRoot;
7use crate::anim::FrameTime;
8use crate::event::ImeState;
9use crate::overlay::{
10 OverlayEntry, OverlayHit, OverlayKey, OverlayPaintPass, sort_into_paint_order,
11};
12use crate::selection_toolbar::{
13 SelectionToolbarActions, SelectionToolbarPass, SelectionToolbarRequest,
14};
15use crate::shortcuts::{OverlayStamp, ShortcutPaintPass, ShortcutTable};
16use crate::view::{ChangeFlags, View};
17use crate::widget::{PaintCtx, PaintOutcome, PaintScene};
18
19impl<State: 'static, V: View<State>> RenderRoot<State, V> {
20 pub fn paint(&mut self, scene: &mut dyn PaintScene, frame_time: FrameTime) -> PaintOutcome {
33 let overlay_pass = OverlayPaintPass::enter();
35 let toolbar_pass = SelectionToolbarPass::enter();
36 let shortcut_pass = ShortcutPaintPass::enter();
37 self.publish_focus_session();
39 self.paint_serial = self.paint_serial.wrapping_add(1);
41 let links = (self.hover_link, self.focus_epoch);
43 if links != self.painted_links {
44 self.painted_links = links;
45 self.paint_epoch = self.paint_epoch.wrapping_add(1);
46 }
47
48 let (mut outcome, main_tree_ime) = self.paint_main_tree(scene, frame_time);
49 outcome.paint_serial = self.paint_serial;
50
51 let mut entries = overlay_pass.take();
53 sort_into_paint_order(&mut entries);
54 self.overlay_hits = entries.iter().map(OverlayHit::of).collect();
56 self.overlay_pods = entries
57 .iter()
58 .map(|entry| Rc::downgrade(&entry.pod))
59 .collect();
60 let (holder, holder_ime) = self.paint_overlays(&entries, scene, frame_time, &mut outcome);
61 drop(entries);
63 self.shortcuts = ShortcutTable::new(shortcut_pass.take());
65 self.last_hints = self.shortcuts.publish();
66
67 self.resolve_session_surface(main_tree_ime, holder, holder_ime);
68 self.trap_modal_focus();
70
71 self.resolve_selection_toolbar(toolbar_pass.take());
73
74 outcome
75 }
76
77 fn resolve_session_surface(
89 &mut self,
90 main_tree_ime: Option<ImeState>,
91 holder: Option<OverlayKey>,
92 holder_ime: Option<ImeState>,
93 ) {
94 let published = if holder.is_some() {
95 holder_ime
96 } else {
97 main_tree_ime
98 };
99 let ownership_moved = holder != self.focus_surface;
100 match published {
101 Some(ime) if ime.active => self.store_ime_state(Some(ime)),
102 Some(_) => self.release_focus_session(),
103 None if ownership_moved => self.store_ime_state(None),
104 None => {}
105 }
106 self.focus_surface = if self.focus_active { holder } else { None };
108 }
109
110 fn paint_main_tree(
114 &mut self,
115 scene: &mut dyn PaintScene,
116 frame_time: FrameTime,
117 ) -> (PaintOutcome, Option<ImeState>) {
118 let Some(root_id) = self.root_id else {
119 return (PaintOutcome::default(), None);
120 };
121 let theme = self.theme.as_deref();
123 let insets = self.insets;
124 let presented_frames = self.presented_frames;
125 let surface_translucent = self.surface_translucent;
126 let (paint_epoch, retained_layers) = (self.paint_epoch, self.retained_layers);
127 let paint_serial = self.paint_serial;
128 let focus_ring = self.focus_ring_visible();
129 let retained_ledger = &self.retained_ledger;
130 let hints = Rc::clone(&self.last_hints);
131 let Some(pod) = self.tree.pod_mut(root_id) else {
132 return (PaintOutcome::default(), None);
133 };
134 let mut ctx = PaintCtx::new(pod.origin(), pod.size()).with_shortcut_hints(hints);
135 ctx.set_frame_time(frame_time);
137 ctx.set_theme(theme);
138 ctx.set_window_insets(insets);
139 ctx.set_presented_frames(presented_frames);
140 ctx.set_translucent(surface_translucent);
141 ctx.set_paint_state(
142 paint_epoch,
143 retained_layers,
144 Some(retained_ledger),
145 paint_serial,
146 );
147 ctx.set_has_focus(self.focus_active);
150 ctx.set_focus_ring(focus_ring);
151 ctx.set_focus_epoch(self.focus_epoch);
152 ctx.set_hovered(self.hover_active);
153 ctx.set_hover_epoch(self.hover_epoch);
154 pod.widget_mut().paint(&mut ctx, scene);
155 pod.clear_flags();
156 let main_tree_ime = if self.focus_active {
159 ctx.take_ime_state()
160 } else {
161 None
162 };
163 self.platform_view_frames = ctx.take_platform_views();
166 self.input_shields = ctx.take_input_shields();
167 let outcome = fold_main_tree_outcome(
168 &ctx,
169 &mut self.pending,
170 &mut self.painted_animating,
171 &mut self.deferred_frame,
172 );
173 (outcome, main_tree_ime)
174 }
175
176 fn paint_overlays(
183 &mut self,
184 entries: &[OverlayEntry],
185 scene: &mut dyn PaintScene,
186 frame_time: FrameTime,
187 outcome: &mut PaintOutcome,
188 ) -> (Option<OverlayKey>, Option<ImeState>) {
189 if entries.is_empty() {
190 return (None, None);
191 }
192 let (paint_epoch, retained_layers) = (self.paint_epoch, self.retained_layers);
193 let paint_serial = self.paint_serial;
194 let retained_ledger = &self.retained_ledger;
195 let theme = self.theme.as_deref();
196 let presented_frames = self.presented_frames;
197 let surface_translucent = self.surface_translucent;
198 let hover_active = self.hover_active;
199 let hover_epoch = self.hover_epoch;
200 let focus_active = self.focus_active;
201 let focus_epoch = self.focus_epoch;
202 let focus_ring = self.focus_ring_visible();
203
204 let mut holder: Option<(OverlayKey, Option<ImeState>)> = None;
206 let mut contested = false;
207
208 for entry in entries {
209 let mut ctx = PaintCtx::new(entry.window_rect.origin(), entry.window_rect.size())
210 .with_shortcut_hints(Rc::clone(&self.last_hints));
211 ctx.set_frame_time(frame_time);
212 ctx.set_theme(theme);
213 ctx.set_window_insets(entry.insets);
214 ctx.set_presented_frames(presented_frames);
215 ctx.set_translucent(surface_translucent);
216 ctx.set_paint_state(
217 paint_epoch,
218 retained_layers,
219 Some(retained_ledger),
220 paint_serial,
221 );
222 ctx.set_has_focus(focus_active);
224 ctx.set_focus_ring(focus_ring);
225 ctx.set_focus_epoch(focus_epoch);
226 ctx.set_hovered(hover_active);
227 ctx.set_hover_epoch(hover_epoch);
228 let pod_holds_focus = {
229 let _stamp = OverlayStamp::enter(entry.key);
230 let mut pod = entry.pod.borrow_mut();
231 pod.retire_stale_focus_link();
232 let holds = pod.holds_live_focus();
233 pod.paint_child(&mut ctx, scene);
234 holds
235 };
236
237 fold_overlay_outcome(&ctx, outcome, &mut self.pending);
238 let published = ctx.take_ime_state();
241 if focus_active && pod_holds_focus {
242 if holder.is_some() {
243 contested = true;
244 } else {
245 holder = Some((entry.key, published));
246 }
247 }
248 self.platform_view_frames.extend(ctx.take_platform_views());
250 self.input_shields.extend(ctx.take_input_shields());
251 }
252
253 match holder {
254 Some((key, published)) if !contested => (Some(key), published),
255 _ => (None, None),
256 }
257 }
258
259 fn resolve_selection_toolbar(&mut self, published: Option<SelectionToolbarRequest>) {
263 let next = if self.focus_active { published } else { None };
264 let menu_edge = |request: &Option<SelectionToolbarRequest>| {
266 request.map_or((false, SelectionToolbarActions::default()), |request| {
267 (request.present_menu, request.actions)
268 })
269 };
270 if menu_edge(&self.selection_toolbar) != menu_edge(&next) {
271 self.selection_toolbar_gen = self.selection_toolbar_gen.wrapping_add(1);
272 }
273 self.selection_toolbar = next;
274 }
275
276 pub fn selection_toolbar(&self) -> Option<SelectionToolbarRequest> {
283 self.selection_toolbar
284 }
285
286 pub fn selection_toolbar_generation(&self) -> u64 {
291 self.selection_toolbar_gen
292 }
293}
294
295fn fold_main_tree_outcome(
300 ctx: &PaintCtx<'_>,
301 pending: &mut ChangeFlags,
302 painted_animating: &mut bool,
303 deferred_frame: &mut bool,
304) -> PaintOutcome {
305 let needs_layout = ctx.needs_layout();
306 let animating = needs_layout || ctx.needs_frame();
307 let unpaced = needs_layout || (ctx.needs_frame() && !ctx.needs_frame_paced_only());
308 let landing = *painted_animating && !animating;
309 if unpaced || landing || ctx.is_layout_path_dirty() {
310 *pending |= ChangeFlags::LAYOUT;
311 }
312 *painted_animating = animating;
313 let deferred_frame = std::mem::take(deferred_frame);
315 PaintOutcome {
316 needs_frame: ctx.needs_frame() || deferred_frame,
317 needs_layout,
318 needs_frame_paced_only: ctx.needs_frame_paced_only(),
319 paced_interval: ctx.paced_interval(),
320 paint_serial: 0,
322 }
323}
324
325fn fold_overlay_outcome(ctx: &PaintCtx<'_>, outcome: &mut PaintOutcome, pending: &mut ChangeFlags) {
329 let stood_unpaced = outcome.needs_frame && !outcome.needs_frame_paced_only;
330 let entry_unpaced = ctx.needs_frame() && !ctx.needs_frame_paced_only();
331 outcome.needs_frame |= ctx.needs_frame();
332 outcome.needs_frame_paced_only = outcome.needs_frame && !(stood_unpaced || entry_unpaced);
333 outcome.paced_interval = match (outcome.paced_interval, ctx.paced_interval()) {
334 (Some(standing), Some(asked)) => Some(standing.min(asked)),
335 (standing, asked) => standing.or(asked),
336 };
337 if ctx.needs_layout() {
338 outcome.needs_layout = true;
339 *pending |= ChangeFlags::LAYOUT;
340 }
341 if ctx.is_layout_path_dirty() {
342 *pending |= ChangeFlags::LAYOUT;
343 }
344}