Skip to main content

zng_app/
update.rs

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