zng_app/
update.rs

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