1use 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::{BoxedUiNode, UiNode},
25    },
26    window::{WINDOW, WindowId},
27};
28
29pub 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    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    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    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    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    pub fn insert_window(&mut self, id: WindowId) {
115        self.windows.insert(id);
116        self.search_root = true;
117    }
118
119    pub fn search_all(&mut self) {
121        self.search = self.subscribers.to_set();
122    }
123
124    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    pub fn has_pending_search(&mut self) -> bool {
133        self.search_root || !self.search.is_empty()
134    }
135
136    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    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    pub fn enter_window(&self, window_id: WindowId) -> bool {
182        self.windows.contains(&window_id)
183    }
184
185    pub fn enter_widget(&self, widget_id: WidgetId) -> bool {
187        self.widgets.contains(&widget_id)
188    }
189
190    pub fn windows(&self) -> &IdSet<WindowId> {
192        &self.windows
193    }
194
195    pub fn widgets(&self) -> &IdSet<WidgetId> {
197        &self.widgets
198    }
199
200    #[must_use = "use `search_all` to request search"]
202    pub fn search_widgets(&mut self) -> &IdSet<WidgetId> {
203        &self.search
204    }
205
206    #[must_use = "use `search_widget` to request search"]
208    pub fn search_root(&mut self) -> bool {
209        self.search_root
210    }
211}
212
213pub trait WidgetPathProvider {
215    type WidgetIter<'s>: Iterator<Item = WidgetId>
217    where
218        Self: 's;
219
220    fn window_id(&self) -> WindowId;
222    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
262pub trait UpdateSubscribers: Send + Sync + 'static {
264    fn contains(&self, widget_id: WidgetId) -> bool;
266    fn to_set(&self) -> IdSet<WidgetId>;
268}
269
270pub struct EventUpdate {
272    pub(crate) event: AnyEvent,
273    pub(crate) args: Box<dyn AnyEventArgs>,
274    pub(crate) delivery_list: UpdateDeliveryList,
275    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    pub fn event(&self) -> AnyEvent {
282        self.event
283    }
284
285    pub fn delivery_list(&self) -> &UpdateDeliveryList {
287        &self.delivery_list
288    }
289
290    pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
294        &mut self.delivery_list
295    }
296
297    pub fn args(&self) -> &dyn AnyEventArgs {
299        &*self.args
300    }
301
302    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    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    pub(crate) fn push_once_action(&mut self, action: Box<dyn FnOnce(&EventUpdate) + Send>, is_preview: bool) {
331        if is_preview {
332            self.pre_actions.get_mut().push(action);
333        } else {
334            self.pos_actions.get_mut().push(action);
335        }
336    }
337
338    pub(crate) fn call_pre_actions(&mut self) {
339        let _s = tracing::trace_span!("call_pre_actions");
340        let actions = mem::take(self.pre_actions.get_mut());
341        for action in actions {
342            action(self)
343        }
344    }
345
346    pub(crate) fn call_pos_actions(&mut self) {
347        let _s = tracing::trace_span!("call_pos_actions");
348        let actions = mem::take(self.pos_actions.get_mut());
349        for action in actions {
350            action(self)
351        }
352    }
353}
354impl fmt::Debug for EventUpdate {
355    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356        f.debug_struct("EventUpdate")
357            .field("event", &self.event)
358            .field("args", &self.args)
359            .field("delivery_list", &self.delivery_list)
360            .finish_non_exhaustive()
361    }
362}
363
364#[derive(Debug, Default)]
366pub struct InfoUpdates {
367    delivery_list: UpdateDeliveryList,
368}
369impl InfoUpdates {
370    pub fn new(delivery_list: UpdateDeliveryList) -> Self {
372        Self { delivery_list }
373    }
374
375    pub fn delivery_list(&self) -> &UpdateDeliveryList {
377        &self.delivery_list
378    }
379
380    pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
382        &mut self.delivery_list
383    }
384
385    pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
387    where
388        H: FnOnce() -> R,
389    {
390        if self.delivery_list.enter_window(window_id) {
391            Some(handle())
392        } else {
393            None
394        }
395    }
396
397    pub fn extend(&mut self, other: InfoUpdates) {
399        self.delivery_list.extend_unchecked(other.delivery_list)
400    }
401}
402
403#[derive(Debug, Default)]
405pub struct WidgetUpdates {
406    pub(crate) delivery_list: UpdateDeliveryList,
407}
408impl WidgetUpdates {
409    pub fn new(delivery_list: UpdateDeliveryList) -> Self {
411        Self { delivery_list }
412    }
413
414    pub fn delivery_list(&self) -> &UpdateDeliveryList {
416        &self.delivery_list
417    }
418
419    pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
421        &mut self.delivery_list
422    }
423
424    pub fn with_window<H, R>(&self, handle: H) -> Option<R>
426    where
427        H: FnOnce() -> R,
428    {
429        if self.delivery_list.enter_window(WINDOW.id()) {
430            Some(handle())
431        } else {
432            None
433        }
434    }
435
436    pub fn with_widget<H, R>(&self, handle: H) -> Option<R>
438    where
439        H: FnOnce() -> R,
440    {
441        if WIDGET.take_update(UpdateFlags::UPDATE) || self.delivery_list.enter_widget(WIDGET.id()) {
442            Some(handle())
443        } else {
444            None
445        }
446    }
447
448    pub fn extend(&mut self, other: WidgetUpdates) {
450        self.delivery_list.extend_unchecked(other.delivery_list)
451    }
452}
453
454#[derive(Debug, Default)]
456pub struct LayoutUpdates {
457    pub(crate) delivery_list: UpdateDeliveryList,
458}
459impl LayoutUpdates {
460    pub fn new(delivery_list: UpdateDeliveryList) -> Self {
462        Self { delivery_list }
463    }
464
465    pub fn delivery_list(&self) -> &UpdateDeliveryList {
467        &self.delivery_list
468    }
469
470    pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
472        &mut self.delivery_list
473    }
474
475    pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
477    where
478        H: FnOnce() -> R,
479    {
480        if self.delivery_list.enter_window(window_id) {
481            Some(handle())
482        } else {
483            None
484        }
485    }
486
487    pub fn extend(&mut self, other: LayoutUpdates) {
489        self.delivery_list.extend_unchecked(other.delivery_list)
490    }
491}
492
493#[derive(Debug, Default)]
495pub struct RenderUpdates {
496    delivery_list: UpdateDeliveryList,
497}
498impl RenderUpdates {
499    pub fn new(delivery_list: UpdateDeliveryList) -> Self {
501        Self { delivery_list }
502    }
503
504    pub fn delivery_list(&self) -> &UpdateDeliveryList {
506        &self.delivery_list
507    }
508
509    pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
511        &mut self.delivery_list
512    }
513
514    pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
516    where
517        H: FnOnce() -> R,
518    {
519        if self.delivery_list.enter_window(window_id) {
520            Some(handle())
521        } else {
522            None
523        }
524    }
525
526    pub fn extend(&mut self, other: RenderUpdates) {
528        self.delivery_list.extend_unchecked(other.delivery_list)
529    }
530}
531
532pub trait UpdatesTraceUiNodeExt: UiNode {
536    fn instrument<S: Into<String>>(self, tag: S) -> BoxedUiNode
538    where
539        Self: Sized;
540}
541impl<U: UiNode> UpdatesTraceUiNodeExt for U {
542    fn instrument<S: Into<String>>(self, tag: S) -> BoxedUiNode {
543        let tag = tag.into();
544        self.trace(move |op| UpdatesTrace::custom_span(&tag, op.mtd_name()))
545    }
546}
547
548pub fn updates_trace_span(tag: &'static str) -> tracing::span::EnteredSpan {
552    UpdatesTrace::custom_span(tag, "")
553}
554
555pub fn updates_trace_event(tag: &str) {
559    UpdatesTrace::log_custom(tag)
560}
561
562pub(crate) struct UpdatesTrace {
563    context: Mutex<UpdateContext>,
564    trace: Arc<Mutex<Vec<UpdateTrace>>>,
565
566    widgets_stack: Mutex<Vec<(WidgetId, String)>>,
567    node_parents_stack: Mutex<Vec<String>>,
568    tags_stack: Mutex<Vec<String>>,
569}
570impl tracing::subscriber::Subscriber for UpdatesTrace {
571    fn enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
572        metadata.target() == Self::UPDATES_TARGET
573    }
574
575    fn new_span(&self, span: &tracing::span::Attributes<'_>) -> tracing::span::Id {
576        match span.metadata().name() {
577            "property" | "intrinsic" => {
578                let name = visit_str(|v| span.record(v), "name");
579                let mut ctx = self.context.lock();
580
581                if let Some(p) = ctx.node_parent.replace(name) {
582                    self.node_parents_stack.lock().push(p);
583                }
584                if let Some(p) = ctx.tag.replace(String::new()) {
585                    self.tags_stack.lock().push(p);
586                }
587
588                tracing::span::Id::from_u64(1)
589            }
590            "widget" => {
591                let id = visit_u64(|v| span.record(v), "raw_id").unwrap();
592                if id == 0 {
593                    panic!()
594                }
595                let id = WidgetId::from_raw(id);
596
597                let name = visit_str(|v| span.record(v), "name");
598
599                let mut ctx = self.context.lock();
600                if let Some(p) = ctx.widget.replace((id, name)) {
601                    self.widgets_stack.lock().push(p);
602                }
603
604                if let Some(p) = ctx.node_parent.replace(String::new()) {
605                    self.node_parents_stack.lock().push(p);
606                }
607
608                if let Some(p) = ctx.tag.replace(String::new()) {
609                    self.tags_stack.lock().push(p);
610                }
611
612                tracing::span::Id::from_u64(2)
613            }
614            "Window" => {
615                let id = visit_u64(|v| span.record(v), "raw_id").unwrap() as u32;
616                if id == 0 {
617                    panic!()
618                }
619                let id = WindowId::from_raw(id);
620
621                let mut ctx = self.context.lock();
622                ctx.window_id = Some(id);
623
624                if let Some(p) = ctx.tag.replace(String::new()) {
625                    self.tags_stack.lock().push(p);
626                }
627
628                tracing::span::Id::from_u64(3)
629            }
630            "AppExtension" => {
631                let name = visit_str(|v| span.record(v), "name");
632
633                let mut ctx = self.context.lock();
634                ctx.app_extension = Some(name);
635
636                if let Some(p) = ctx.tag.replace(String::new()) {
637                    self.tags_stack.lock().push(p);
638                }
639
640                tracing::span::Id::from_u64(4)
641            }
642            "tag" => {
643                let tag = visit_str(|v| span.record(v), "tag");
644                let mut ctx = self.context.lock();
645                if let Some(p) = ctx.tag.replace(tag) {
646                    self.tags_stack.lock().push(p);
647                }
648                tracing::span::Id::from_u64(5)
649            }
650            _ => tracing::span::Id::from_u64(u64::MAX),
651        }
652    }
653
654    fn record(&self, _span: &tracing::span::Id, _values: &tracing::span::Record<'_>) {}
655
656    fn record_follows_from(&self, _span: &tracing::span::Id, _follows: &tracing::span::Id) {}
657
658    fn event(&self, event: &tracing::Event<'_>) {
659        let action = match visit_str(|v| event.record(v), "kind").as_str() {
660            "var" => UpdateAction::Var {
661                type_name: visit_str(|v| event.record(v), "type_name"),
662            },
663            "event" => UpdateAction::Event {
664                type_name: visit_str(|v| event.record(v), "type_name"),
665            },
666            "request" => UpdateAction::Update,
667            "info" => UpdateAction::Info,
668            "layout" => UpdateAction::Layout,
669            "render" => UpdateAction::Render,
670            "custom" => UpdateAction::Custom {
671                tag: visit_str(|v| event.record(v), "tag"),
672            },
673            _ => return,
674        };
675
676        let ctx = self.context.lock().clone();
677        let entry = UpdateTrace { ctx, action };
682        self.trace.lock().push(entry);
683    }
684
685    fn enter(&self, _span: &tracing::span::Id) {}
686
687    fn exit(&self, span: &tracing::span::Id) {
688        let mut ctx = self.context.lock();
689        if span == &tracing::span::Id::from_u64(1) {
690            ctx.node_parent = self.node_parents_stack.lock().pop();
691            ctx.tag = self.tags_stack.lock().pop();
692        } else if span == &tracing::span::Id::from_u64(2) {
693            ctx.widget = self.widgets_stack.lock().pop();
694            ctx.node_parent = self.node_parents_stack.lock().pop();
695            ctx.tag = self.tags_stack.lock().pop();
696        } else if span == &tracing::span::Id::from_u64(3) {
697            ctx.window_id = None;
698            ctx.tag = self.tags_stack.lock().pop();
699        } else if span == &tracing::span::Id::from_u64(4) {
700            ctx.app_extension = None;
701            ctx.tag = self.tags_stack.lock().pop();
702        } else if span == &tracing::span::Id::from_u64(5) {
703            ctx.tag = self.tags_stack.lock().pop();
704        }
705    }
706}
707static UPDATES_TRACE_ENABLED: AtomicBool = AtomicBool::new(false);
708impl UpdatesTrace {
709    const UPDATES_TARGET: &'static str = "zng-updates";
710
711    fn new() -> Self {
712        UpdatesTrace {
713            context: Mutex::new(UpdateContext::default()),
714            trace: Arc::new(Mutex::new(Vec::with_capacity(100))),
715            widgets_stack: Mutex::new(Vec::with_capacity(100)),
716            node_parents_stack: Mutex::new(Vec::with_capacity(100)),
717            tags_stack: Mutex::new(Vec::new()),
718        }
719    }
720
721    #[inline(always)]
723    pub fn is_tracing() -> bool {
724        UPDATES_TRACE_ENABLED.load(atomic::Ordering::Relaxed)
725    }
726
727    pub fn extension_span<E: AppExtension>(ext_mtd: &'static str) -> tracing::span::EnteredSpan {
729        if Self::is_tracing() {
730            tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "AppExtension", name = pretty_type_name::pretty_type_name::<E>(), %ext_mtd).entered()
731        } else {
732            tracing::span::Span::none().entered()
733        }
734    }
735
736    pub fn window_span(id: WindowId) -> tracing::span::EnteredSpan {
738        if Self::is_tracing() {
739            tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "Window", %id, raw_id = id.get() as u64).entered()
740        } else {
741            tracing::span::Span::none().entered()
742        }
743    }
744
745    #[cfg(feature = "trace_widget")]
747    pub fn widget_span(id: WidgetId, name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
748        if Self::is_tracing() {
749            tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "widget", %id, raw_id = id.get(), name, %node_mtd).entered()
750        } else {
751            tracing::span::Span::none().entered()
752        }
753    }
754
755    #[cfg(feature = "trace_wgt_item")]
757    pub fn property_span(name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
758        if Self::is_tracing() {
759            tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "property", name, %node_mtd).entered()
760        } else {
761            tracing::span::Span::none().entered()
762        }
763    }
764
765    #[cfg(feature = "trace_wgt_item")]
767    pub fn intrinsic_span(name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
768        if Self::is_tracing() {
769            tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "intrinsic", name, %node_mtd).entered()
770        } else {
771            tracing::span::Span::none().entered()
772        }
773    }
774
775    pub fn custom_span(name: &str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
777        if Self::is_tracing() {
778            tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "tag", %name, %node_mtd).entered()
779        } else {
780            tracing::Span::none().entered()
781        }
782    }
783
784    pub fn log_update() {
786        if Self::is_tracing() {
787            tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
788                kind = "update"
789            });
790        }
791    }
792
793    pub fn log_info() {
795        if Self::is_tracing() {
796            tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
797                kind = "info"
798            });
799        }
800    }
801
802    pub fn log_layout() {
804        if Self::is_tracing() {
805            tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
806                kind = "layout"
807            });
808        }
809    }
810
811    pub fn log_render() {
813        if Self::is_tracing() {
814            tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
815                kind = "render"
816            });
817        }
818    }
819
820    pub fn log_custom(tag: &str) {
822        if Self::is_tracing() {
823            tracing::event!(
824                target: UpdatesTrace::UPDATES_TARGET,
825                tracing::Level::TRACE,
826                { kind = "custom", %tag }
827            );
828        }
829    }
830
831    pub fn log_var(type_name: &str) {
833        if Self::is_tracing() {
834            tracing::event!(
835                target: UpdatesTrace::UPDATES_TARGET,
836                tracing::Level::TRACE,
837                { kind = "var", type_name = pretty_type_name::pretty_type_name_str(type_name) }
838            );
839        }
840    }
841
842    pub fn log_event(event: AnyEvent) {
844        if Self::is_tracing() {
845            tracing::event!(
846                target: UpdatesTrace::UPDATES_TARGET,
847                tracing::Level::TRACE,
848                { kind = "event", type_name = event.name() }
849            );
850        }
851    }
852
853    pub fn collect_trace<R>(trace: &mut Vec<UpdateTrace>, action: impl FnOnce() -> R) -> R {
855        let trace_enabled = UPDATES_TRACE_ENABLED.swap(true, atomic::Ordering::Relaxed);
856
857        let tracer = UpdatesTrace::new();
858        let result = Arc::clone(&tracer.trace);
859        let r = tracing::subscriber::with_default(tracer, action);
860        trace.extend(Arc::try_unwrap(result).unwrap().into_inner());
861
862        UPDATES_TRACE_ENABLED.store(trace_enabled, atomic::Ordering::Relaxed);
863
864        r
865    }
866
867    pub fn format_trace(trace: Vec<UpdateTrace>) -> String {
869        let mut frequencies = HashMap::with_capacity(50);
870        for t in trace {
871            match frequencies.entry(t) {
872                hash_map::Entry::Vacant(e) => {
873                    e.insert(1);
874                }
875                hash_map::Entry::Occupied(mut e) => {
876                    *e.get_mut() += 1;
877                }
878            }
879        }
880        let mut frequencies: Vec<_> = frequencies.into_iter().collect();
881        frequencies.sort_by_key(|(_, c)| -c);
882
883        let mut trace = String::new();
884        for (t, c) in frequencies.into_iter().take(20) {
885            use std::fmt::Write;
886            let _ = writeln!(&mut trace, "{t} ({c} times)");
887        }
888        trace
889    }
890}
891#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
892struct UpdateContext {
893    app_extension: Option<String>,
894    window_id: Option<WindowId>,
895    widget: Option<(WidgetId, String)>,
896    node_parent: Option<String>,
897    tag: Option<String>,
898}
899impl fmt::Display for UpdateContext {
900    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
901        if let Some(e) = &self.app_extension {
902            write!(f, "{}", e.rsplit("::").next().unwrap())?;
903        } else {
904            write!(f, "<unknown>")?;
905        }
906        if let Some(w) = self.window_id {
907            write!(f, "//{w}")?;
908        }
909        if let Some((id, name)) = &self.widget {
910            write!(f, "/../{name}#{id}")?;
911        }
912        if let Some(p) = &self.node_parent {
913            if !p.is_empty() {
914                write!(f, "//{p}")?;
915            }
916        }
917        if let Some(t) = &self.tag {
918            if !t.is_empty() {
919                write!(f, "//{t}")?;
920            }
921        }
922        Ok(())
923    }
924}
925
926#[derive(Debug, PartialEq, Eq, Hash)]
927pub(crate) struct UpdateTrace {
928    ctx: UpdateContext,
929    action: UpdateAction,
930}
931impl fmt::Display for UpdateTrace {
932    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
933        write!(f, "{} {}", self.ctx, self.action)
934    }
935}
936#[derive(Debug, PartialEq, Eq, Hash)]
937enum UpdateAction {
938    Info,
939    Update,
940    Layout,
941    Render,
942    Var { type_name: String },
943    Event { type_name: String },
944    Custom { tag: String },
945}
946impl fmt::Display for UpdateAction {
947    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
948        match self {
949            UpdateAction::Info => write!(f, "info"),
950            UpdateAction::Update => write!(f, "update"),
951            UpdateAction::Layout => write!(f, "layout"),
952            UpdateAction::Render => write!(f, "render"),
953            UpdateAction::Var { type_name } => write!(f, "update var of type {type_name}"),
954            UpdateAction::Event { type_name } => write!(f, "update event {type_name}"),
955            UpdateAction::Custom { tag } => write!(f, "{tag}"),
956        }
957    }
958}
959
960fn visit_str(record: impl FnOnce(&mut dyn tracing::field::Visit), name: &str) -> String {
961    struct Visitor<'a> {
962        name: &'a str,
963        result: String,
964    }
965    impl tracing::field::Visit for Visitor<'_> {
966        fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
967            if field.name() == self.name {
968                self.result = format!("{value:?}");
969            }
970        }
971        fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
972            if field.name() == self.name {
973                value.clone_into(&mut self.result);
974            }
975        }
976    }
977
978    let mut visitor = Visitor {
979        name,
980        result: String::new(),
981    };
982    record(&mut visitor);
983    visitor.result
984}
985fn visit_u64(record: impl FnOnce(&mut dyn tracing::field::Visit), name: &str) -> Option<u64> {
986    struct Visitor<'a> {
987        name: &'a str,
988        result: Option<u64>,
989    }
990    impl tracing::field::Visit for Visitor<'_> {
991        fn record_debug(&mut self, _field: &tracing::field::Field, _value: &dyn std::fmt::Debug) {}
992        fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
993            if field.name() == self.name {
994                self.result = Some(value)
995            }
996        }
997    }
998
999    let mut visitor = Visitor { name, result: None };
1000    record(&mut visitor);
1001    visitor.result
1002}
1003
1004pub struct UPDATES;
1006impl UPDATES {
1007    pub(crate) fn init(&self, event_sender: AppEventSender) {
1008        UPDATES_SV.write().event_sender = Some(event_sender);
1009    }
1010
1011    #[must_use]
1012    #[cfg(any(test, doc, feature = "test_util"))]
1013    pub(crate) fn apply(&self) -> ContextUpdates {
1014        self.apply_updates() | self.apply_info() | self.apply_layout_render()
1015    }
1016
1017    #[must_use]
1018    pub(crate) fn apply_updates(&self) -> ContextUpdates {
1019        let events = EVENTS.apply_updates();
1020        VARS_APP.apply_updates();
1021
1022        let (update, update_widgets) = UPDATES.take_update();
1023
1024        ContextUpdates {
1025            events,
1026            update,
1027            update_widgets,
1028            info: false,
1029            info_widgets: InfoUpdates::default(),
1030            layout: false,
1031            layout_widgets: LayoutUpdates::default(),
1032            render: false,
1033            render_widgets: RenderUpdates::default(),
1034            render_update_widgets: RenderUpdates::default(),
1035        }
1036    }
1037    #[must_use]
1038    pub(crate) fn apply_info(&self) -> ContextUpdates {
1039        let (info, info_widgets) = UPDATES.take_info();
1040
1041        ContextUpdates {
1042            events: vec![],
1043            update: false,
1044            update_widgets: WidgetUpdates::default(),
1045            info,
1046            info_widgets,
1047            layout: false,
1048            layout_widgets: LayoutUpdates::default(),
1049            render: false,
1050            render_widgets: RenderUpdates::default(),
1051            render_update_widgets: RenderUpdates::default(),
1052        }
1053    }
1054    #[must_use]
1055    pub(crate) fn apply_layout_render(&self) -> ContextUpdates {
1056        let (layout, layout_widgets) = UPDATES.take_layout();
1057        let (render, render_widgets, render_update_widgets) = UPDATES.take_render();
1058
1059        ContextUpdates {
1060            events: vec![],
1061            update: false,
1062            update_widgets: WidgetUpdates::default(),
1063            info: false,
1064            info_widgets: InfoUpdates::default(),
1065            layout,
1066            layout_widgets,
1067            render,
1068            render_widgets,
1069            render_update_widgets,
1070        }
1071    }
1072
1073    pub(crate) fn on_app_awake(&self) {
1074        UPDATES_SV.write().app_awake(true);
1075    }
1076
1077    pub(crate) fn on_app_sleep(&self) {
1078        UPDATES_SV.write().app_awake(false);
1079    }
1080
1081    pub(crate) fn next_deadline(&self, timer: &mut LoopTimer) {
1083        TIMERS_SV.write().next_deadline(timer);
1084        VARS_APP.next_deadline(timer);
1085    }
1086
1087    pub(crate) fn update_timers(&self, timer: &mut LoopTimer) {
1089        TIMERS_SV.write().apply_updates(timer);
1090        VARS_APP.update_animations(timer);
1091    }
1092
1093    #[must_use]
1095    pub(crate) fn has_pending_updates(&self) -> bool {
1096        UPDATES_SV.read().update_ext.intersects(UpdateFlags::UPDATE | UpdateFlags::INFO)
1097            || VARS_APP.has_pending_updates()
1098            || EVENTS_SV.write().has_pending_updates()
1099            || TIMERS_SV.read().has_pending_updates()
1100    }
1101
1102    #[must_use]
1103    pub(crate) fn has_pending_layout_or_render(&self) -> bool {
1104        UPDATES_SV
1105            .read()
1106            .update_ext
1107            .intersects(UpdateFlags::LAYOUT | UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE)
1108    }
1109
1110    pub fn sender(&self) -> AppEventSender {
1112        UPDATES_SV.read().event_sender.as_ref().unwrap().clone()
1113    }
1114
1115    pub fn waker(&self, target: impl Into<Option<WidgetId>>) -> Waker {
1117        UPDATES_SV.read().event_sender.as_ref().unwrap().waker(target)
1118    }
1119
1120    pub(crate) fn update_flags_root(&self, flags: UpdateFlags, window_id: WindowId, root_id: WidgetId) {
1121        if flags.is_empty() {
1122            return;
1123        }
1124
1125        let mut u = UPDATES_SV.write();
1126        if flags.contains(UpdateFlags::UPDATE) {
1127            u.update_widgets.insert_updates_root(window_id, root_id);
1128        }
1129        if flags.contains(UpdateFlags::INFO) {
1130            u.info_widgets.insert_updates_root(window_id, root_id);
1131        }
1132        if flags.contains(UpdateFlags::LAYOUT) {
1133            u.layout_widgets.insert_updates_root(window_id, root_id);
1134        }
1135
1136        if flags.contains(UpdateFlags::RENDER) {
1137            u.render_widgets.insert_updates_root(window_id, root_id);
1138        } else if flags.contains(UpdateFlags::RENDER_UPDATE) {
1139            u.render_update_widgets.insert_updates_root(window_id, root_id);
1140        }
1141
1142        u.update_ext |= flags;
1143    }
1144
1145    pub(crate) fn update_flags(&self, flags: UpdateFlags, target: impl Into<Option<WidgetId>>) {
1146        if flags.is_empty() {
1147            return;
1148        }
1149
1150        let mut u = UPDATES_SV.write();
1151
1152        if let Some(id) = target.into() {
1153            if flags.contains(UpdateFlags::UPDATE) {
1154                u.update_widgets.search_widget(id);
1155            }
1156            if flags.contains(UpdateFlags::INFO) {
1157                u.info_widgets.search_widget(id);
1158            }
1159            if flags.contains(UpdateFlags::LAYOUT) {
1160                u.layout_widgets.search_widget(id);
1161            }
1162
1163            if flags.contains(UpdateFlags::RENDER) {
1164                u.render_widgets.search_widget(id);
1165            } else if flags.contains(UpdateFlags::RENDER_UPDATE) {
1166                u.render_update_widgets.search_widget(id);
1167            }
1168        }
1169
1170        u.update_ext |= flags;
1171    }
1172
1173    pub fn update_op(&self, op: UpdateOp, target: impl Into<Option<WidgetId>>) -> &Self {
1175        let target = target.into();
1176        match op {
1177            UpdateOp::Update => self.update(target),
1178            UpdateOp::Info => self.update_info(target),
1179            UpdateOp::Layout => self.layout(target),
1180            UpdateOp::Render => self.render(target),
1181            UpdateOp::RenderUpdate => self.render_update(target),
1182        }
1183    }
1184
1185    pub fn update_op_window(&self, op: UpdateOp, target: WindowId) -> &Self {
1187        match op {
1188            UpdateOp::Update => self.update_window(target),
1189            UpdateOp::Info => self.update_info_window(target),
1190            UpdateOp::Layout => self.layout_window(target),
1191            UpdateOp::Render => self.render_window(target),
1192            UpdateOp::RenderUpdate => self.render_update_window(target),
1193        }
1194    }
1195
1196    pub fn update(&self, target: impl Into<Option<WidgetId>>) -> &Self {
1200        UpdatesTrace::log_update();
1201        self.update_internal(target.into())
1202    }
1203    pub(crate) fn update_internal(&self, target: Option<WidgetId>) -> &UPDATES {
1205        let mut u = UPDATES_SV.write();
1206        u.update_ext.insert(UpdateFlags::UPDATE);
1207        u.send_awake();
1208        if let Some(id) = target {
1209            u.update_widgets.search_widget(id);
1210        }
1211        self
1212    }
1213
1214    pub fn update_window(&self, target: WindowId) -> &Self {
1216        let mut u = UPDATES_SV.write();
1217        u.update_ext.insert(UpdateFlags::UPDATE);
1218        u.send_awake();
1219        u.update_widgets.insert_window(target);
1220        self
1221    }
1222
1223    pub(crate) fn send_awake(&self) {
1224        UPDATES_SV.write().send_awake();
1225    }
1226
1227    pub fn update_info(&self, target: impl Into<Option<WidgetId>>) -> &Self {
1231        UpdatesTrace::log_info();
1232        let mut u = UPDATES_SV.write();
1233        u.update_ext.insert(UpdateFlags::INFO);
1234        u.send_awake();
1235        if let Some(id) = target.into() {
1236            u.info_widgets.search_widget(id);
1237        }
1238        self
1239    }
1240
1241    pub fn update_info_window(&self, target: WindowId) -> &Self {
1243        UpdatesTrace::log_info();
1244        let mut u = UPDATES_SV.write();
1245        u.update_ext.insert(UpdateFlags::INFO);
1246        u.send_awake();
1247        u.info_widgets.insert_window(target);
1248        self
1249    }
1250
1251    pub fn layout(&self, target: impl Into<Option<WidgetId>>) -> &Self {
1255        UpdatesTrace::log_layout();
1256        let mut u = UPDATES_SV.write();
1257        u.update_ext.insert(UpdateFlags::LAYOUT);
1258        u.send_awake();
1259        if let Some(id) = target.into() {
1260            u.layout_widgets.search_widget(id);
1261        }
1262        self
1263    }
1264
1265    pub fn layout_window(&self, target: WindowId) -> &Self {
1267        UpdatesTrace::log_layout();
1268        let mut u = UPDATES_SV.write();
1269        u.update_ext.insert(UpdateFlags::LAYOUT);
1270        u.send_awake();
1271        u.layout_widgets.insert_window(target);
1272        self
1273    }
1274
1275    pub fn render(&self, target: impl Into<Option<WidgetId>>) -> &Self {
1282        UpdatesTrace::log_render();
1283        let mut u = UPDATES_SV.write();
1284        u.update_ext.insert(UpdateFlags::RENDER);
1285        u.send_awake();
1286        if let Some(id) = target.into() {
1287            u.render_widgets.search_widget(id);
1288        }
1289        self
1290    }
1291
1292    pub fn render_window(&self, target: WindowId) -> &Self {
1294        UpdatesTrace::log_render();
1295        let mut u = UPDATES_SV.write();
1296        u.update_ext.insert(UpdateFlags::RENDER);
1297        u.send_awake();
1298        u.render_widgets.insert_window(target);
1299        self
1300    }
1301
1302    pub fn render_update(&self, target: impl Into<Option<WidgetId>>) -> &Self {
1308        UpdatesTrace::log_render();
1309        let mut u = UPDATES_SV.write();
1310        u.update_ext.insert(UpdateFlags::RENDER_UPDATE);
1311        u.send_awake();
1312        if let Some(id) = target.into() {
1313            u.render_update_widgets.search_widget(id);
1314        }
1315        self
1316    }
1317
1318    pub fn render_update_window(&self, target: WindowId) -> &Self {
1320        UpdatesTrace::log_render();
1321        let mut u = UPDATES_SV.write();
1322        u.update_ext.insert(UpdateFlags::RENDER_UPDATE);
1323        u.send_awake();
1324        u.render_update_widgets.insert_window(target);
1325        self
1326    }
1327
1328    pub fn is_pending_render(&self, window_id: WindowId) -> bool {
1330        let u = UPDATES_SV.read();
1331        u.render_widgets.enter_window(window_id) || u.render_update_widgets.enter_window(window_id)
1332    }
1333
1334    pub fn run<F: Future<Output = ()> + Send + 'static>(&self, future: F) -> OnUpdateHandle {
1338        self.run_hn_once(async_app_hn_once!(|_| future.await))
1339    }
1340
1341    pub fn run_hn_once<H: AppHandler<UpdateArgs>>(&self, handler: H) -> OnUpdateHandle {
1346        let mut u = UPDATES_SV.write();
1347        u.update_ext.insert(UpdateFlags::UPDATE);
1348        u.send_awake();
1349        Self::push_handler(u.pos_handlers.get_mut(), true, handler, true)
1350    }
1351
1352    pub fn on_pre_update<H>(&self, handler: H) -> OnUpdateHandle
1366    where
1367        H: AppHandler<UpdateArgs>,
1368    {
1369        let u = UPDATES_SV.read();
1370        Self::push_handler(&mut u.pre_handlers.lock(), true, handler, false)
1371    }
1372
1373    pub fn on_update<H>(&self, handler: H) -> OnUpdateHandle
1387    where
1388        H: AppHandler<UpdateArgs>,
1389    {
1390        let u = UPDATES_SV.read();
1391        Self::push_handler(&mut u.pos_handlers.lock(), false, handler, false)
1392    }
1393
1394    fn push_handler<H>(entries: &mut Vec<UpdateHandler>, is_preview: bool, mut handler: H, force_once: bool) -> OnUpdateHandle
1395    where
1396        H: AppHandler<UpdateArgs>,
1397    {
1398        let (handle_owner, handle) = OnUpdateHandle::new();
1399        entries.push(UpdateHandler {
1400            handle: handle_owner,
1401            count: 0,
1402            handler: Box::new(move |args, handle| {
1403                let handler_args = AppHandlerArgs { handle, is_preview };
1404                handler.event(args, &handler_args);
1405                if force_once {
1406                    handler_args.handle.unsubscribe();
1407                }
1408            }),
1409        });
1410        handle
1411    }
1412
1413    pub(crate) fn on_pre_updates(&self) {
1414        let _s = tracing::trace_span!("UPDATES.on_pre_updates");
1415        let mut handlers = mem::take(UPDATES_SV.write().pre_handlers.get_mut());
1416        Self::retain_updates(&mut handlers);
1417
1418        let mut u = UPDATES_SV.write();
1419        handlers.append(u.pre_handlers.get_mut());
1420        *u.pre_handlers.get_mut() = handlers;
1421    }
1422
1423    pub(crate) fn on_updates(&self) {
1424        let _s = tracing::trace_span!("UPDATES.on_updates");
1425        let mut handlers = mem::take(UPDATES_SV.write().pos_handlers.get_mut());
1426        Self::retain_updates(&mut handlers);
1427
1428        let mut u = UPDATES_SV.write();
1429        handlers.append(u.pos_handlers.get_mut());
1430        *u.pos_handlers.get_mut() = handlers;
1431    }
1432
1433    fn retain_updates(handlers: &mut Vec<UpdateHandler>) {
1434        handlers.retain_mut(|e| {
1435            !e.handle.is_dropped() && {
1436                e.count = e.count.wrapping_add(1);
1437                (e.handler)(&UpdateArgs { count: e.count }, &e.handle.weak_handle());
1438                !e.handle.is_dropped()
1439            }
1440        });
1441    }
1442
1443    pub(super) fn take_update(&self) -> (bool, WidgetUpdates) {
1445        let mut u = UPDATES_SV.write();
1446
1447        let ext = u.update_ext.contains(UpdateFlags::UPDATE);
1448        u.update_ext.remove(UpdateFlags::UPDATE);
1449
1450        (
1451            ext,
1452            WidgetUpdates {
1453                delivery_list: mem::take(&mut u.update_widgets),
1454            },
1455        )
1456    }
1457
1458    pub(super) fn take_info(&self) -> (bool, InfoUpdates) {
1460        let mut u = UPDATES_SV.write();
1461
1462        let ext = u.update_ext.contains(UpdateFlags::INFO);
1463        u.update_ext.remove(UpdateFlags::INFO);
1464
1465        (
1466            ext,
1467            InfoUpdates {
1468                delivery_list: mem::take(&mut u.info_widgets),
1469            },
1470        )
1471    }
1472
1473    pub(super) fn take_layout(&self) -> (bool, LayoutUpdates) {
1475        let mut u = UPDATES_SV.write();
1476
1477        let ext = u.update_ext.contains(UpdateFlags::LAYOUT);
1478        u.update_ext.remove(UpdateFlags::LAYOUT);
1479
1480        (
1481            ext,
1482            LayoutUpdates {
1483                delivery_list: mem::take(&mut u.layout_widgets),
1484            },
1485        )
1486    }
1487
1488    pub(super) fn take_render(&self) -> (bool, RenderUpdates, RenderUpdates) {
1490        let mut u = UPDATES_SV.write();
1491
1492        let ext = u.update_ext.intersects(UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE);
1493        u.update_ext.remove(UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE);
1494
1495        (
1496            ext,
1497            RenderUpdates {
1498                delivery_list: mem::take(&mut u.render_widgets),
1499            },
1500            RenderUpdates {
1501                delivery_list: mem::take(&mut u.render_update_widgets),
1502            },
1503        )
1504    }
1505
1506    pub(crate) fn handler_lens(&self) -> (usize, usize) {
1507        let u = UPDATES_SV.read();
1508
1509        (u.pre_handlers.lock().len(), u.pos_handlers.lock().len())
1510    }
1511    pub(crate) fn new_update_handlers(&self, pre_from: usize, pos_from: usize) -> Vec<Box<dyn Fn() -> bool>> {
1512        let u = UPDATES_SV.read();
1513
1514        u.pre_handlers
1515            .lock()
1516            .iter()
1517            .skip(pre_from)
1518            .chain(u.pos_handlers.lock().iter().skip(pos_from))
1519            .map(|h| h.handle.weak_handle())
1520            .map(|h| {
1521                let r: Box<dyn Fn() -> bool> = Box::new(move || h.upgrade().is_some());
1522                r
1523            })
1524            .collect()
1525    }
1526}
1527
1528app_local! {
1529    static UPDATES_SV: UpdatesService = UpdatesService::new();
1530}
1531struct UpdatesService {
1532    event_sender: Option<AppEventSender>,
1533
1534    update_ext: UpdateFlags,
1535    update_widgets: UpdateDeliveryList,
1536    info_widgets: UpdateDeliveryList,
1537    layout_widgets: UpdateDeliveryList,
1538    render_widgets: UpdateDeliveryList,
1539    render_update_widgets: UpdateDeliveryList,
1540
1541    pre_handlers: Mutex<Vec<UpdateHandler>>,
1542    pos_handlers: Mutex<Vec<UpdateHandler>>,
1543
1544    app_is_awake: bool,
1545    awake_pending: bool,
1546}
1547impl UpdatesService {
1548    fn new() -> Self {
1549        Self {
1550            event_sender: None,
1551            update_ext: UpdateFlags::empty(),
1552            update_widgets: UpdateDeliveryList::new_any(),
1553            info_widgets: UpdateDeliveryList::new_any(),
1554            layout_widgets: UpdateDeliveryList::new_any(),
1555            render_widgets: UpdateDeliveryList::new_any(),
1556            render_update_widgets: UpdateDeliveryList::new_any(),
1557
1558            pre_handlers: Mutex::new(vec![]),
1559            pos_handlers: Mutex::new(vec![]),
1560
1561            app_is_awake: false,
1562            awake_pending: false,
1563        }
1564    }
1565
1566    fn send_awake(&mut self) {
1567        if !self.app_is_awake && !self.awake_pending {
1568            self.awake_pending = true;
1569            match self.event_sender.as_ref() {
1570                Some(s) => {
1571                    if let Err(AppChannelError::Disconnected) = s.send_check_update() {
1572                        tracing::debug!("no app connected to update");
1573                    }
1574                }
1575                None => {
1576                    tracing::debug!("no app connected yet to update");
1577                }
1578            }
1579        }
1580    }
1581
1582    fn app_awake(&mut self, wake: bool) {
1583        self.awake_pending = false;
1584        self.app_is_awake = wake;
1585    }
1586}
1587
1588#[non_exhaustive]
1592#[derive(Default)]
1593pub struct ContextUpdates {
1594    pub events: Vec<EventUpdate>,
1598
1599    pub update: bool,
1604
1605    pub info: bool,
1610
1611    pub layout: bool,
1616
1617    pub render: bool,
1622
1623    pub update_widgets: WidgetUpdates,
1627
1628    pub info_widgets: InfoUpdates,
1632
1633    pub layout_widgets: LayoutUpdates,
1637
1638    pub render_widgets: RenderUpdates,
1642
1643    pub render_update_widgets: RenderUpdates,
1647}
1648
1649impl fmt::Debug for ContextUpdates {
1650    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1651        if f.alternate() {
1652            f.debug_struct("ContextUpdates")
1653                .field("update", &self.update)
1654                .field("info", &self.info)
1655                .field("layout", &self.layout)
1656                .field("render", &self.render)
1657                .field("events", &self.events)
1658                .field("update_widgets", &self.update_widgets)
1659                .field("info_widgets", &self.info_widgets)
1660                .field("layout_widgets", &self.layout_widgets)
1661                .field("render_widgets", &self.render_widgets)
1662                .field("render_update_widgets", &self.render_update_widgets)
1663                .finish()
1664        } else {
1665            write!(f, "ContextUpdates: ")?;
1666            let mut sep = "";
1667            if !self.events.is_empty() {
1668                write!(f, "{sep}events[")?;
1669                for e in &self.events {
1670                    write!(f, "{sep}{}", e.event.name())?;
1671                    sep = ", ";
1672                }
1673                write!(f, "]")?;
1674            }
1675            if self.update {
1676                write!(f, "{sep}update")?;
1677                sep = ", ";
1678            }
1679            if self.info {
1680                write!(f, "{sep}info")?;
1681                sep = ", ";
1682            }
1683            if self.layout {
1684                write!(f, "{sep}layout")?;
1685                sep = ", ";
1686            }
1687            if self.render {
1688                write!(f, "{sep}render")?;
1689                sep = ", ";
1690            }
1691            if sep.is_empty() {
1692                write!(f, "<none>")?;
1693            }
1694            Ok(())
1695        }
1696    }
1697}
1698impl ContextUpdates {
1699    pub fn has_updates(&self) -> bool {
1701        !self.events.is_empty() || self.update || self.info || self.layout || self.render
1702    }
1703}
1704impl std::ops::BitOrAssign for ContextUpdates {
1705    fn bitor_assign(&mut self, rhs: Self) {
1706        self.events.extend(rhs.events);
1707        self.update |= rhs.update;
1708        self.update_widgets.extend(rhs.update_widgets);
1709        self.info |= rhs.info;
1710        self.info_widgets.extend(rhs.info_widgets);
1711        self.layout |= rhs.layout;
1712        self.layout_widgets.extend(rhs.layout_widgets);
1713        self.render |= rhs.render;
1714        self.render_widgets.extend(rhs.render_widgets);
1715        self.render_update_widgets.extend(rhs.render_update_widgets);
1716    }
1717}
1718impl std::ops::BitOr for ContextUpdates {
1719    type Output = Self;
1720
1721    fn bitor(mut self, rhs: Self) -> Self {
1722        self |= rhs;
1723        self
1724    }
1725}
1726
1727bitflags::bitflags! {
1728    #[derive(Clone, Copy, Debug, bytemuck::NoUninit)]
1729    #[repr(transparent)]
1730    pub(crate) struct UpdateFlags: u8 {
1731        const REINIT =        0b1000_0000;
1732        const INFO =          0b0001_0000;
1733        const UPDATE =        0b0000_0001;
1734        const LAYOUT =        0b0000_0010;
1735        const RENDER =        0b0000_0100;
1736        const RENDER_UPDATE = 0b0000_1000;
1737    }
1738}
1739
1740#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1745#[repr(transparent)]
1746#[must_use = "dropping the handle unsubscribes update handler"]
1747pub struct OnUpdateHandle(Handle<()>);
1748impl OnUpdateHandle {
1749    fn new() -> (HandleOwner<()>, OnUpdateHandle) {
1750        let (owner, handle) = Handle::new(());
1751        (owner, OnUpdateHandle(handle))
1752    }
1753
1754    pub fn dummy() -> Self {
1758        OnUpdateHandle(Handle::dummy(()))
1759    }
1760
1761    pub fn perm(self) {
1765        self.0.perm();
1766    }
1767
1768    pub fn is_permanent(&self) -> bool {
1772        self.0.is_permanent()
1773    }
1774
1775    pub fn unsubscribe(self) {
1777        self.0.force_drop()
1778    }
1779
1780    pub fn is_unsubscribed(&self) -> bool {
1784        self.0.is_dropped()
1785    }
1786
1787    pub fn downgrade(&self) -> WeakOnUpdateHandle {
1789        WeakOnUpdateHandle(self.0.downgrade())
1790    }
1791}
1792
1793#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)]
1795pub struct WeakOnUpdateHandle(WeakHandle<()>);
1796impl WeakOnUpdateHandle {
1797    pub fn new() -> Self {
1799        Self(WeakHandle::new())
1800    }
1801
1802    pub fn upgrade(&self) -> Option<OnUpdateHandle> {
1804        self.0.upgrade().map(OnUpdateHandle)
1805    }
1806}
1807
1808#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1810pub enum UpdateOp {
1811    Update,
1819    Info,
1828    Layout,
1836    Render,
1844    RenderUpdate,
1855}
1856
1857#[derive(Debug, Clone, Copy)]
1859#[non_exhaustive]
1860pub struct UpdateArgs {
1861    pub count: usize,
1863}
1864
1865struct UpdateHandler {
1866    handle: HandleOwner<()>,
1867    count: usize,
1868    handler: Box<dyn FnMut(&UpdateArgs, &dyn AppWeakHandle) + Send>,
1869}