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, async_hn_once,
18 event::{AnyEvent, AnyEventArgs, EVENTS, EVENTS_SV},
19 handler::{AppWeakHandle, Handler, HandlerExt as _},
20 timer::TIMERS_SV,
21 widget::{
22 WIDGET, WidgetId,
23 info::{InteractionPath, WidgetInfo, WidgetInfoTree, WidgetPath},
24 node::UiNode,
25 },
26 window::{WINDOW, WindowId},
27};
28
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 fn custom(&self, delivery_list: UpdateDeliveryList) -> Self {
334 Self {
335 event: self.event,
336 args: self.args.clone_any(),
337 delivery_list,
338 pre_actions: Mutex::new(vec![]),
339 pos_actions: Mutex::new(vec![]),
340 }
341 }
342
343 pub(crate) fn push_once_action(&mut self, action: Box<dyn FnOnce(&EventUpdate) + Send>, is_preview: bool) {
344 if is_preview {
345 self.pre_actions.get_mut().push(action);
346 } else {
347 self.pos_actions.get_mut().push(action);
348 }
349 }
350
351 pub(crate) fn call_pre_actions(&mut self) {
352 let _s = tracing::trace_span!("call_pre_actions");
353 let actions = mem::take(self.pre_actions.get_mut());
354 for action in actions {
355 action(self)
356 }
357 }
358
359 pub(crate) fn call_pos_actions(&mut self) {
360 let _s = tracing::trace_span!("call_pos_actions");
361 let actions = mem::take(self.pos_actions.get_mut());
362 for action in actions {
363 action(self)
364 }
365 }
366}
367impl fmt::Debug for EventUpdate {
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 f.debug_struct("EventUpdate")
370 .field("event", &self.event)
371 .field("args", &self.args)
372 .field("delivery_list", &self.delivery_list)
373 .finish_non_exhaustive()
374 }
375}
376
377#[derive(Debug, Default)]
379pub struct InfoUpdates {
380 delivery_list: UpdateDeliveryList,
381}
382impl InfoUpdates {
383 pub fn new(delivery_list: UpdateDeliveryList) -> Self {
385 Self { delivery_list }
386 }
387
388 pub fn delivery_list(&self) -> &UpdateDeliveryList {
390 &self.delivery_list
391 }
392
393 pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
395 &mut self.delivery_list
396 }
397
398 pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
400 where
401 H: FnOnce() -> R,
402 {
403 if self.delivery_list.enter_window(window_id) {
404 Some(handle())
405 } else {
406 None
407 }
408 }
409
410 pub fn extend(&mut self, other: InfoUpdates) {
412 self.delivery_list.extend_unchecked(other.delivery_list)
413 }
414}
415
416#[derive(Debug, Default)]
418pub struct WidgetUpdates {
419 pub(crate) delivery_list: UpdateDeliveryList,
420}
421impl WidgetUpdates {
422 pub fn new(delivery_list: UpdateDeliveryList) -> Self {
424 Self { delivery_list }
425 }
426
427 pub fn delivery_list(&self) -> &UpdateDeliveryList {
429 &self.delivery_list
430 }
431
432 pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
434 &mut self.delivery_list
435 }
436
437 pub fn with_window<H, R>(&self, handle: H) -> Option<R>
439 where
440 H: FnOnce() -> R,
441 {
442 if self.delivery_list.enter_window(WINDOW.id()) {
443 Some(handle())
444 } else {
445 None
446 }
447 }
448
449 pub fn with_widget<H, R>(&self, handle: H) -> Option<R>
451 where
452 H: FnOnce() -> R,
453 {
454 if WIDGET.take_update(UpdateFlags::UPDATE) || self.delivery_list.enter_widget(WIDGET.id()) {
455 Some(handle())
456 } else {
457 None
458 }
459 }
460
461 pub fn extend(&mut self, other: WidgetUpdates) {
463 self.delivery_list.extend_unchecked(other.delivery_list)
464 }
465}
466
467#[derive(Debug, Default)]
469pub struct LayoutUpdates {
470 pub(crate) delivery_list: UpdateDeliveryList,
471}
472impl LayoutUpdates {
473 pub fn new(delivery_list: UpdateDeliveryList) -> Self {
475 Self { delivery_list }
476 }
477
478 pub fn delivery_list(&self) -> &UpdateDeliveryList {
480 &self.delivery_list
481 }
482
483 pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
485 &mut self.delivery_list
486 }
487
488 pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
490 where
491 H: FnOnce() -> R,
492 {
493 if self.delivery_list.enter_window(window_id) {
494 Some(handle())
495 } else {
496 None
497 }
498 }
499
500 pub fn extend(&mut self, other: LayoutUpdates) {
502 self.delivery_list.extend_unchecked(other.delivery_list)
503 }
504}
505
506#[derive(Debug, Default)]
508pub struct RenderUpdates {
509 delivery_list: UpdateDeliveryList,
510}
511impl RenderUpdates {
512 pub fn new(delivery_list: UpdateDeliveryList) -> Self {
514 Self { delivery_list }
515 }
516
517 pub fn delivery_list(&self) -> &UpdateDeliveryList {
519 &self.delivery_list
520 }
521
522 pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
524 &mut self.delivery_list
525 }
526
527 pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
529 where
530 H: FnOnce() -> R,
531 {
532 if self.delivery_list.enter_window(window_id) {
533 Some(handle())
534 } else {
535 None
536 }
537 }
538
539 pub fn extend(&mut self, other: RenderUpdates) {
541 self.delivery_list.extend_unchecked(other.delivery_list)
542 }
543}
544
545pub trait UpdatesTraceUiNodeExt {
549 fn instrument<S: Into<String>>(self, tag: S) -> UiNode
551 where
552 Self: Sized;
553}
554impl UpdatesTraceUiNodeExt for UiNode {
555 fn instrument<S: Into<String>>(self, tag: S) -> UiNode {
556 let tag = tag.into();
557 self.trace(move |op| UpdatesTrace::custom_span(&tag, op.mtd_name()))
558 }
559}
560
561pub fn updates_trace_span(tag: &'static str) -> tracing::span::EnteredSpan {
565 UpdatesTrace::custom_span(tag, "")
566}
567
568pub fn updates_trace_event(tag: &str) {
572 UpdatesTrace::log_custom(tag)
573}
574
575pub(crate) struct UpdatesTrace {
576 context: Mutex<UpdateContext>,
577 trace: Arc<Mutex<Vec<UpdateTrace>>>,
578
579 widgets_stack: Mutex<Vec<(WidgetId, String)>>,
580 node_parents_stack: Mutex<Vec<String>>,
581 tags_stack: Mutex<Vec<String>>,
582}
583impl tracing::subscriber::Subscriber for UpdatesTrace {
584 fn enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
585 metadata.target() == Self::UPDATES_TARGET
586 }
587
588 fn new_span(&self, span: &tracing::span::Attributes<'_>) -> tracing::span::Id {
589 match span.metadata().name() {
590 "property" | "intrinsic" => {
591 let name = visit_str(|v| span.record(v), "name");
592 let mut ctx = self.context.lock();
593
594 if let Some(p) = ctx.node_parent.replace(name) {
595 self.node_parents_stack.lock().push(p);
596 }
597 if let Some(p) = ctx.tag.replace(String::new()) {
598 self.tags_stack.lock().push(p);
599 }
600
601 tracing::span::Id::from_u64(1)
602 }
603 "widget" => {
604 let id = visit_u64(|v| span.record(v), "raw_id").unwrap();
605 if id == 0 {
606 panic!()
607 }
608 let id = WidgetId::from_raw(id);
609
610 let name = visit_str(|v| span.record(v), "name");
611
612 let mut ctx = self.context.lock();
613 if let Some(p) = ctx.widget.replace((id, name)) {
614 self.widgets_stack.lock().push(p);
615 }
616
617 if let Some(p) = ctx.node_parent.replace(String::new()) {
618 self.node_parents_stack.lock().push(p);
619 }
620
621 if let Some(p) = ctx.tag.replace(String::new()) {
622 self.tags_stack.lock().push(p);
623 }
624
625 tracing::span::Id::from_u64(2)
626 }
627 "Window" => {
628 let id = visit_u64(|v| span.record(v), "raw_id").unwrap() as u32;
629 if id == 0 {
630 panic!()
631 }
632 let id = WindowId::from_raw(id);
633
634 let mut ctx = self.context.lock();
635 ctx.window_id = Some(id);
636
637 if let Some(p) = ctx.tag.replace(String::new()) {
638 self.tags_stack.lock().push(p);
639 }
640
641 tracing::span::Id::from_u64(3)
642 }
643 "AppExtension" => {
644 let name = visit_str(|v| span.record(v), "name");
645
646 let mut ctx = self.context.lock();
647 ctx.app_extension = Some(name);
648
649 if let Some(p) = ctx.tag.replace(String::new()) {
650 self.tags_stack.lock().push(p);
651 }
652
653 tracing::span::Id::from_u64(4)
654 }
655 "tag" => {
656 let tag = visit_str(|v| span.record(v), "tag");
657 let mut ctx = self.context.lock();
658 if let Some(p) = ctx.tag.replace(tag) {
659 self.tags_stack.lock().push(p);
660 }
661 tracing::span::Id::from_u64(5)
662 }
663 _ => tracing::span::Id::from_u64(u64::MAX),
664 }
665 }
666
667 fn record(&self, _span: &tracing::span::Id, _values: &tracing::span::Record<'_>) {}
668
669 fn record_follows_from(&self, _span: &tracing::span::Id, _follows: &tracing::span::Id) {}
670
671 fn event(&self, event: &tracing::Event<'_>) {
672 let action = match visit_str(|v| event.record(v), "kind").as_str() {
673 "var" => UpdateAction::Var {
674 type_name: visit_str(|v| event.record(v), "type_name"),
675 },
676 "event" => UpdateAction::Event {
677 type_name: visit_str(|v| event.record(v), "type_name"),
678 },
679 "request" => UpdateAction::Update,
680 "info" => UpdateAction::Info,
681 "layout" => UpdateAction::Layout,
682 "render" => UpdateAction::Render,
683 "custom" => UpdateAction::Custom {
684 tag: visit_str(|v| event.record(v), "tag"),
685 },
686 _ => return,
687 };
688
689 let ctx = self.context.lock().clone();
690 let entry = UpdateTrace { ctx, action };
695 self.trace.lock().push(entry);
696 }
697
698 fn enter(&self, _span: &tracing::span::Id) {}
699
700 fn exit(&self, span: &tracing::span::Id) {
701 let mut ctx = self.context.lock();
702 if span == &tracing::span::Id::from_u64(1) {
703 ctx.node_parent = self.node_parents_stack.lock().pop();
704 ctx.tag = self.tags_stack.lock().pop();
705 } else if span == &tracing::span::Id::from_u64(2) {
706 ctx.widget = self.widgets_stack.lock().pop();
707 ctx.node_parent = self.node_parents_stack.lock().pop();
708 ctx.tag = self.tags_stack.lock().pop();
709 } else if span == &tracing::span::Id::from_u64(3) {
710 ctx.window_id = None;
711 ctx.tag = self.tags_stack.lock().pop();
712 } else if span == &tracing::span::Id::from_u64(4) {
713 ctx.app_extension = None;
714 ctx.tag = self.tags_stack.lock().pop();
715 } else if span == &tracing::span::Id::from_u64(5) {
716 ctx.tag = self.tags_stack.lock().pop();
717 }
718 }
719}
720static UPDATES_TRACE_ENABLED: AtomicBool = AtomicBool::new(false);
721impl UpdatesTrace {
722 const UPDATES_TARGET: &'static str = "zng-updates";
723
724 fn new() -> Self {
725 UpdatesTrace {
726 context: Mutex::new(UpdateContext::default()),
727 trace: Arc::new(Mutex::new(Vec::with_capacity(100))),
728 widgets_stack: Mutex::new(Vec::with_capacity(100)),
729 node_parents_stack: Mutex::new(Vec::with_capacity(100)),
730 tags_stack: Mutex::new(Vec::new()),
731 }
732 }
733
734 #[inline(always)]
736 pub fn is_tracing() -> bool {
737 UPDATES_TRACE_ENABLED.load(atomic::Ordering::Relaxed)
738 }
739
740 pub fn extension_span<E: AppExtension>(ext_mtd: &'static str) -> tracing::span::EnteredSpan {
742 if Self::is_tracing() {
743 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "AppExtension", name = pretty_type_name::pretty_type_name::<E>(), %ext_mtd).entered()
744 } else {
745 tracing::span::Span::none().entered()
746 }
747 }
748
749 pub fn window_span(id: WindowId) -> tracing::span::EnteredSpan {
751 if Self::is_tracing() {
752 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "Window", %id, raw_id = id.get() as u64).entered()
753 } else {
754 tracing::span::Span::none().entered()
755 }
756 }
757
758 #[cfg(feature = "trace_widget")]
760 pub fn widget_span(id: WidgetId, name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
761 if Self::is_tracing() {
762 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "widget", %id, raw_id = id.get(), name, %node_mtd).entered()
763 } else {
764 tracing::span::Span::none().entered()
765 }
766 }
767
768 #[cfg(feature = "trace_wgt_item")]
770 pub fn property_span(name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
771 if Self::is_tracing() {
772 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "property", name, %node_mtd).entered()
773 } else {
774 tracing::span::Span::none().entered()
775 }
776 }
777
778 #[cfg(feature = "trace_wgt_item")]
780 pub fn intrinsic_span(name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
781 if Self::is_tracing() {
782 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "intrinsic", name, %node_mtd).entered()
783 } else {
784 tracing::span::Span::none().entered()
785 }
786 }
787
788 pub fn custom_span(name: &str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
790 if Self::is_tracing() {
791 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "tag", %name, %node_mtd).entered()
792 } else {
793 tracing::Span::none().entered()
794 }
795 }
796
797 pub fn log_update() {
799 if Self::is_tracing() {
800 tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
801 kind = "update"
802 });
803 }
804 }
805
806 pub fn log_info() {
808 if Self::is_tracing() {
809 tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
810 kind = "info"
811 });
812 }
813 }
814
815 pub fn log_layout() {
817 if Self::is_tracing() {
818 tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
819 kind = "layout"
820 });
821 }
822 }
823
824 pub fn log_render() {
826 if Self::is_tracing() {
827 tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
828 kind = "render"
829 });
830 }
831 }
832
833 pub fn log_custom(tag: &str) {
835 if Self::is_tracing() {
836 tracing::event!(
837 target: UpdatesTrace::UPDATES_TARGET,
838 tracing::Level::TRACE,
839 { kind = "custom", %tag }
840 );
841 }
842 }
843
844 pub fn log_var(type_name: &str) {
846 if Self::is_tracing() {
847 tracing::event!(
848 target: UpdatesTrace::UPDATES_TARGET,
849 tracing::Level::TRACE,
850 { kind = "var", type_name = pretty_type_name::pretty_type_name_str(type_name) }
851 );
852 }
853 }
854
855 pub fn log_event(event: AnyEvent) {
857 if Self::is_tracing() {
858 tracing::event!(
859 target: UpdatesTrace::UPDATES_TARGET,
860 tracing::Level::TRACE,
861 { kind = "event", type_name = event.name() }
862 );
863 }
864 }
865
866 pub fn collect_trace<R>(trace: &mut Vec<UpdateTrace>, action: impl FnOnce() -> R) -> R {
868 let trace_enabled = UPDATES_TRACE_ENABLED.swap(true, atomic::Ordering::Relaxed);
869
870 let tracer = UpdatesTrace::new();
871 let result = Arc::clone(&tracer.trace);
872 let r = tracing::subscriber::with_default(tracer, action);
873 trace.extend(Arc::try_unwrap(result).unwrap().into_inner());
874
875 UPDATES_TRACE_ENABLED.store(trace_enabled, atomic::Ordering::Relaxed);
876
877 r
878 }
879
880 pub fn format_trace(trace: Vec<UpdateTrace>) -> String {
882 let mut frequencies = HashMap::with_capacity(50);
883 for t in trace {
884 match frequencies.entry(t) {
885 hash_map::Entry::Vacant(e) => {
886 e.insert(1);
887 }
888 hash_map::Entry::Occupied(mut e) => {
889 *e.get_mut() += 1;
890 }
891 }
892 }
893 let mut frequencies: Vec<_> = frequencies.into_iter().collect();
894 frequencies.sort_by_key(|(_, c)| -c);
895
896 let mut trace = String::new();
897 for (t, c) in frequencies.into_iter().take(20) {
898 use std::fmt::Write;
899 let _ = writeln!(&mut trace, "{t} ({c} times)");
900 }
901 trace
902 }
903}
904#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
905struct UpdateContext {
906 app_extension: Option<String>,
907 window_id: Option<WindowId>,
908 widget: Option<(WidgetId, String)>,
909 node_parent: Option<String>,
910 tag: Option<String>,
911}
912impl fmt::Display for UpdateContext {
913 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
914 if let Some(e) = &self.app_extension {
915 write!(f, "{}", e.rsplit("::").next().unwrap())?;
916 } else {
917 write!(f, "<unknown>")?;
918 }
919 if let Some(w) = self.window_id {
920 write!(f, "//{w}")?;
921 }
922 if let Some((id, name)) = &self.widget {
923 write!(f, "/../{name}#{id}")?;
924 }
925 if let Some(p) = &self.node_parent
926 && !p.is_empty()
927 {
928 write!(f, "//{p}")?;
929 }
930 if let Some(t) = &self.tag
931 && !t.is_empty()
932 {
933 write!(f, "//{t}")?;
934 }
935 Ok(())
936 }
937}
938
939#[derive(Debug, PartialEq, Eq, Hash)]
940pub(crate) struct UpdateTrace {
941 ctx: UpdateContext,
942 action: UpdateAction,
943}
944impl fmt::Display for UpdateTrace {
945 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
946 write!(f, "{} {}", self.ctx, self.action)
947 }
948}
949#[derive(Debug, PartialEq, Eq, Hash)]
950enum UpdateAction {
951 Info,
952 Update,
953 Layout,
954 Render,
955 Var { type_name: String },
956 Event { type_name: String },
957 Custom { tag: String },
958}
959impl fmt::Display for UpdateAction {
960 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
961 match self {
962 UpdateAction::Info => write!(f, "info"),
963 UpdateAction::Update => write!(f, "update"),
964 UpdateAction::Layout => write!(f, "layout"),
965 UpdateAction::Render => write!(f, "render"),
966 UpdateAction::Var { type_name } => write!(f, "update var of type {type_name}"),
967 UpdateAction::Event { type_name } => write!(f, "update event {type_name}"),
968 UpdateAction::Custom { tag } => write!(f, "{tag}"),
969 }
970 }
971}
972
973fn visit_str(record: impl FnOnce(&mut dyn tracing::field::Visit), name: &str) -> String {
974 struct Visitor<'a> {
975 name: &'a str,
976 result: String,
977 }
978 impl tracing::field::Visit for Visitor<'_> {
979 fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
980 if field.name() == self.name {
981 self.result = format!("{value:?}");
982 }
983 }
984 fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
985 if field.name() == self.name {
986 value.clone_into(&mut self.result);
987 }
988 }
989 }
990
991 let mut visitor = Visitor {
992 name,
993 result: String::new(),
994 };
995 record(&mut visitor);
996 visitor.result
997}
998fn visit_u64(record: impl FnOnce(&mut dyn tracing::field::Visit), name: &str) -> Option<u64> {
999 struct Visitor<'a> {
1000 name: &'a str,
1001 result: Option<u64>,
1002 }
1003 impl tracing::field::Visit for Visitor<'_> {
1004 fn record_debug(&mut self, _field: &tracing::field::Field, _value: &dyn std::fmt::Debug) {}
1005 fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
1006 if field.name() == self.name {
1007 self.result = Some(value)
1008 }
1009 }
1010 }
1011
1012 let mut visitor = Visitor { name, result: None };
1013 record(&mut visitor);
1014 visitor.result
1015}
1016
1017pub struct UPDATES;
1019impl UPDATES {
1020 pub(crate) fn init(&self, event_sender: AppEventSender) {
1021 UPDATES_SV.write().event_sender = Some(event_sender);
1022 }
1023
1024 #[must_use]
1025 #[cfg(any(test, doc, feature = "test_util"))]
1026 pub(crate) fn apply(&self) -> ContextUpdates {
1027 self.apply_updates() | self.apply_info() | self.apply_layout_render()
1028 }
1029
1030 #[must_use]
1031 pub(crate) fn apply_updates(&self) -> ContextUpdates {
1032 let events = EVENTS.apply_updates();
1033 VARS_APP.apply_updates();
1034
1035 let (update, update_widgets) = UPDATES.take_update();
1036
1037 ContextUpdates {
1038 events,
1039 update,
1040 update_widgets,
1041 info: false,
1042 info_widgets: InfoUpdates::default(),
1043 layout: false,
1044 layout_widgets: LayoutUpdates::default(),
1045 render: false,
1046 render_widgets: RenderUpdates::default(),
1047 render_update_widgets: RenderUpdates::default(),
1048 }
1049 }
1050 #[must_use]
1051 pub(crate) fn apply_info(&self) -> ContextUpdates {
1052 let (info, info_widgets) = UPDATES.take_info();
1053
1054 ContextUpdates {
1055 events: vec![],
1056 update: false,
1057 update_widgets: WidgetUpdates::default(),
1058 info,
1059 info_widgets,
1060 layout: false,
1061 layout_widgets: LayoutUpdates::default(),
1062 render: false,
1063 render_widgets: RenderUpdates::default(),
1064 render_update_widgets: RenderUpdates::default(),
1065 }
1066 }
1067 #[must_use]
1068 pub(crate) fn apply_layout_render(&self) -> ContextUpdates {
1069 let (layout, layout_widgets) = UPDATES.take_layout();
1070 let (render, render_widgets, render_update_widgets) = UPDATES.take_render();
1071
1072 ContextUpdates {
1073 events: vec![],
1074 update: false,
1075 update_widgets: WidgetUpdates::default(),
1076 info: false,
1077 info_widgets: InfoUpdates::default(),
1078 layout,
1079 layout_widgets,
1080 render,
1081 render_widgets,
1082 render_update_widgets,
1083 }
1084 }
1085
1086 pub(crate) fn on_app_awake(&self) {
1087 UPDATES_SV.write().app_awake(true);
1088 }
1089
1090 pub(crate) fn on_app_sleep(&self) {
1091 UPDATES_SV.write().app_awake(false);
1092 }
1093
1094 pub(crate) fn next_deadline(&self, timer: &mut LoopTimer) {
1096 TIMERS_SV.write().next_deadline(timer);
1097 VARS_APP.next_deadline(timer);
1098 }
1099
1100 pub(crate) fn update_timers(&self, timer: &mut LoopTimer) {
1102 TIMERS_SV.write().apply_updates(timer);
1103 VARS_APP.update_animations(timer);
1104 }
1105
1106 #[must_use]
1108 pub(crate) fn has_pending_updates(&self) -> bool {
1109 UPDATES_SV.read().update_ext.intersects(UpdateFlags::UPDATE | UpdateFlags::INFO)
1110 || VARS_APP.has_pending_updates()
1111 || EVENTS_SV.write().has_pending_updates()
1112 || TIMERS_SV.read().has_pending_updates()
1113 }
1114
1115 #[must_use]
1116 pub(crate) fn has_pending_layout_or_render(&self) -> bool {
1117 UPDATES_SV
1118 .read()
1119 .update_ext
1120 .intersects(UpdateFlags::LAYOUT | UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE)
1121 }
1122
1123 pub fn sender(&self) -> AppEventSender {
1125 UPDATES_SV.read().event_sender.as_ref().unwrap().clone()
1126 }
1127
1128 pub fn waker(&self, target: impl Into<Option<WidgetId>>) -> Waker {
1130 UPDATES_SV.read().event_sender.as_ref().unwrap().waker(target)
1131 }
1132
1133 pub(crate) fn update_flags_root(&self, flags: UpdateFlags, window_id: WindowId, root_id: WidgetId) {
1134 if flags.is_empty() {
1135 return;
1136 }
1137
1138 let mut u = UPDATES_SV.write();
1139 if flags.contains(UpdateFlags::UPDATE) {
1140 u.update_widgets.insert_updates_root(window_id, root_id);
1141 }
1142 if flags.contains(UpdateFlags::INFO) {
1143 u.info_widgets.insert_updates_root(window_id, root_id);
1144 }
1145 if flags.contains(UpdateFlags::LAYOUT) {
1146 u.layout_widgets.insert_updates_root(window_id, root_id);
1147 }
1148
1149 if flags.contains(UpdateFlags::RENDER) {
1150 u.render_widgets.insert_updates_root(window_id, root_id);
1151 } else if flags.contains(UpdateFlags::RENDER_UPDATE) {
1152 u.render_update_widgets.insert_updates_root(window_id, root_id);
1153 }
1154
1155 u.update_ext |= flags;
1156 }
1157
1158 pub(crate) fn update_flags(&self, flags: UpdateFlags, target: impl Into<Option<WidgetId>>) {
1159 if flags.is_empty() {
1160 return;
1161 }
1162
1163 let mut u = UPDATES_SV.write();
1164
1165 if let Some(id) = target.into() {
1166 if flags.contains(UpdateFlags::UPDATE) {
1167 u.update_widgets.search_widget(id);
1168 }
1169 if flags.contains(UpdateFlags::INFO) {
1170 u.info_widgets.search_widget(id);
1171 }
1172 if flags.contains(UpdateFlags::LAYOUT) {
1173 u.layout_widgets.search_widget(id);
1174 }
1175
1176 if flags.contains(UpdateFlags::RENDER) {
1177 u.render_widgets.search_widget(id);
1178 } else if flags.contains(UpdateFlags::RENDER_UPDATE) {
1179 u.render_update_widgets.search_widget(id);
1180 }
1181 }
1182
1183 u.update_ext |= flags;
1184 }
1185
1186 pub fn update_op(&self, op: UpdateOp, target: impl Into<Option<WidgetId>>) -> &Self {
1188 let target = target.into();
1189 match op {
1190 UpdateOp::Update => self.update(target),
1191 UpdateOp::Info => self.update_info(target),
1192 UpdateOp::Layout => self.layout(target),
1193 UpdateOp::Render => self.render(target),
1194 UpdateOp::RenderUpdate => self.render_update(target),
1195 }
1196 }
1197
1198 pub fn update_op_window(&self, op: UpdateOp, target: WindowId) -> &Self {
1200 match op {
1201 UpdateOp::Update => self.update_window(target),
1202 UpdateOp::Info => self.update_info_window(target),
1203 UpdateOp::Layout => self.layout_window(target),
1204 UpdateOp::Render => self.render_window(target),
1205 UpdateOp::RenderUpdate => self.render_update_window(target),
1206 }
1207 }
1208
1209 pub fn update(&self, target: impl Into<Option<WidgetId>>) -> &Self {
1213 UpdatesTrace::log_update();
1214 self.update_internal(target.into())
1215 }
1216 pub(crate) fn update_internal(&self, target: Option<WidgetId>) -> &UPDATES {
1218 let mut u = UPDATES_SV.write();
1219 u.update_ext.insert(UpdateFlags::UPDATE);
1220 u.send_awake();
1221 if let Some(id) = target {
1222 u.update_widgets.search_widget(id);
1223 }
1224 self
1225 }
1226
1227 pub fn update_window(&self, target: WindowId) -> &Self {
1229 let mut u = UPDATES_SV.write();
1230 u.update_ext.insert(UpdateFlags::UPDATE);
1231 u.send_awake();
1232 u.update_widgets.insert_window(target);
1233 self
1234 }
1235
1236 pub(crate) fn send_awake(&self) {
1237 UPDATES_SV.write().send_awake();
1238 }
1239
1240 pub fn update_info(&self, target: impl Into<Option<WidgetId>>) -> &Self {
1244 UpdatesTrace::log_info();
1245 let mut u = UPDATES_SV.write();
1246 u.update_ext.insert(UpdateFlags::INFO);
1247 u.send_awake();
1248 if let Some(id) = target.into() {
1249 u.info_widgets.search_widget(id);
1250 }
1251 self
1252 }
1253
1254 pub fn update_info_window(&self, target: WindowId) -> &Self {
1256 UpdatesTrace::log_info();
1257 let mut u = UPDATES_SV.write();
1258 u.update_ext.insert(UpdateFlags::INFO);
1259 u.send_awake();
1260 u.info_widgets.insert_window(target);
1261 self
1262 }
1263
1264 pub fn layout(&self, target: impl Into<Option<WidgetId>>) -> &Self {
1268 UpdatesTrace::log_layout();
1269 let mut u = UPDATES_SV.write();
1270 u.update_ext.insert(UpdateFlags::LAYOUT);
1271 u.send_awake();
1272 if let Some(id) = target.into() {
1273 u.layout_widgets.search_widget(id);
1274 }
1275 self
1276 }
1277
1278 pub fn layout_window(&self, target: WindowId) -> &Self {
1280 UpdatesTrace::log_layout();
1281 let mut u = UPDATES_SV.write();
1282 u.update_ext.insert(UpdateFlags::LAYOUT);
1283 u.send_awake();
1284 u.layout_widgets.insert_window(target);
1285 self
1286 }
1287
1288 pub fn render(&self, target: impl Into<Option<WidgetId>>) -> &Self {
1295 UpdatesTrace::log_render();
1296 let mut u = UPDATES_SV.write();
1297 u.update_ext.insert(UpdateFlags::RENDER);
1298 u.send_awake();
1299 if let Some(id) = target.into() {
1300 u.render_widgets.search_widget(id);
1301 }
1302 self
1303 }
1304
1305 pub fn render_window(&self, target: WindowId) -> &Self {
1307 UpdatesTrace::log_render();
1308 let mut u = UPDATES_SV.write();
1309 u.update_ext.insert(UpdateFlags::RENDER);
1310 u.send_awake();
1311 u.render_widgets.insert_window(target);
1312 self
1313 }
1314
1315 pub fn render_update(&self, target: impl Into<Option<WidgetId>>) -> &Self {
1321 UpdatesTrace::log_render();
1322 let mut u = UPDATES_SV.write();
1323 u.update_ext.insert(UpdateFlags::RENDER_UPDATE);
1324 u.send_awake();
1325 if let Some(id) = target.into() {
1326 u.render_update_widgets.search_widget(id);
1327 }
1328 self
1329 }
1330
1331 pub fn render_update_window(&self, target: WindowId) -> &Self {
1333 UpdatesTrace::log_render();
1334 let mut u = UPDATES_SV.write();
1335 u.update_ext.insert(UpdateFlags::RENDER_UPDATE);
1336 u.send_awake();
1337 u.render_update_widgets.insert_window(target);
1338 self
1339 }
1340
1341 pub fn is_pending_render(&self, window_id: WindowId) -> bool {
1343 let u = UPDATES_SV.read();
1344 u.render_widgets.enter_window(window_id) || u.render_update_widgets.enter_window(window_id)
1345 }
1346
1347 pub fn run<F: Future<Output = ()> + Send + 'static>(&self, future: impl IntoFuture<Output = (), IntoFuture = F>) -> OnUpdateHandle {
1353 let future = future.into_future();
1354 self.run_hn_once(async_hn_once!(|_| future.await))
1355 }
1356
1357 pub fn run_hn_once(&self, handler: Handler<UpdateArgs>) -> OnUpdateHandle {
1364 let mut u = UPDATES_SV.write();
1365 u.update_ext.insert(UpdateFlags::UPDATE);
1366 u.send_awake();
1367 Self::push_handler(u.pre_handlers.get_mut(), true, handler.into_once(), true)
1368 }
1369
1370 pub fn on_pre_update(&self, handler: Handler<UpdateArgs>) -> OnUpdateHandle {
1385 let u = UPDATES_SV.read();
1386 Self::push_handler(&mut u.pre_handlers.lock(), true, handler, false)
1387 }
1388
1389 pub fn on_update(&self, handler: Handler<UpdateArgs>) -> OnUpdateHandle {
1404 let u = UPDATES_SV.read();
1405 Self::push_handler(&mut u.pos_handlers.lock(), false, handler, false)
1406 }
1407
1408 fn push_handler(
1409 entries: &mut Vec<UpdateHandler>,
1410 is_preview: bool,
1411 mut handler: Handler<UpdateArgs>,
1412 force_once: bool,
1413 ) -> OnUpdateHandle {
1414 let (handle_owner, handle) = OnUpdateHandle::new();
1415 entries.push(UpdateHandler {
1416 handle: handle_owner,
1417 count: 0,
1418 handler: Box::new(move |args, handle| {
1419 handler.app_event(handle.clone_boxed(), is_preview, args);
1420 if force_once {
1421 handle.unsubscribe();
1422 }
1423 }),
1424 });
1425 handle
1426 }
1427
1428 pub(crate) fn on_pre_updates(&self) {
1429 let _s = tracing::trace_span!("UPDATES.on_pre_updates");
1430 let mut handlers = mem::take(UPDATES_SV.write().pre_handlers.get_mut());
1431 Self::retain_updates(&mut handlers);
1432
1433 let mut u = UPDATES_SV.write();
1434 handlers.append(u.pre_handlers.get_mut());
1435 *u.pre_handlers.get_mut() = handlers;
1436 }
1437
1438 pub(crate) fn on_updates(&self) {
1439 let _s = tracing::trace_span!("UPDATES.on_updates");
1440 let mut handlers = mem::take(UPDATES_SV.write().pos_handlers.get_mut());
1441 Self::retain_updates(&mut handlers);
1442
1443 let mut u = UPDATES_SV.write();
1444 handlers.append(u.pos_handlers.get_mut());
1445 *u.pos_handlers.get_mut() = handlers;
1446 }
1447
1448 fn retain_updates(handlers: &mut Vec<UpdateHandler>) {
1449 handlers.retain_mut(|e| {
1450 !e.handle.is_dropped() && {
1451 e.count = e.count.wrapping_add(1);
1452 (e.handler)(&UpdateArgs { count: e.count }, &e.handle.weak_handle());
1453 !e.handle.is_dropped()
1454 }
1455 });
1456 }
1457
1458 pub(super) fn take_update(&self) -> (bool, WidgetUpdates) {
1460 let mut u = UPDATES_SV.write();
1461
1462 let ext = u.update_ext.contains(UpdateFlags::UPDATE);
1463 u.update_ext.remove(UpdateFlags::UPDATE);
1464
1465 (
1466 ext,
1467 WidgetUpdates {
1468 delivery_list: mem::take(&mut u.update_widgets),
1469 },
1470 )
1471 }
1472
1473 pub(super) fn take_info(&self) -> (bool, InfoUpdates) {
1475 let mut u = UPDATES_SV.write();
1476
1477 let ext = u.update_ext.contains(UpdateFlags::INFO);
1478 u.update_ext.remove(UpdateFlags::INFO);
1479
1480 (
1481 ext,
1482 InfoUpdates {
1483 delivery_list: mem::take(&mut u.info_widgets),
1484 },
1485 )
1486 }
1487
1488 pub(super) fn take_layout(&self) -> (bool, LayoutUpdates) {
1490 let mut u = UPDATES_SV.write();
1491
1492 let ext = u.update_ext.contains(UpdateFlags::LAYOUT);
1493 u.update_ext.remove(UpdateFlags::LAYOUT);
1494
1495 (
1496 ext,
1497 LayoutUpdates {
1498 delivery_list: mem::take(&mut u.layout_widgets),
1499 },
1500 )
1501 }
1502
1503 pub(super) fn take_render(&self) -> (bool, RenderUpdates, RenderUpdates) {
1505 let mut u = UPDATES_SV.write();
1506
1507 let ext = u.update_ext.intersects(UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE);
1508 u.update_ext.remove(UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE);
1509
1510 (
1511 ext,
1512 RenderUpdates {
1513 delivery_list: mem::take(&mut u.render_widgets),
1514 },
1515 RenderUpdates {
1516 delivery_list: mem::take(&mut u.render_update_widgets),
1517 },
1518 )
1519 }
1520
1521 pub(crate) fn handler_lens(&self) -> (usize, usize) {
1522 let u = UPDATES_SV.read();
1523
1524 (u.pre_handlers.lock().len(), u.pos_handlers.lock().len())
1525 }
1526 pub(crate) fn new_update_handlers(&self, pre_from: usize, pos_from: usize) -> Vec<Box<dyn Fn() -> bool>> {
1527 let u = UPDATES_SV.read();
1528
1529 u.pre_handlers
1530 .lock()
1531 .iter()
1532 .skip(pre_from)
1533 .chain(u.pos_handlers.lock().iter().skip(pos_from))
1534 .map(|h| h.handle.weak_handle())
1535 .map(|h| {
1536 let r: Box<dyn Fn() -> bool> = Box::new(move || h.upgrade().is_some());
1537 r
1538 })
1539 .collect()
1540 }
1541}
1542
1543app_local! {
1544 static UPDATES_SV: UpdatesService = UpdatesService::new();
1545}
1546struct UpdatesService {
1547 event_sender: Option<AppEventSender>,
1548
1549 update_ext: UpdateFlags,
1550 update_widgets: UpdateDeliveryList,
1551 info_widgets: UpdateDeliveryList,
1552 layout_widgets: UpdateDeliveryList,
1553 render_widgets: UpdateDeliveryList,
1554 render_update_widgets: UpdateDeliveryList,
1555
1556 pre_handlers: Mutex<Vec<UpdateHandler>>,
1557 pos_handlers: Mutex<Vec<UpdateHandler>>,
1558
1559 app_is_awake: bool,
1560 awake_pending: bool,
1561}
1562impl UpdatesService {
1563 fn new() -> Self {
1564 Self {
1565 event_sender: None,
1566 update_ext: UpdateFlags::empty(),
1567 update_widgets: UpdateDeliveryList::new_any(),
1568 info_widgets: UpdateDeliveryList::new_any(),
1569 layout_widgets: UpdateDeliveryList::new_any(),
1570 render_widgets: UpdateDeliveryList::new_any(),
1571 render_update_widgets: UpdateDeliveryList::new_any(),
1572
1573 pre_handlers: Mutex::new(vec![]),
1574 pos_handlers: Mutex::new(vec![]),
1575
1576 app_is_awake: false,
1577 awake_pending: false,
1578 }
1579 }
1580
1581 fn send_awake(&mut self) {
1582 if !self.app_is_awake && !self.awake_pending {
1583 self.awake_pending = true;
1584 match self.event_sender.as_ref() {
1585 Some(s) => {
1586 if let Err(AppChannelError::Disconnected) = s.send_check_update() {
1587 tracing::debug!("no app connected to update");
1588 }
1589 }
1590 None => {
1591 tracing::debug!("no app connected yet to update");
1592 }
1593 }
1594 }
1595 }
1596
1597 fn app_awake(&mut self, wake: bool) {
1598 self.awake_pending = false;
1599 self.app_is_awake = wake;
1600 }
1601}
1602
1603#[non_exhaustive]
1607#[derive(Default)]
1608pub struct ContextUpdates {
1609 pub events: Vec<EventUpdate>,
1613
1614 pub update: bool,
1619
1620 pub info: bool,
1625
1626 pub layout: bool,
1631
1632 pub render: bool,
1637
1638 pub update_widgets: WidgetUpdates,
1642
1643 pub info_widgets: InfoUpdates,
1647
1648 pub layout_widgets: LayoutUpdates,
1652
1653 pub render_widgets: RenderUpdates,
1657
1658 pub render_update_widgets: RenderUpdates,
1662}
1663
1664impl fmt::Debug for ContextUpdates {
1665 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1666 if f.alternate() {
1667 f.debug_struct("ContextUpdates")
1668 .field("update", &self.update)
1669 .field("info", &self.info)
1670 .field("layout", &self.layout)
1671 .field("render", &self.render)
1672 .field("events", &self.events)
1673 .field("update_widgets", &self.update_widgets)
1674 .field("info_widgets", &self.info_widgets)
1675 .field("layout_widgets", &self.layout_widgets)
1676 .field("render_widgets", &self.render_widgets)
1677 .field("render_update_widgets", &self.render_update_widgets)
1678 .finish()
1679 } else {
1680 write!(f, "ContextUpdates: ")?;
1681 let mut sep = "";
1682 if !self.events.is_empty() {
1683 write!(f, "{sep}events[")?;
1684 for e in &self.events {
1685 write!(f, "{sep}{}", e.event.name())?;
1686 sep = ", ";
1687 }
1688 write!(f, "]")?;
1689 }
1690 if self.update {
1691 write!(f, "{sep}update")?;
1692 sep = ", ";
1693 }
1694 if self.info {
1695 write!(f, "{sep}info")?;
1696 sep = ", ";
1697 }
1698 if self.layout {
1699 write!(f, "{sep}layout")?;
1700 sep = ", ";
1701 }
1702 if self.render {
1703 write!(f, "{sep}render")?;
1704 sep = ", ";
1705 }
1706 if sep.is_empty() {
1707 write!(f, "<none>")?;
1708 }
1709 Ok(())
1710 }
1711 }
1712}
1713impl ContextUpdates {
1714 pub fn has_updates(&self) -> bool {
1716 !self.events.is_empty() || self.update || self.info || self.layout || self.render
1717 }
1718}
1719impl std::ops::BitOrAssign for ContextUpdates {
1720 fn bitor_assign(&mut self, rhs: Self) {
1721 self.events.extend(rhs.events);
1722 self.update |= rhs.update;
1723 self.update_widgets.extend(rhs.update_widgets);
1724 self.info |= rhs.info;
1725 self.info_widgets.extend(rhs.info_widgets);
1726 self.layout |= rhs.layout;
1727 self.layout_widgets.extend(rhs.layout_widgets);
1728 self.render |= rhs.render;
1729 self.render_widgets.extend(rhs.render_widgets);
1730 self.render_update_widgets.extend(rhs.render_update_widgets);
1731 }
1732}
1733impl std::ops::BitOr for ContextUpdates {
1734 type Output = Self;
1735
1736 fn bitor(mut self, rhs: Self) -> Self {
1737 self |= rhs;
1738 self
1739 }
1740}
1741
1742bitflags::bitflags! {
1743 #[derive(Clone, Copy, Debug, bytemuck::NoUninit)]
1744 #[repr(transparent)]
1745 pub(crate) struct UpdateFlags: u8 {
1746 const REINIT = 0b1000_0000;
1747 const INFO = 0b0001_0000;
1748 const UPDATE = 0b0000_0001;
1749 const LAYOUT = 0b0000_0010;
1750 const RENDER = 0b0000_0100;
1751 const RENDER_UPDATE = 0b0000_1000;
1752 }
1753}
1754
1755#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1760#[repr(transparent)]
1761#[must_use = "dropping the handle unsubscribes update handler"]
1762pub struct OnUpdateHandle(Handle<()>);
1763impl OnUpdateHandle {
1764 fn new() -> (HandleOwner<()>, OnUpdateHandle) {
1765 let (owner, handle) = Handle::new(());
1766 (owner, OnUpdateHandle(handle))
1767 }
1768
1769 pub fn dummy() -> Self {
1773 OnUpdateHandle(Handle::dummy(()))
1774 }
1775
1776 pub fn perm(self) {
1780 self.0.perm();
1781 }
1782
1783 pub fn is_permanent(&self) -> bool {
1787 self.0.is_permanent()
1788 }
1789
1790 pub fn unsubscribe(self) {
1792 self.0.force_drop()
1793 }
1794
1795 pub fn is_unsubscribed(&self) -> bool {
1799 self.0.is_dropped()
1800 }
1801
1802 pub fn downgrade(&self) -> WeakOnUpdateHandle {
1804 WeakOnUpdateHandle(self.0.downgrade())
1805 }
1806}
1807
1808#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)]
1810pub struct WeakOnUpdateHandle(WeakHandle<()>);
1811impl WeakOnUpdateHandle {
1812 pub fn new() -> Self {
1814 Self(WeakHandle::new())
1815 }
1816
1817 pub fn upgrade(&self) -> Option<OnUpdateHandle> {
1819 self.0.upgrade().map(OnUpdateHandle)
1820 }
1821}
1822
1823#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1825pub enum UpdateOp {
1826 Update,
1834 Info,
1843 Layout,
1851 Render,
1859 RenderUpdate,
1870}
1871
1872#[derive(Debug, Clone, Copy)]
1874#[non_exhaustive]
1875pub struct UpdateArgs {
1876 pub count: usize,
1878}
1879
1880struct UpdateHandler {
1881 handle: HandleOwner<()>,
1882 count: usize,
1883 handler: Box<dyn FnMut(&UpdateArgs, &dyn AppWeakHandle) + Send>,
1884}