zng_app/
update.rs

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