zng_app/
update.rs

1//! App updates API.
2
3use std::{
4    collections::{HashMap, hash_map},
5    fmt, mem,
6    sync::Arc,
7    task::Waker,
8};
9
10use parking_lot::Mutex;
11use zng_app_context::app_local;
12use zng_handle::{Handle, HandleOwner, WeakHandle};
13use zng_task::channel::ChannelError;
14use zng_unique_id::IdSet;
15use zng_var::{VARS, VARS_APP};
16
17use crate::{
18    AppEventSender, LoopTimer, async_hn_once,
19    handler::{AppWeakHandle, Handler, HandlerExt as _},
20    hn_once,
21    timer::TIMERS_SV,
22    widget::{
23        WIDGET, WidgetId,
24        info::{InteractionPath, WidgetInfo, WidgetInfoTree, WidgetPath},
25        node::UiNode,
26    },
27    window::{WINDOW, WindowId},
28};
29
30/// Represents all the widgets and windows marked to receive an update.
31pub struct UpdateDeliveryList {
32    windows: IdSet<WindowId>,
33    widgets: IdSet<WidgetId>,
34    search: IdSet<WidgetId>,
35    search_root: bool,
36}
37impl fmt::Debug for UpdateDeliveryList {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        f.debug_struct("UpdateDeliveryList")
40            .field("windows", &self.windows)
41            .field("widgets", &self.widgets)
42            .field("search", &self.search)
43            .finish_non_exhaustive()
44    }
45}
46impl Default for UpdateDeliveryList {
47    fn default() -> Self {
48        Self::new()
49    }
50}
51impl UpdateDeliveryList {
52    /// New list that only allows `subscribers`.
53    pub fn new() -> Self {
54        Self {
55            windows: IdSet::default(),
56            widgets: IdSet::default(),
57            search: IdSet::default(),
58            search_root: false,
59        }
60    }
61
62    pub(crate) fn insert_updates_root(&mut self, window_id: WindowId, root_id: WidgetId) {
63        self.windows.insert(window_id);
64        self.widgets.insert(root_id);
65    }
66
67    /// Insert the `wgt` and ancestors up-to the inner most that is included in the subscribers.
68    pub fn insert_wgt(&mut self, wgt: &impl WidgetPathProvider) {
69        for w in wgt.widget_and_ancestors() {
70            self.widgets.insert(w);
71        }
72        self.windows.insert(wgt.window_id());
73    }
74
75    /// Insert the window by itself, the window root widget will be targeted.
76    pub fn insert_window(&mut self, id: WindowId) {
77        self.windows.insert(id);
78        self.search_root = true;
79    }
80
81    /// Register the widget of unknown location for search before delivery routing starts.
82    pub fn search_widget(&mut self, widget_id: WidgetId) {
83        self.search.insert(widget_id);
84    }
85
86    /// If the list has pending widgets that must be found before delivery can start.
87    pub fn has_pending_search(&mut self) -> bool {
88        self.search_root || !self.search.is_empty()
89    }
90
91    /// Search all pending widgets in all `windows`, all search items are cleared, even if not found.
92    pub fn fulfill_search<'a, 'b>(&'a mut self, windows: impl Iterator<Item = &'b WidgetInfoTree>) {
93        for window in windows {
94            if self.search_root && self.windows.contains(&window.window_id()) {
95                self.widgets.insert(window.root().id());
96            }
97
98            self.search.retain(|w| {
99                if let Some(w) = window.get(*w) {
100                    for w in w.widget_and_ancestors() {
101                        self.widgets.insert(w);
102                    }
103                    self.windows.insert(w.window_id());
104                    false
105                } else {
106                    true
107                }
108            });
109        }
110        self.search.clear();
111        self.search_root = true;
112    }
113
114    /// Copy windows, widgets and search from `other`, trusting that all values are allowed.
115    fn extend_unchecked(&mut self, other: UpdateDeliveryList) {
116        if self.windows.is_empty() {
117            self.windows = other.windows;
118        } else {
119            self.windows.extend(other.windows);
120        }
121
122        if self.widgets.is_empty() {
123            self.widgets = other.widgets;
124        } else {
125            self.widgets.extend(other.widgets);
126        }
127
128        if self.search.is_empty() {
129            self.search = other.search;
130        } else {
131            self.search.extend(other.search);
132        }
133    }
134
135    /// Returns `true` if the window is on the list.
136    pub fn enter_window(&self, window_id: WindowId) -> bool {
137        self.windows.contains(&window_id)
138    }
139
140    /// Returns `true` if the widget is on the list.
141    pub fn enter_widget(&self, widget_id: WidgetId) -> bool {
142        self.widgets.contains(&widget_id)
143    }
144
145    /// Windows in the delivery list.
146    pub fn windows(&self) -> &IdSet<WindowId> {
147        &self.windows
148    }
149
150    /// Found widgets in the delivery list, can be targets or ancestors of targets.
151    pub fn widgets(&self) -> &IdSet<WidgetId> {
152        &self.widgets
153    }
154
155    /// Widgets still pending search or not found.
156    #[must_use = "use `search_all` to request search"]
157    pub fn search_widgets(&mut self) -> &IdSet<WidgetId> {
158        &self.search
159    }
160
161    /// If search for window a root is pending.
162    #[must_use = "use `search_widget` to request search"]
163    pub fn search_root(&mut self) -> bool {
164        self.search_root
165    }
166}
167
168/// Provides an iterator of widget IDs and a window ID.
169pub trait WidgetPathProvider {
170    /// Output of `widget_and_ancestors`.
171    type WidgetIter<'s>: Iterator<Item = WidgetId>
172    where
173        Self: 's;
174
175    /// The window parent.
176    fn window_id(&self) -> WindowId;
177    /// Iterate over the widget, parent, grandparent, .., root.
178    fn widget_and_ancestors(&self) -> Self::WidgetIter<'_>;
179}
180impl WidgetPathProvider for WidgetInfo {
181    type WidgetIter<'s> = std::iter::Map<crate::widget::info::iter::Ancestors, fn(WidgetInfo) -> WidgetId>;
182
183    fn window_id(&self) -> WindowId {
184        self.tree().window_id()
185    }
186
187    fn widget_and_ancestors(&self) -> Self::WidgetIter<'_> {
188        fn wgt_to_id(wgt: WidgetInfo) -> WidgetId {
189            wgt.id()
190        }
191        self.self_and_ancestors().map(wgt_to_id)
192    }
193}
194impl WidgetPathProvider for WidgetPath {
195    type WidgetIter<'s> = std::iter::Rev<std::iter::Copied<std::slice::Iter<'s, WidgetId>>>;
196
197    fn window_id(&self) -> WindowId {
198        self.window_id()
199    }
200
201    fn widget_and_ancestors(&self) -> Self::WidgetIter<'_> {
202        self.widgets_path().iter().copied().rev()
203    }
204}
205impl WidgetPathProvider for InteractionPath {
206    type WidgetIter<'s> = std::iter::Rev<std::iter::Copied<std::slice::Iter<'s, WidgetId>>>;
207
208    fn window_id(&self) -> WindowId {
209        WidgetPath::window_id(self)
210    }
211
212    fn widget_and_ancestors(&self) -> Self::WidgetIter<'_> {
213        self.widgets_path().iter().copied().rev()
214    }
215}
216
217/// Widget info updates of the current cycle.
218#[derive(Debug, Default)]
219pub struct InfoUpdates {
220    delivery_list: UpdateDeliveryList,
221}
222impl InfoUpdates {
223    /// New with list.
224    pub fn new(delivery_list: UpdateDeliveryList) -> Self {
225        Self { delivery_list }
226    }
227
228    /// Request delivery list.
229    pub fn delivery_list(&self) -> &UpdateDeliveryList {
230        &self.delivery_list
231    }
232
233    /// Request delivery list.
234    pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
235        &mut self.delivery_list
236    }
237
238    /// Calls `handle` if info rebuild was requested for the window.
239    pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
240    where
241        H: FnOnce() -> R,
242    {
243        if self.delivery_list.enter_window(window_id) {
244            Some(handle())
245        } else {
246            None
247        }
248    }
249
250    /// Copy all delivery from `other` onto `self`.
251    pub fn extend(&mut self, other: InfoUpdates) {
252        self.delivery_list.extend_unchecked(other.delivery_list)
253    }
254}
255
256/// Widget updates of the current cycle.
257#[derive(Debug, Default)]
258pub struct WidgetUpdates {
259    pub(crate) delivery_list: UpdateDeliveryList,
260}
261impl WidgetUpdates {
262    /// New with list.
263    pub fn new(delivery_list: UpdateDeliveryList) -> Self {
264        Self { delivery_list }
265    }
266
267    /// Updates delivery list.
268    pub fn delivery_list(&self) -> &UpdateDeliveryList {
269        &self.delivery_list
270    }
271
272    /// Updates delivery list.
273    pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
274        &mut self.delivery_list
275    }
276
277    /// Calls `handle` if update was requested for the [`WINDOW`].
278    pub fn with_window<H, R>(&self, handle: H) -> Option<R>
279    where
280        H: FnOnce() -> R,
281    {
282        if self.delivery_list.enter_window(WINDOW.id()) {
283            Some(handle())
284        } else {
285            None
286        }
287    }
288
289    /// Calls `handle` if update was requested for the [`WIDGET`].
290    pub fn with_widget<H, R>(&self, handle: H) -> Option<R>
291    where
292        H: FnOnce() -> R,
293    {
294        if WIDGET.take_update(UpdateFlags::UPDATE) || self.delivery_list.enter_widget(WIDGET.id()) {
295            Some(handle())
296        } else {
297            None
298        }
299    }
300
301    /// Copy all delivery from `other` onto `self`.
302    pub fn extend(&mut self, other: WidgetUpdates) {
303        self.delivery_list.extend_unchecked(other.delivery_list)
304    }
305}
306
307/// Widget layout updates of the current cycle.
308#[derive(Debug, Default)]
309pub struct LayoutUpdates {
310    pub(crate) delivery_list: UpdateDeliveryList,
311}
312impl LayoutUpdates {
313    /// New with list.
314    pub fn new(delivery_list: UpdateDeliveryList) -> Self {
315        Self { delivery_list }
316    }
317
318    /// Request delivery list.
319    pub fn delivery_list(&self) -> &UpdateDeliveryList {
320        &self.delivery_list
321    }
322
323    /// Request delivery list.
324    pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
325        &mut self.delivery_list
326    }
327
328    /// Calls `handle` if layout rebuild was requested for the window.
329    pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
330    where
331        H: FnOnce() -> R,
332    {
333        if self.delivery_list.enter_window(window_id) {
334            Some(handle())
335        } else {
336            None
337        }
338    }
339
340    /// Copy all delivery from `other` onto `self`.
341    pub fn extend(&mut self, other: LayoutUpdates) {
342        self.delivery_list.extend_unchecked(other.delivery_list)
343    }
344}
345
346/// Widget render updates of the current cycle.
347#[derive(Debug, Default)]
348pub struct RenderUpdates {
349    delivery_list: UpdateDeliveryList,
350}
351impl RenderUpdates {
352    /// New with list.
353    pub fn new(delivery_list: UpdateDeliveryList) -> Self {
354        Self { delivery_list }
355    }
356
357    /// Request delivery list.
358    pub fn delivery_list(&self) -> &UpdateDeliveryList {
359        &self.delivery_list
360    }
361
362    /// Request delivery list.
363    pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
364        &mut self.delivery_list
365    }
366
367    /// Calls `handle` if render frame rebuild or update was requested for the window.
368    pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
369    where
370        H: FnOnce() -> R,
371    {
372        if self.delivery_list.enter_window(window_id) {
373            Some(handle())
374        } else {
375            None
376        }
377    }
378
379    /// Copy all delivery from `other` onto `self`.
380    pub fn extend(&mut self, other: RenderUpdates) {
381        self.delivery_list.extend_unchecked(other.delivery_list)
382    }
383}
384
385/// Extension methods for infinite loop diagnostics.
386///
387/// You can also use [`updates_trace_span`] and [`updates_trace_event`] to define custom scopes and entries.
388pub trait UpdatesTraceUiNodeExt {
389    /// Defines a custom span.
390    fn instrument<S: Into<String>>(self, tag: S) -> UiNode
391    where
392        Self: Sized;
393}
394impl UpdatesTraceUiNodeExt for UiNode {
395    fn instrument<S: Into<String>>(self, tag: S) -> UiNode {
396        let tag = tag.into();
397        self.trace(move |op| UpdatesTrace::custom_span(&tag, op.mtd_name()))
398    }
399}
400
401/// Custom span in the app loop diagnostics.
402///
403/// See [`UpdatesTraceUiNodeExt`] for more details.
404pub fn updates_trace_span(tag: &'static str) -> tracing::span::EnteredSpan {
405    UpdatesTrace::custom_span(tag, "")
406}
407
408/// Custom log entry in the app loop diagnostics.
409///
410/// See [`UpdatesTraceUiNodeExt`] for more details.
411pub fn updates_trace_event(tag: &str) {
412    UpdatesTrace::log_custom(tag)
413}
414
415pub(crate) struct UpdatesTrace {
416    context: Mutex<UpdateContext>,
417    trace: Arc<Mutex<Vec<UpdateTrace>>>,
418
419    widgets_stack: Mutex<Vec<(WidgetId, String)>>,
420    node_parents_stack: Mutex<Vec<String>>,
421    tags_stack: Mutex<Vec<String>>,
422}
423impl tracing::subscriber::Subscriber for UpdatesTrace {
424    fn enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
425        metadata.target() == Self::UPDATES_TARGET
426    }
427
428    fn new_span(&self, span: &tracing::span::Attributes<'_>) -> tracing::span::Id {
429        match span.metadata().name() {
430            "property" | "intrinsic" => {
431                let name = visit_str(|v| span.record(v), "name");
432                let mut ctx = self.context.lock();
433
434                if let Some(p) = ctx.node_parent.replace(name) {
435                    self.node_parents_stack.lock().push(p);
436                }
437                if let Some(p) = ctx.tag.replace(String::new()) {
438                    self.tags_stack.lock().push(p);
439                }
440
441                tracing::span::Id::from_u64(1)
442            }
443            "widget" => {
444                let id = visit_u64(|v| span.record(v), "raw_id").unwrap();
445                if id == 0 {
446                    panic!()
447                }
448                let id = WidgetId::from_raw(id);
449
450                let name = visit_str(|v| span.record(v), "name");
451
452                let mut ctx = self.context.lock();
453                if let Some(p) = ctx.widget.replace((id, name)) {
454                    self.widgets_stack.lock().push(p);
455                }
456
457                if let Some(p) = ctx.node_parent.replace(String::new()) {
458                    self.node_parents_stack.lock().push(p);
459                }
460
461                if let Some(p) = ctx.tag.replace(String::new()) {
462                    self.tags_stack.lock().push(p);
463                }
464
465                tracing::span::Id::from_u64(2)
466            }
467            "Window" => {
468                let id = visit_u64(|v| span.record(v), "raw_id").unwrap() as u32;
469                if id == 0 {
470                    panic!()
471                }
472                let id = WindowId::from_raw(id);
473
474                let mut ctx = self.context.lock();
475                ctx.window_id = Some(id);
476
477                if let Some(p) = ctx.tag.replace(String::new()) {
478                    self.tags_stack.lock().push(p);
479                }
480
481                tracing::span::Id::from_u64(3)
482            }
483            "tag" => {
484                let tag = visit_str(|v| span.record(v), "tag");
485                let mut ctx = self.context.lock();
486                if let Some(p) = ctx.tag.replace(tag) {
487                    self.tags_stack.lock().push(p);
488                }
489                tracing::span::Id::from_u64(5)
490            }
491            _ => tracing::span::Id::from_u64(u64::MAX),
492        }
493    }
494
495    fn record(&self, _span: &tracing::span::Id, _values: &tracing::span::Record<'_>) {}
496
497    fn record_follows_from(&self, _span: &tracing::span::Id, _follows: &tracing::span::Id) {}
498
499    fn event(&self, event: &tracing::Event<'_>) {
500        let action = match visit_str(|v| event.record(v), "kind").as_str() {
501            "var" => UpdateAction::Var {
502                type_name: visit_str(|v| event.record(v), "type_name"),
503            },
504            "request" => UpdateAction::Update,
505            "info" => UpdateAction::Info,
506            "layout" => UpdateAction::Layout,
507            "render" => UpdateAction::Render,
508            "custom" => UpdateAction::Custom {
509                tag: visit_str(|v| event.record(v), "tag"),
510            },
511            _ => return,
512        };
513
514        let ctx = self.context.lock().clone();
515        // if ctx.app_extension.is_none() {
516        //     return;
517        // }
518
519        let entry = UpdateTrace { ctx, action };
520        self.trace.lock().push(entry);
521    }
522
523    fn enter(&self, _span: &tracing::span::Id) {}
524
525    fn exit(&self, span: &tracing::span::Id) {
526        let mut ctx = self.context.lock();
527        if span == &tracing::span::Id::from_u64(1) {
528            ctx.node_parent = self.node_parents_stack.lock().pop();
529            ctx.tag = self.tags_stack.lock().pop();
530        } else if span == &tracing::span::Id::from_u64(2) {
531            ctx.widget = self.widgets_stack.lock().pop();
532            ctx.node_parent = self.node_parents_stack.lock().pop();
533            ctx.tag = self.tags_stack.lock().pop();
534        } else if span == &tracing::span::Id::from_u64(3) {
535            ctx.window_id = None;
536            ctx.tag = self.tags_stack.lock().pop();
537        } else if span == &tracing::span::Id::from_u64(4) {
538            ctx.app_extension = None;
539            ctx.tag = self.tags_stack.lock().pop();
540        } else if span == &tracing::span::Id::from_u64(5) {
541            ctx.tag = self.tags_stack.lock().pop();
542        }
543    }
544}
545impl UpdatesTrace {
546    const UPDATES_TARGET: &'static str = "zng-updates";
547
548    fn new() -> Self {
549        UpdatesTrace {
550            context: Mutex::new(UpdateContext::default()),
551            trace: Arc::new(Mutex::new(Vec::with_capacity(100))),
552            widgets_stack: Mutex::new(Vec::with_capacity(100)),
553            node_parents_stack: Mutex::new(Vec::with_capacity(100)),
554            tags_stack: Mutex::new(Vec::new()),
555        }
556    }
557
558    /// Opens a window span.
559    ///
560    /// The span is at the DEBUG level.
561    pub fn window_span(id: WindowId) -> tracing::span::EnteredSpan {
562        tracing::debug_span!(target: UpdatesTrace::UPDATES_TARGET, "Window", %id, raw_id = id.get() as u64).entered()
563    }
564
565    /// Opens a widget span.
566    ///
567    /// The span is at the DEBUG level.
568    #[cfg(feature = "trace_widget")]
569    pub fn widget_span(id: WidgetId, name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
570        tracing::debug_span!(target: UpdatesTrace::UPDATES_TARGET, "widget", %id, raw_id = id.get(), name, %node_mtd).entered()
571    }
572
573    /// Opens a property span.
574    ///
575    /// The span is at the TRACE level.
576    #[cfg(feature = "trace_wgt_item")]
577    pub fn property_span(name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
578        tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "property", name, %node_mtd).entered()
579    }
580
581    /// Opens an intrinsic span.
582    ///
583    /// The span is at the TRACE level.
584    #[cfg(feature = "trace_wgt_item")]
585    pub fn intrinsic_span(name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
586        tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "intrinsic", name, %node_mtd).entered()
587    }
588
589    /// Opens a custom named span.
590    ///
591    /// The span is at the TRACE level.
592    pub fn custom_span(name: &str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
593        tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "tag", %name, %node_mtd).entered()
594    }
595
596    /// Log a direct update request.
597    ///
598    /// The event is at the TRACE level.
599    pub fn log_update() {
600        tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
601            kind = "update"
602        });
603    }
604
605    /// Log a direct info rebuild request.
606    ///
607    /// The event is at the TRACE level.
608    pub fn log_info() {
609        tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
610            kind = "info"
611        });
612    }
613
614    /// Log a direct layout request.
615    ///
616    /// The event is at the TRACE level.
617    pub fn log_layout() {
618        tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
619            kind = "layout"
620        });
621    }
622
623    /// Log a direct render request.
624    ///
625    /// The event is at the TRACE level.
626    pub fn log_render() {
627        tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
628            kind = "render"
629        });
630    }
631
632    /// Log a custom event.
633    ///
634    /// The event is at the TRACE level.
635    pub fn log_custom(tag: &str) {
636        tracing::event!(
637            target: UpdatesTrace::UPDATES_TARGET,
638            tracing::Level::TRACE,
639            { kind = "custom", %tag }
640        );
641    }
642
643    /// Log a var update request.
644    ///
645    /// The event is at the TRACE level.
646    pub fn log_var(type_name: &str) {
647        tracing::event!(
648            target: UpdatesTrace::UPDATES_TARGET,
649            tracing::Level::TRACE,
650            { kind = "var", type_name = pretty_type_name::pretty_type_name_str(type_name) }
651        );
652    }
653
654    /// Run `action` collecting a trace of what caused updates.
655    pub fn collect_trace<R>(trace: &mut Vec<UpdateTrace>, action: impl FnOnce() -> R) -> R {
656        let tracer = UpdatesTrace::new();
657        let result = Arc::clone(&tracer.trace);
658        let r = tracing::subscriber::with_default(tracer, action);
659        trace.extend(Arc::try_unwrap(result).unwrap().into_inner());
660
661        r
662    }
663
664    /// Displays the top 20 most frequent update sources in the trace.
665    pub fn format_trace(trace: Vec<UpdateTrace>) -> String {
666        let mut frequencies = HashMap::with_capacity(50);
667        for t in trace {
668            match frequencies.entry(t) {
669                hash_map::Entry::Vacant(e) => {
670                    e.insert(1);
671                }
672                hash_map::Entry::Occupied(mut e) => {
673                    *e.get_mut() += 1;
674                }
675            }
676        }
677        let mut frequencies: Vec<_> = frequencies.into_iter().collect();
678        frequencies.sort_by_key(|(_, c)| -c);
679
680        let mut trace = String::new();
681        for (t, c) in frequencies.into_iter().take(20) {
682            use std::fmt::Write;
683            let _ = writeln!(&mut trace, "{t} ({c} times)");
684        }
685        trace
686    }
687}
688#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
689struct UpdateContext {
690    app_extension: Option<String>,
691    window_id: Option<WindowId>,
692    widget: Option<(WidgetId, String)>,
693    node_parent: Option<String>,
694    tag: Option<String>,
695}
696impl fmt::Display for UpdateContext {
697    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
698        if let Some(e) = &self.app_extension {
699            write!(f, "{}", e.rsplit("::").next().unwrap())?;
700        } else {
701            write!(f, "<unknown>")?;
702        }
703        if let Some(w) = self.window_id {
704            write!(f, "//{w}")?;
705        }
706        if let Some((id, name)) = &self.widget {
707            write!(f, "/../{name}#{id}")?;
708        }
709        if let Some(p) = &self.node_parent
710            && !p.is_empty()
711        {
712            write!(f, "//{p}")?;
713        }
714        if let Some(t) = &self.tag
715            && !t.is_empty()
716        {
717            write!(f, "//{t}")?;
718        }
719        Ok(())
720    }
721}
722
723#[derive(Debug, PartialEq, Eq, Hash)]
724pub(crate) struct UpdateTrace {
725    ctx: UpdateContext,
726    action: UpdateAction,
727}
728impl fmt::Display for UpdateTrace {
729    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
730        write!(f, "{} {}", self.ctx, self.action)
731    }
732}
733#[derive(Debug, PartialEq, Eq, Hash)]
734enum UpdateAction {
735    Info,
736    Update,
737    Layout,
738    Render,
739    Var { type_name: String },
740    Custom { tag: String },
741}
742impl fmt::Display for UpdateAction {
743    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
744        match self {
745            UpdateAction::Info => write!(f, "info"),
746            UpdateAction::Update => write!(f, "update"),
747            UpdateAction::Layout => write!(f, "layout"),
748            UpdateAction::Render => write!(f, "render"),
749            UpdateAction::Var { type_name } => write!(f, "update {type_name}"),
750            UpdateAction::Custom { tag } => write!(f, "{tag}"),
751        }
752    }
753}
754
755fn visit_str(record: impl FnOnce(&mut dyn tracing::field::Visit), name: &str) -> String {
756    struct Visitor<'a> {
757        name: &'a str,
758        result: String,
759    }
760    impl tracing::field::Visit for Visitor<'_> {
761        fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
762            if field.name() == self.name {
763                self.result = format!("{value:?}");
764            }
765        }
766        fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
767            if field.name() == self.name {
768                value.clone_into(&mut self.result);
769            }
770        }
771    }
772
773    let mut visitor = Visitor {
774        name,
775        result: String::new(),
776    };
777    record(&mut visitor);
778    visitor.result
779}
780fn visit_u64(record: impl FnOnce(&mut dyn tracing::field::Visit), name: &str) -> Option<u64> {
781    struct Visitor<'a> {
782        name: &'a str,
783        result: Option<u64>,
784    }
785    impl tracing::field::Visit for Visitor<'_> {
786        fn record_debug(&mut self, _field: &tracing::field::Field, _value: &dyn std::fmt::Debug) {}
787        fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
788            if field.name() == self.name {
789                self.result = Some(value)
790            }
791        }
792    }
793
794    let mut visitor = Visitor { name, result: None };
795    record(&mut visitor);
796    visitor.result
797}
798
799/// Update schedule service.
800pub struct UPDATES;
801impl UPDATES {
802    pub(crate) fn init(&self, event_sender: AppEventSender) {
803        UPDATES_SV.write().event_sender = Some(event_sender);
804    }
805
806    #[must_use]
807    #[cfg(any(test, doc, feature = "test_util"))]
808    pub(crate) fn apply(&self) -> ContextUpdates {
809        self.apply_updates() | self.apply_info() | self.apply_layout_render()
810    }
811
812    #[must_use]
813    pub(crate) fn apply_updates(&self) -> ContextUpdates {
814        VARS_APP.apply_updates();
815
816        let (update, update_widgets) = UPDATES.take_update();
817
818        ContextUpdates {
819            update,
820            update_widgets,
821            info: false,
822            info_widgets: InfoUpdates::default(),
823            layout: false,
824            layout_widgets: LayoutUpdates::default(),
825            render: false,
826            render_widgets: RenderUpdates::default(),
827            render_update_widgets: RenderUpdates::default(),
828        }
829    }
830    #[must_use]
831    pub(crate) fn apply_info(&self) -> ContextUpdates {
832        let (info, info_widgets) = UPDATES.take_info();
833
834        ContextUpdates {
835            update: false,
836            update_widgets: WidgetUpdates::default(),
837            info,
838            info_widgets,
839            layout: false,
840            layout_widgets: LayoutUpdates::default(),
841            render: false,
842            render_widgets: RenderUpdates::default(),
843            render_update_widgets: RenderUpdates::default(),
844        }
845    }
846    #[must_use]
847    pub(crate) fn apply_layout_render(&self) -> ContextUpdates {
848        let (layout, layout_widgets) = UPDATES.take_layout();
849        let (render, render_widgets, render_update_widgets) = UPDATES.take_render();
850
851        ContextUpdates {
852            update: false,
853            update_widgets: WidgetUpdates::default(),
854            info: false,
855            info_widgets: InfoUpdates::default(),
856            layout,
857            layout_widgets,
858            render,
859            render_widgets,
860            render_update_widgets,
861        }
862    }
863
864    pub(crate) fn on_app_awake(&self) {
865        UPDATES_SV.write().app_awake(true);
866    }
867
868    pub(crate) fn on_app_sleep(&self) {
869        UPDATES_SV.write().app_awake(false);
870    }
871
872    /// Returns next timer or animation tick time.
873    pub(crate) fn next_deadline(&self, timer: &mut LoopTimer) {
874        TIMERS_SV.write().next_deadline(timer);
875        VARS_APP.next_deadline(timer);
876    }
877
878    /// Update timers and animations, returns next wake time.
879    pub(crate) fn update_timers(&self, timer: &mut LoopTimer) {
880        TIMERS_SV.write().apply_updates(timer);
881        VARS_APP.update_animations(timer);
882    }
883
884    /// If a call to `apply_updates` will generate updates (ignoring timers).
885    #[must_use]
886    pub(crate) fn has_pending_updates(&self) -> bool {
887        UPDATES_SV.read().update_ext.intersects(UpdateFlags::UPDATE | UpdateFlags::INFO)
888            || VARS_APP.has_pending_updates()
889            || TIMERS_SV.read().has_pending_updates()
890    }
891
892    #[must_use]
893    pub(crate) fn has_pending_layout_or_render(&self) -> bool {
894        UPDATES_SV
895            .read()
896            .update_ext
897            .intersects(UpdateFlags::LAYOUT | UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE)
898    }
899
900    /// Create an [`AppEventSender`] that can be used to awake the app and send app events from threads outside of the app.
901    pub fn sender(&self) -> AppEventSender {
902        UPDATES_SV.read().event_sender.as_ref().unwrap().clone()
903    }
904
905    /// Create an std task waker that wakes the event loop and updates.
906    pub fn waker(&self, also_update: Option<WidgetId>) -> Waker {
907        UPDATES_SV.read().event_sender.as_ref().unwrap().waker(also_update)
908    }
909
910    pub(crate) fn update_flags_root(&self, flags: UpdateFlags, window_id: WindowId, root_id: WidgetId) {
911        if flags.is_empty() {
912            return;
913        }
914
915        let mut u = UPDATES_SV.write();
916        if flags.contains(UpdateFlags::UPDATE) {
917            u.update_widgets.insert_updates_root(window_id, root_id);
918        }
919        if flags.contains(UpdateFlags::INFO) {
920            u.info_widgets.insert_updates_root(window_id, root_id);
921        }
922        if flags.contains(UpdateFlags::LAYOUT) {
923            u.layout_widgets.insert_updates_root(window_id, root_id);
924        }
925
926        if flags.contains(UpdateFlags::RENDER) {
927            u.render_widgets.insert_updates_root(window_id, root_id);
928        } else if flags.contains(UpdateFlags::RENDER_UPDATE) {
929            u.render_update_widgets.insert_updates_root(window_id, root_id);
930        }
931
932        u.update_ext |= flags;
933    }
934
935    pub(crate) fn update_flags(&self, flags: UpdateFlags, target: WidgetId) {
936        if flags.is_empty() {
937            return;
938        }
939
940        let mut u = UPDATES_SV.write();
941
942        if flags.contains(UpdateFlags::UPDATE) {
943            u.update_widgets.search_widget(target);
944        }
945        if flags.contains(UpdateFlags::INFO) {
946            u.info_widgets.search_widget(target);
947        }
948        if flags.contains(UpdateFlags::LAYOUT) {
949            u.layout_widgets.search_widget(target);
950        }
951
952        if flags.contains(UpdateFlags::RENDER) {
953            u.render_widgets.search_widget(target);
954        } else if flags.contains(UpdateFlags::RENDER_UPDATE) {
955            u.render_update_widgets.search_widget(target);
956        }
957
958        u.update_ext |= flags;
959    }
960
961    /// Schedules an [`UpdateOp`] that affects the `target` widget, ancestor widgets and window.
962    pub fn update_op(&self, op: UpdateOp, target: WidgetId) -> &Self {
963        match op {
964            UpdateOp::Update => self.update(target),
965            UpdateOp::Info => self.update_info(target),
966            UpdateOp::Layout => self.layout(target),
967            UpdateOp::Render => self.render(target),
968            UpdateOp::RenderUpdate => self.render_update(target),
969        }
970    }
971
972    /// Schedules an [`UpdateOp`] for the window only.
973    pub fn update_op_window(&self, op: UpdateOp, target: WindowId) -> &Self {
974        match op {
975            UpdateOp::Update => self.update_window(target),
976            UpdateOp::Info => self.update_info_window(target),
977            UpdateOp::Layout => self.layout_window(target),
978            UpdateOp::Render => self.render_window(target),
979            UpdateOp::RenderUpdate => self.render_update_window(target),
980        }
981    }
982
983    /// Schedules an update that affects the `target`.
984    ///
985    /// After the current update cycle ends a new update will happen that includes the `target` widget.
986    pub fn update(&self, target: WidgetId) -> &Self {
987        UpdatesTrace::log_update();
988        self.update_internal(target)
989    }
990    /// Implements `update` without `log_update`.
991    pub(crate) fn update_internal(&self, target: WidgetId) -> &UPDATES {
992        let mut u = UPDATES_SV.write();
993        u.update_ext.insert(UpdateFlags::UPDATE);
994        u.send_awake();
995        u.update_widgets.search_widget(target);
996        self
997    }
998
999    /// Schedules an update for the window only.
1000    pub fn update_window(&self, target: WindowId) -> &Self {
1001        let mut u = UPDATES_SV.write();
1002        u.update_ext.insert(UpdateFlags::UPDATE);
1003        u.send_awake();
1004        u.update_widgets.insert_window(target);
1005        self
1006    }
1007
1008    /// Schedules an update without specific window or widget target.
1009    pub fn update_app(&self) {
1010        let mut u = UPDATES_SV.write();
1011        u.update_ext.insert(UpdateFlags::UPDATE);
1012        u.send_awake();
1013    }
1014
1015    /// Schedules an info rebuild that affects the `target`.
1016    ///
1017    /// After the current update cycle ends a new update will happen that requests an info rebuild that includes the `target` widget.
1018    pub fn update_info(&self, target: WidgetId) -> &Self {
1019        UpdatesTrace::log_info();
1020        let mut u = UPDATES_SV.write();
1021        u.update_ext.insert(UpdateFlags::INFO);
1022        u.send_awake();
1023        u.info_widgets.search_widget(target);
1024        self
1025    }
1026
1027    /// Schedules an info rebuild for the window only.
1028    pub fn update_info_window(&self, target: WindowId) -> &Self {
1029        UpdatesTrace::log_info();
1030        let mut u = UPDATES_SV.write();
1031        u.update_ext.insert(UpdateFlags::INFO);
1032        u.send_awake();
1033        u.info_widgets.insert_window(target);
1034        self
1035    }
1036
1037    /// Schedules a layout update that affects the `target`.
1038    ///
1039    /// After the current update cycle ends and there are no more updates requested a layout pass is issued that includes the `target` widget.
1040    pub fn layout(&self, target: WidgetId) -> &Self {
1041        UpdatesTrace::log_layout();
1042        let mut u = UPDATES_SV.write();
1043        u.update_ext.insert(UpdateFlags::LAYOUT);
1044        u.send_awake();
1045        u.layout_widgets.search_widget(target);
1046        self
1047    }
1048
1049    /// Schedules a layout update for the window only.
1050    pub fn layout_window(&self, target: WindowId) -> &Self {
1051        UpdatesTrace::log_layout();
1052        let mut u = UPDATES_SV.write();
1053        u.update_ext.insert(UpdateFlags::LAYOUT);
1054        u.send_awake();
1055        u.layout_widgets.insert_window(target);
1056        self
1057    }
1058
1059    /// Schedules a full render that affects the `target`.
1060    ///
1061    /// After the current update cycle ends and there are no more updates or layouts requested a render pass is issued that
1062    /// includes the `target` widget.
1063    ///
1064    /// If no `target` is provided only the app extensions receive a render request.
1065    pub fn render(&self, target: WidgetId) -> &Self {
1066        UpdatesTrace::log_render();
1067        let mut u = UPDATES_SV.write();
1068        u.update_ext.insert(UpdateFlags::RENDER);
1069        u.send_awake();
1070        u.render_widgets.search_widget(target);
1071        self
1072    }
1073
1074    /// Schedules a new frame for the window only.
1075    pub fn render_window(&self, target: WindowId) -> &Self {
1076        UpdatesTrace::log_render();
1077        let mut u = UPDATES_SV.write();
1078        u.update_ext.insert(UpdateFlags::RENDER);
1079        u.send_awake();
1080        u.render_widgets.insert_window(target);
1081        self
1082    }
1083
1084    /// Schedules a render update that affects the `target`.
1085    ///
1086    /// After the current update cycle ends and there are no more updates or layouts requested a render pass is issued that
1087    /// includes the `target` widget marked for render update only. Note that if a full render was requested for another widget
1088    /// on the same window this request is upgraded to a full frame render.
1089    pub fn render_update(&self, target: WidgetId) -> &Self {
1090        UpdatesTrace::log_render();
1091        let mut u = UPDATES_SV.write();
1092        u.update_ext.insert(UpdateFlags::RENDER_UPDATE);
1093        u.send_awake();
1094        u.render_update_widgets.search_widget(target);
1095        self
1096    }
1097
1098    /// Schedules a render update for the window only.
1099    pub fn render_update_window(&self, target: WindowId) -> &Self {
1100        UpdatesTrace::log_render();
1101        let mut u = UPDATES_SV.write();
1102        u.update_ext.insert(UpdateFlags::RENDER_UPDATE);
1103        u.send_awake();
1104        u.render_update_widgets.insert_window(target);
1105        self
1106    }
1107
1108    /// Returns `true` is render or render update is requested for the window.
1109    pub fn is_pending_render(&self, window_id: WindowId) -> bool {
1110        let u = UPDATES_SV.read();
1111        u.render_widgets.enter_window(window_id) || u.render_update_widgets.enter_window(window_id)
1112    }
1113
1114    /// Schedule the `future` to run in the app context, in the *preview* track of the next update.
1115    ///
1116    /// This requests an app update. Each future awake also requests an app update and also runs in the *preview* track.
1117    ///
1118    /// Returns a handle that can be dropped to cancel execution.
1119    pub fn run<F: Future<Output = ()> + Send + 'static>(&self, future: impl IntoFuture<Output = (), IntoFuture = F>) -> OnUpdateHandle {
1120        let future = future.into_future();
1121        self.run_hn_once(async_hn_once!(|_| future.await))
1122    }
1123
1124    /// Schedule a handler to run once in the app context, in the *preview* track of the next update.
1125    ///
1126    /// The [`Handler`] can be any kind, including async handlers. If the handler is async and does not finish in
1127    /// one call it is scheduled to update in *preview* updates.
1128    ///
1129    /// Returns a handle that can be dropped to cancel execution.
1130    pub fn run_hn_once(&self, handler: Handler<UpdateArgs>) -> OnUpdateHandle {
1131        let mut u = UPDATES_SV.write();
1132        u.update_ext.insert(UpdateFlags::UPDATE);
1133        u.send_awake();
1134        Self::push_handler(u.pre_handlers.get_mut(), true, handler.into_once(), true)
1135    }
1136
1137    /// Create a preview update handler.
1138    ///
1139    /// The `handler` is called every time the app updates, just before the UI updates. It can be any of the non-async [`Handler`],
1140    /// use the [`hn!`] or [`hn_once!`] macros to declare the closure. You must avoid using async handlers because UI bound async
1141    /// tasks cause app updates to awake, so it is very easy to lock the app in a constant sequence of updates. You can use [`run`](Self::run)
1142    /// to start an async app context task.
1143    ///
1144    /// Returns an [`OnUpdateHandle`] that can be used to unsubscribe, you can also unsubscribe from inside the handler by calling
1145    /// [`APP_HANDLER.unsubscribe`].
1146    ///
1147    /// [`hn_once!`]: macro@crate::handler::hn_once
1148    /// [`hn!`]: macro@crate::handler::hn
1149    /// [`async_hn!`]: macro@crate::handler::async_hn
1150    /// [`APP_HANDLER.unsubscribe`]: crate::handler::APP_HANDLER::unsubscribe
1151    pub fn on_pre_update(&self, handler: Handler<UpdateArgs>) -> OnUpdateHandle {
1152        let u = UPDATES_SV.read();
1153        Self::push_handler(&mut u.pre_handlers.lock(), true, handler, false)
1154    }
1155
1156    /// Create an update handler.
1157    ///
1158    /// The `handler` is called every time the app updates, just after the UI updates. It can be any of the non-async [`Handler`],
1159    /// use the [`hn!`] or [`hn_once!`] macros to declare the closure. You must avoid using async handlers because UI bound async
1160    /// tasks cause app updates to awake, so it is very easy to lock the app in a constant sequence of updates. You can use [`run`](Self::run)
1161    /// to start an async app context task.
1162    ///
1163    /// Returns an [`OnUpdateHandle`] that can be used to unsubscribe, you can also unsubscribe from inside the handler by calling
1164    /// [`APP_HANDLER.unsubscribe`].
1165    ///
1166    /// [`hn_once!`]: macro@crate::handler::hn_once
1167    /// [`hn!`]: macro@crate::handler::hn
1168    /// [`async_hn!`]: macro@crate::handler::async_hn
1169    /// [`APP_HANDLER.unsubscribe`]: crate::handler::APP_HANDLER::unsubscribe
1170    pub fn on_update(&self, handler: Handler<UpdateArgs>) -> OnUpdateHandle {
1171        let u = UPDATES_SV.read();
1172        Self::push_handler(&mut u.pos_handlers.lock(), false, handler, false)
1173    }
1174
1175    /// Calls the closure once the current update is over.
1176    ///
1177    /// This is an alias for [`VARS::modify`].
1178    pub fn once_update(&self, debug_name: &'static str, u: impl FnOnce() + Send + 'static) {
1179        VARS.modify(debug_name, u);
1180    }
1181
1182    /// Calls the closure once the next update is over.
1183    ///
1184    /// Note that this requests an update, after the current update is over another one will process and at its end the closure is called.
1185    pub fn once_next_update(&self, debug_name: &'static str, u: impl FnOnce() + Send + 'static) {
1186        self.run_hn_once(hn_once!(|_| {
1187            UPDATES.once_update(debug_name, u);
1188        }))
1189        .perm();
1190    }
1191
1192    fn push_handler(
1193        entries: &mut Vec<UpdateHandler>,
1194        is_preview: bool,
1195        mut handler: Handler<UpdateArgs>,
1196        force_once: bool,
1197    ) -> OnUpdateHandle {
1198        let (handle_owner, handle) = OnUpdateHandle::new();
1199        entries.push(UpdateHandler {
1200            handle: handle_owner,
1201            count: 0,
1202            handler: Box::new(move |args, handle| {
1203                handler.app_event(handle.clone_boxed(), is_preview, args);
1204                if force_once {
1205                    handle.unsubscribe();
1206                }
1207            }),
1208        });
1209        handle
1210    }
1211
1212    pub(crate) fn on_pre_updates(&self) {
1213        let _s = tracing::trace_span!("UPDATES.on_pre_updates");
1214        let mut handlers = mem::take(UPDATES_SV.write().pre_handlers.get_mut());
1215        Self::retain_updates(&mut handlers);
1216
1217        let mut u = UPDATES_SV.write();
1218        handlers.append(u.pre_handlers.get_mut());
1219        *u.pre_handlers.get_mut() = handlers;
1220    }
1221
1222    pub(crate) fn on_updates(&self) {
1223        let _s = tracing::trace_span!("UPDATES.on_updates");
1224        let mut handlers = mem::take(UPDATES_SV.write().pos_handlers.get_mut());
1225        Self::retain_updates(&mut handlers);
1226
1227        let mut u = UPDATES_SV.write();
1228        handlers.append(u.pos_handlers.get_mut());
1229        *u.pos_handlers.get_mut() = handlers;
1230    }
1231
1232    fn retain_updates(handlers: &mut Vec<UpdateHandler>) {
1233        handlers.retain_mut(|e| {
1234            !e.handle.is_dropped() && {
1235                e.count = e.count.wrapping_add(1);
1236                (e.handler)(&UpdateArgs { count: e.count }, &e.handle.weak_handle());
1237                !e.handle.is_dropped()
1238            }
1239        });
1240    }
1241
1242    /// Returns (update_ext, update_widgets)
1243    pub(super) fn take_update(&self) -> (bool, WidgetUpdates) {
1244        let mut u = UPDATES_SV.write();
1245
1246        let ext = u.update_ext.contains(UpdateFlags::UPDATE);
1247        u.update_ext.remove(UpdateFlags::UPDATE);
1248
1249        (
1250            ext,
1251            WidgetUpdates {
1252                delivery_list: mem::take(&mut u.update_widgets),
1253            },
1254        )
1255    }
1256
1257    /// Returns (info_ext, info_widgets)
1258    pub(super) fn take_info(&self) -> (bool, InfoUpdates) {
1259        let mut u = UPDATES_SV.write();
1260
1261        let ext = u.update_ext.contains(UpdateFlags::INFO);
1262        u.update_ext.remove(UpdateFlags::INFO);
1263
1264        (
1265            ext,
1266            InfoUpdates {
1267                delivery_list: mem::take(&mut u.info_widgets),
1268            },
1269        )
1270    }
1271
1272    /// Returns (layout_ext, layout_widgets)
1273    pub(super) fn take_layout(&self) -> (bool, LayoutUpdates) {
1274        let mut u = UPDATES_SV.write();
1275
1276        let ext = u.update_ext.contains(UpdateFlags::LAYOUT);
1277        u.update_ext.remove(UpdateFlags::LAYOUT);
1278
1279        (
1280            ext,
1281            LayoutUpdates {
1282                delivery_list: mem::take(&mut u.layout_widgets),
1283            },
1284        )
1285    }
1286
1287    /// Returns (render_ext, render_widgets, render_update_widgets)
1288    pub(super) fn take_render(&self) -> (bool, RenderUpdates, RenderUpdates) {
1289        let mut u = UPDATES_SV.write();
1290
1291        let ext = u.update_ext.intersects(UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE);
1292        u.update_ext.remove(UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE);
1293
1294        (
1295            ext,
1296            RenderUpdates {
1297                delivery_list: mem::take(&mut u.render_widgets),
1298            },
1299            RenderUpdates {
1300                delivery_list: mem::take(&mut u.render_update_widgets),
1301            },
1302        )
1303    }
1304}
1305
1306app_local! {
1307    static UPDATES_SV: UpdatesService = UpdatesService::new();
1308}
1309struct UpdatesService {
1310    event_sender: Option<AppEventSender>,
1311
1312    update_ext: UpdateFlags,
1313    update_widgets: UpdateDeliveryList,
1314    info_widgets: UpdateDeliveryList,
1315    layout_widgets: UpdateDeliveryList,
1316    render_widgets: UpdateDeliveryList,
1317    render_update_widgets: UpdateDeliveryList,
1318
1319    pre_handlers: Mutex<Vec<UpdateHandler>>,
1320    pos_handlers: Mutex<Vec<UpdateHandler>>,
1321
1322    app_is_awake: bool,
1323    awake_pending: bool,
1324}
1325impl UpdatesService {
1326    fn new() -> Self {
1327        Self {
1328            event_sender: None,
1329            update_ext: UpdateFlags::empty(),
1330            update_widgets: UpdateDeliveryList::new(),
1331            info_widgets: UpdateDeliveryList::new(),
1332            layout_widgets: UpdateDeliveryList::new(),
1333            render_widgets: UpdateDeliveryList::new(),
1334            render_update_widgets: UpdateDeliveryList::new(),
1335
1336            pre_handlers: Mutex::new(vec![]),
1337            pos_handlers: Mutex::new(vec![]),
1338
1339            app_is_awake: false,
1340            awake_pending: false,
1341        }
1342    }
1343
1344    fn send_awake(&mut self) {
1345        if !self.app_is_awake && !self.awake_pending {
1346            self.awake_pending = true;
1347            match self.event_sender.as_ref() {
1348                Some(s) => {
1349                    if let Err(ChannelError::Disconnected { .. }) = s.send_update_app() {
1350                        tracing::debug!("no app connected to update");
1351                    }
1352                }
1353                None => {
1354                    tracing::debug!("no app connected yet to update");
1355                }
1356            }
1357        }
1358    }
1359
1360    fn app_awake(&mut self, wake: bool) {
1361        self.awake_pending = false;
1362        self.app_is_awake = wake;
1363    }
1364}
1365
1366/// Updates that must be reacted by an app owner.
1367///
1368/// This type is public only for testing, it is the return type for test methods of [`WINDOW`].
1369#[non_exhaustive]
1370#[derive(Default)]
1371pub struct ContextUpdates {
1372    /// Update requested.
1373    ///
1374    /// When this is `true`, [`update_widgets`](Self::update_widgets)
1375    /// may contain widgets, if not then only app extensions must update.
1376    pub update: bool,
1377
1378    /// Info rebuild requested.
1379    ///
1380    /// When this is `true`, [`info_widgets`](Self::info_widgets)
1381    /// may contain widgets, if not then only app extensions must update.
1382    pub info: bool,
1383
1384    /// Layout requested.
1385    ///
1386    /// When this is `true`, [`layout_widgets`](Self::layout_widgets)
1387    /// may contain widgets, if not then only app extensions must update.
1388    pub layout: bool,
1389
1390    /// Render requested.
1391    ///
1392    /// When this is `true`, [`render_widgets`](Self::render_widgets) or [`render_update_widgets`](Self::render_update_widgets)
1393    /// may contain widgets, if not then only app extensions must update.
1394    pub render: bool,
1395
1396    /// Update targets.
1397    ///
1398    /// When this is not empty [`update`](Self::update) is `true`.
1399    pub update_widgets: WidgetUpdates,
1400
1401    /// Info rebuild targets.
1402    ///
1403    /// When this is not empty [`info`](Self::info) is `true`.
1404    pub info_widgets: InfoUpdates,
1405
1406    /// Layout targets.
1407    ///
1408    /// When this is not empty [`layout`](Self::layout) is `true`.
1409    pub layout_widgets: LayoutUpdates,
1410
1411    /// Full render targets.
1412    ///
1413    /// When this is not empty [`render`](Self::render) is `true`.
1414    pub render_widgets: RenderUpdates,
1415
1416    /// Render update targets.
1417    ///
1418    /// When this is not empty [`render`](Self::render) is `true`.
1419    pub render_update_widgets: RenderUpdates,
1420}
1421
1422impl fmt::Debug for ContextUpdates {
1423    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1424        if f.alternate() {
1425            f.debug_struct("ContextUpdates")
1426                .field("update", &self.update)
1427                .field("info", &self.info)
1428                .field("layout", &self.layout)
1429                .field("render", &self.render)
1430                .field("update_widgets", &self.update_widgets)
1431                .field("info_widgets", &self.info_widgets)
1432                .field("layout_widgets", &self.layout_widgets)
1433                .field("render_widgets", &self.render_widgets)
1434                .field("render_update_widgets", &self.render_update_widgets)
1435                .finish()
1436        } else {
1437            write!(f, "ContextUpdates: ")?;
1438            let mut sep = "";
1439            if self.update {
1440                write!(f, "{sep}update")?;
1441                sep = ", ";
1442            }
1443            if self.info {
1444                write!(f, "{sep}info")?;
1445                sep = ", ";
1446            }
1447            if self.layout {
1448                write!(f, "{sep}layout")?;
1449                sep = ", ";
1450            }
1451            if self.render {
1452                write!(f, "{sep}render")?;
1453                sep = ", ";
1454            }
1455            if sep.is_empty() {
1456                write!(f, "<none>")?;
1457            }
1458            Ok(())
1459        }
1460    }
1461}
1462impl ContextUpdates {
1463    /// If has events, update, layout or render was requested.
1464    pub fn has_updates(&self) -> bool {
1465        self.update || self.info || self.layout || self.render
1466    }
1467}
1468impl std::ops::BitOrAssign for ContextUpdates {
1469    fn bitor_assign(&mut self, rhs: Self) {
1470        self.update |= rhs.update;
1471        self.update_widgets.extend(rhs.update_widgets);
1472        self.info |= rhs.info;
1473        self.info_widgets.extend(rhs.info_widgets);
1474        self.layout |= rhs.layout;
1475        self.layout_widgets.extend(rhs.layout_widgets);
1476        self.render |= rhs.render;
1477        self.render_widgets.extend(rhs.render_widgets);
1478        self.render_update_widgets.extend(rhs.render_update_widgets);
1479    }
1480}
1481impl std::ops::BitOr for ContextUpdates {
1482    type Output = Self;
1483
1484    fn bitor(mut self, rhs: Self) -> Self {
1485        self |= rhs;
1486        self
1487    }
1488}
1489
1490bitflags::bitflags! {
1491    #[derive(Clone, Copy, Debug, bytemuck::NoUninit)]
1492    #[repr(transparent)]
1493    pub(crate) struct UpdateFlags: u8 {
1494        const REINIT = 0b1000_0000;
1495        const INFO = 0b0001_0000;
1496        const UPDATE = 0b0000_0001;
1497        const LAYOUT = 0b0000_0010;
1498        const RENDER = 0b0000_0100;
1499        const RENDER_UPDATE = 0b0000_1000;
1500    }
1501}
1502
1503/// Represents an [`on_pre_update`](UPDATES::on_pre_update) or [`on_update`](UPDATES::on_update) handler.
1504///
1505/// Drop all clones of this handle to drop the binding, or call [`perm`](Self::perm) to drop the handle
1506/// but keep the handler alive for the duration of the app.
1507#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1508#[repr(transparent)]
1509#[must_use = "dropping the handle unsubscribes update handler"]
1510pub struct OnUpdateHandle(Handle<()>);
1511impl OnUpdateHandle {
1512    fn new() -> (HandleOwner<()>, OnUpdateHandle) {
1513        let (owner, handle) = Handle::new(());
1514        (owner, OnUpdateHandle(handle))
1515    }
1516
1517    /// Create a handle to nothing, the handle always in the *unsubscribed* state.
1518    ///
1519    /// Note that `Option<OnUpdateHandle>` takes up the same space as `OnUpdateHandle` and avoids an allocation.
1520    pub fn dummy() -> Self {
1521        OnUpdateHandle(Handle::dummy(()))
1522    }
1523
1524    /// Drops the handle but does **not** unsubscribe.
1525    ///
1526    /// The handler stays in memory for the duration of the app or until another handle calls [`unsubscribe`](Self::unsubscribe)
1527    pub fn perm(self) {
1528        self.0.perm();
1529    }
1530
1531    /// If another handle has called [`perm`](Self::perm).
1532    ///
1533    /// If `true` the handler will stay active until the app exits, unless [`unsubscribe`](Self::unsubscribe) is called.
1534    pub fn is_permanent(&self) -> bool {
1535        self.0.is_permanent()
1536    }
1537
1538    /// Drops the handle and forces the handler to drop.
1539    pub fn unsubscribe(self) {
1540        self.0.force_drop()
1541    }
1542
1543    /// If another handle has called [`unsubscribe`](Self::unsubscribe).
1544    ///
1545    /// The handler is already dropped or will be dropped in the next app update, this is irreversible.
1546    pub fn is_unsubscribed(&self) -> bool {
1547        self.0.is_dropped()
1548    }
1549
1550    /// Create a weak handle.
1551    pub fn downgrade(&self) -> WeakOnUpdateHandle {
1552        WeakOnUpdateHandle(self.0.downgrade())
1553    }
1554}
1555
1556/// Weak [`OnUpdateHandle`].
1557#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)]
1558pub struct WeakOnUpdateHandle(WeakHandle<()>);
1559impl WeakOnUpdateHandle {
1560    /// New weak handle that does not upgrade.
1561    pub fn new() -> Self {
1562        Self(WeakHandle::new())
1563    }
1564
1565    /// Gets the strong handle if it is still subscribed.
1566    pub fn upgrade(&self) -> Option<OnUpdateHandle> {
1567        self.0.upgrade().map(OnUpdateHandle)
1568    }
1569}
1570
1571/// Identify node and app-extension operations that can be requested.
1572#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1573pub enum UpdateOp {
1574    /// Updates the target.
1575    ///
1576    /// Causes [`UPDATES.on_pre_update`] and [`UPDATES.on_update`].
1577    ///
1578    /// Causes [`UiNode::update`] or [`UiNodeOp::Update`] for the target widget and all ancestors.
1579    ///
1580    /// [`UiNodeOp::Update`]: crate::widget::node::UiNodeOp::Update
1581    /// [`UPDATES.on_pre_update`]: UPDATES::on_pre_update
1582    /// [`UPDATES.on_update`]: UPDATES::on_update
1583    Update,
1584    /// Rebuilds info for the target.
1585    ///
1586    /// Causes [`UiNode::info`] or [`UiNodeOp::Info`] for the target widget and all ancestors.
1587    ///
1588    /// [`Update`]: UpdateOp::Render
1589    /// [`UiNodeOp::Info`]: crate::widget::node::UiNodeOp::Info
1590    Info,
1591    /// Layouts the target.
1592    ///
1593    /// Causes an [`UiNode::layout`] or [`UiNodeOp::Layout`] for the target widget and all ancestors.
1594    ///
1595    /// [`UiNodeOp::Layout`]: crate::widget::node::UiNodeOp::Layout
1596    Layout,
1597    /// Render the target.
1598    ///
1599    /// Causes [`UiNode::render`] or [`UiNodeOp::Render`] for the target widget and all ancestors.
1600    ///
1601    /// [`UiNodeOp::Render`]: crate::widget::node::UiNodeOp::Render
1602    Render,
1603    /// Update frame bindings of the target.
1604    ///
1605    /// Causes [`UiNode::render_update`] or [`UiNodeOp::RenderUpdate`] for the target widget and all ancestors.
1606    ///
1607    /// This OP is upgraded to [`Render`] if any other widget requests a full render in the same window.
1608    ///
1609    /// [`Render`]: UpdateOp::Render
1610    /// [`UiNodeOp::RenderUpdate`]: crate::widget::node::UiNodeOp::RenderUpdate
1611    RenderUpdate,
1612}
1613
1614/// Arguments for an [`on_pre_update`](UPDATES::on_pre_update), [`on_update`](UPDATES::on_update) or [`run`](UPDATES::run) handler.
1615#[derive(Debug, Clone, Copy)]
1616#[non_exhaustive]
1617pub struct UpdateArgs {
1618    /// Number of times the handler was called.
1619    pub count: usize,
1620}
1621
1622struct UpdateHandler {
1623    handle: HandleOwner<()>,
1624    count: usize,
1625    handler: Box<dyn FnMut(&UpdateArgs, &dyn AppWeakHandle) + Send>,
1626}