1use std::{
4 collections::{HashMap, hash_map},
5 fmt, mem,
6 sync::Arc,
7 task::Waker,
8};
9
10use parking_lot::Mutex;
11use zng_app_context::app_local;
12use zng_handle::{Handle, HandleOwner, WeakHandle};
13use zng_task::channel::ChannelError;
14use zng_unique_id::IdSet;
15use zng_var::{VARS, VARS_APP};
16
17use crate::{
18 AppEventSender, LoopTimer, async_hn_once,
19 handler::{AppWeakHandle, Handler, HandlerExt as _},
20 hn_once,
21 timer::TIMERS_SV,
22 widget::{
23 WIDGET, WidgetId,
24 info::{InteractionPath, WidgetInfo, WidgetInfoTree, WidgetPath},
25 node::UiNode,
26 },
27 window::{WINDOW, WindowId},
28};
29
30pub struct UpdateDeliveryList {
32 windows: IdSet<WindowId>,
33 widgets: IdSet<WidgetId>,
34 search: IdSet<WidgetId>,
35 search_root: bool,
36}
37impl fmt::Debug for UpdateDeliveryList {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 f.debug_struct("UpdateDeliveryList")
40 .field("windows", &self.windows)
41 .field("widgets", &self.widgets)
42 .field("search", &self.search)
43 .finish_non_exhaustive()
44 }
45}
46impl Default for UpdateDeliveryList {
47 fn default() -> Self {
48 Self::new()
49 }
50}
51impl UpdateDeliveryList {
52 pub fn new() -> Self {
54 Self {
55 windows: IdSet::default(),
56 widgets: IdSet::default(),
57 search: IdSet::default(),
58 search_root: false,
59 }
60 }
61
62 pub(crate) fn insert_updates_root(&mut self, window_id: WindowId, root_id: WidgetId) {
63 self.windows.insert(window_id);
64 self.widgets.insert(root_id);
65 }
66
67 pub fn insert_wgt(&mut self, wgt: &impl WidgetPathProvider) {
69 for w in wgt.widget_and_ancestors() {
70 self.widgets.insert(w);
71 }
72 self.windows.insert(wgt.window_id());
73 }
74
75 pub fn insert_window(&mut self, id: WindowId) {
77 self.windows.insert(id);
78 self.search_root = true;
79 }
80
81 pub fn search_widget(&mut self, widget_id: WidgetId) {
83 self.search.insert(widget_id);
84 }
85
86 pub fn has_pending_search(&mut self) -> bool {
88 self.search_root || !self.search.is_empty()
89 }
90
91 pub fn fulfill_search<'a, 'b>(&'a mut self, windows: impl Iterator<Item = &'b WidgetInfoTree>) {
93 for window in windows {
94 if self.search_root && self.windows.contains(&window.window_id()) {
95 self.widgets.insert(window.root().id());
96 }
97
98 self.search.retain(|w| {
99 if let Some(w) = window.get(*w) {
100 for w in w.widget_and_ancestors() {
101 self.widgets.insert(w);
102 }
103 self.windows.insert(w.window_id());
104 false
105 } else {
106 true
107 }
108 });
109 }
110 self.search.clear();
111 self.search_root = true;
112 }
113
114 fn extend_unchecked(&mut self, other: UpdateDeliveryList) {
116 if self.windows.is_empty() {
117 self.windows = other.windows;
118 } else {
119 self.windows.extend(other.windows);
120 }
121
122 if self.widgets.is_empty() {
123 self.widgets = other.widgets;
124 } else {
125 self.widgets.extend(other.widgets);
126 }
127
128 if self.search.is_empty() {
129 self.search = other.search;
130 } else {
131 self.search.extend(other.search);
132 }
133 }
134
135 pub fn enter_window(&self, window_id: WindowId) -> bool {
137 self.windows.contains(&window_id)
138 }
139
140 pub fn enter_widget(&self, widget_id: WidgetId) -> bool {
142 self.widgets.contains(&widget_id)
143 }
144
145 pub fn windows(&self) -> &IdSet<WindowId> {
147 &self.windows
148 }
149
150 pub fn widgets(&self) -> &IdSet<WidgetId> {
152 &self.widgets
153 }
154
155 #[must_use = "use `search_all` to request search"]
157 pub fn search_widgets(&mut self) -> &IdSet<WidgetId> {
158 &self.search
159 }
160
161 #[must_use = "use `search_widget` to request search"]
163 pub fn search_root(&mut self) -> bool {
164 self.search_root
165 }
166}
167
168pub trait WidgetPathProvider {
170 type WidgetIter<'s>: Iterator<Item = WidgetId>
172 where
173 Self: 's;
174
175 fn window_id(&self) -> WindowId;
177 fn widget_and_ancestors(&self) -> Self::WidgetIter<'_>;
179}
180impl WidgetPathProvider for WidgetInfo {
181 type WidgetIter<'s> = std::iter::Map<crate::widget::info::iter::Ancestors, fn(WidgetInfo) -> WidgetId>;
182
183 fn window_id(&self) -> WindowId {
184 self.tree().window_id()
185 }
186
187 fn widget_and_ancestors(&self) -> Self::WidgetIter<'_> {
188 fn wgt_to_id(wgt: WidgetInfo) -> WidgetId {
189 wgt.id()
190 }
191 self.self_and_ancestors().map(wgt_to_id)
192 }
193}
194impl WidgetPathProvider for WidgetPath {
195 type WidgetIter<'s> = std::iter::Rev<std::iter::Copied<std::slice::Iter<'s, WidgetId>>>;
196
197 fn window_id(&self) -> WindowId {
198 self.window_id()
199 }
200
201 fn widget_and_ancestors(&self) -> Self::WidgetIter<'_> {
202 self.widgets_path().iter().copied().rev()
203 }
204}
205impl WidgetPathProvider for InteractionPath {
206 type WidgetIter<'s> = std::iter::Rev<std::iter::Copied<std::slice::Iter<'s, WidgetId>>>;
207
208 fn window_id(&self) -> WindowId {
209 WidgetPath::window_id(self)
210 }
211
212 fn widget_and_ancestors(&self) -> Self::WidgetIter<'_> {
213 self.widgets_path().iter().copied().rev()
214 }
215}
216
217#[derive(Debug, Default)]
219pub struct InfoUpdates {
220 delivery_list: UpdateDeliveryList,
221}
222impl InfoUpdates {
223 pub fn new(delivery_list: UpdateDeliveryList) -> Self {
225 Self { delivery_list }
226 }
227
228 pub fn delivery_list(&self) -> &UpdateDeliveryList {
230 &self.delivery_list
231 }
232
233 pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
235 &mut self.delivery_list
236 }
237
238 pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
240 where
241 H: FnOnce() -> R,
242 {
243 if self.delivery_list.enter_window(window_id) {
244 Some(handle())
245 } else {
246 None
247 }
248 }
249
250 pub fn extend(&mut self, other: InfoUpdates) {
252 self.delivery_list.extend_unchecked(other.delivery_list)
253 }
254}
255
256#[derive(Debug, Default)]
258pub struct WidgetUpdates {
259 pub(crate) delivery_list: UpdateDeliveryList,
260}
261impl WidgetUpdates {
262 pub fn new(delivery_list: UpdateDeliveryList) -> Self {
264 Self { delivery_list }
265 }
266
267 pub fn delivery_list(&self) -> &UpdateDeliveryList {
269 &self.delivery_list
270 }
271
272 pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
274 &mut self.delivery_list
275 }
276
277 pub fn with_window<H, R>(&self, handle: H) -> Option<R>
279 where
280 H: FnOnce() -> R,
281 {
282 if self.delivery_list.enter_window(WINDOW.id()) {
283 Some(handle())
284 } else {
285 None
286 }
287 }
288
289 pub fn with_widget<H, R>(&self, handle: H) -> Option<R>
291 where
292 H: FnOnce() -> R,
293 {
294 if WIDGET.take_update(UpdateFlags::UPDATE) || self.delivery_list.enter_widget(WIDGET.id()) {
295 Some(handle())
296 } else {
297 None
298 }
299 }
300
301 pub fn extend(&mut self, other: WidgetUpdates) {
303 self.delivery_list.extend_unchecked(other.delivery_list)
304 }
305}
306
307#[derive(Debug, Default)]
309pub struct LayoutUpdates {
310 pub(crate) delivery_list: UpdateDeliveryList,
311}
312impl LayoutUpdates {
313 pub fn new(delivery_list: UpdateDeliveryList) -> Self {
315 Self { delivery_list }
316 }
317
318 pub fn delivery_list(&self) -> &UpdateDeliveryList {
320 &self.delivery_list
321 }
322
323 pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
325 &mut self.delivery_list
326 }
327
328 pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
330 where
331 H: FnOnce() -> R,
332 {
333 if self.delivery_list.enter_window(window_id) {
334 Some(handle())
335 } else {
336 None
337 }
338 }
339
340 pub fn extend(&mut self, other: LayoutUpdates) {
342 self.delivery_list.extend_unchecked(other.delivery_list)
343 }
344}
345
346#[derive(Debug, Default)]
348pub struct RenderUpdates {
349 delivery_list: UpdateDeliveryList,
350}
351impl RenderUpdates {
352 pub fn new(delivery_list: UpdateDeliveryList) -> Self {
354 Self { delivery_list }
355 }
356
357 pub fn delivery_list(&self) -> &UpdateDeliveryList {
359 &self.delivery_list
360 }
361
362 pub fn delivery_list_mut(&mut self) -> &mut UpdateDeliveryList {
364 &mut self.delivery_list
365 }
366
367 pub fn with_window<H, R>(&self, window_id: WindowId, handle: H) -> Option<R>
369 where
370 H: FnOnce() -> R,
371 {
372 if self.delivery_list.enter_window(window_id) {
373 Some(handle())
374 } else {
375 None
376 }
377 }
378
379 pub fn extend(&mut self, other: RenderUpdates) {
381 self.delivery_list.extend_unchecked(other.delivery_list)
382 }
383}
384
385pub trait UpdatesTraceUiNodeExt {
389 fn instrument<S: Into<String>>(self, tag: S) -> UiNode
391 where
392 Self: Sized;
393}
394impl UpdatesTraceUiNodeExt for UiNode {
395 fn instrument<S: Into<String>>(self, tag: S) -> UiNode {
396 let tag = tag.into();
397 self.trace(move |op| UpdatesTrace::custom_span(&tag, op.mtd_name()))
398 }
399}
400
401pub fn updates_trace_span(tag: &'static str) -> tracing::span::EnteredSpan {
405 UpdatesTrace::custom_span(tag, "")
406}
407
408pub fn updates_trace_event(tag: &str) {
412 UpdatesTrace::log_custom(tag)
413}
414
415pub(crate) struct UpdatesTrace {
416 context: Mutex<UpdateContext>,
417 trace: Arc<Mutex<Vec<UpdateTrace>>>,
418
419 widgets_stack: Mutex<Vec<(WidgetId, String)>>,
420 node_parents_stack: Mutex<Vec<String>>,
421 tags_stack: Mutex<Vec<String>>,
422}
423impl tracing::subscriber::Subscriber for UpdatesTrace {
424 fn enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
425 metadata.target() == Self::UPDATES_TARGET
426 }
427
428 fn new_span(&self, span: &tracing::span::Attributes<'_>) -> tracing::span::Id {
429 match span.metadata().name() {
430 "property" | "intrinsic" => {
431 let name = visit_str(|v| span.record(v), "name");
432 let mut ctx = self.context.lock();
433
434 if let Some(p) = ctx.node_parent.replace(name) {
435 self.node_parents_stack.lock().push(p);
436 }
437 if let Some(p) = ctx.tag.replace(String::new()) {
438 self.tags_stack.lock().push(p);
439 }
440
441 tracing::span::Id::from_u64(1)
442 }
443 "widget" => {
444 let id = visit_u64(|v| span.record(v), "raw_id").unwrap();
445 if id == 0 {
446 panic!()
447 }
448 let id = WidgetId::from_raw(id);
449
450 let name = visit_str(|v| span.record(v), "name");
451
452 let mut ctx = self.context.lock();
453 if let Some(p) = ctx.widget.replace((id, name)) {
454 self.widgets_stack.lock().push(p);
455 }
456
457 if let Some(p) = ctx.node_parent.replace(String::new()) {
458 self.node_parents_stack.lock().push(p);
459 }
460
461 if let Some(p) = ctx.tag.replace(String::new()) {
462 self.tags_stack.lock().push(p);
463 }
464
465 tracing::span::Id::from_u64(2)
466 }
467 "Window" => {
468 let id = visit_u64(|v| span.record(v), "raw_id").unwrap() as u32;
469 if id == 0 {
470 panic!()
471 }
472 let id = WindowId::from_raw(id);
473
474 let mut ctx = self.context.lock();
475 ctx.window_id = Some(id);
476
477 if let Some(p) = ctx.tag.replace(String::new()) {
478 self.tags_stack.lock().push(p);
479 }
480
481 tracing::span::Id::from_u64(3)
482 }
483 "tag" => {
484 let tag = visit_str(|v| span.record(v), "tag");
485 let mut ctx = self.context.lock();
486 if let Some(p) = ctx.tag.replace(tag) {
487 self.tags_stack.lock().push(p);
488 }
489 tracing::span::Id::from_u64(5)
490 }
491 _ => tracing::span::Id::from_u64(u64::MAX),
492 }
493 }
494
495 fn record(&self, _span: &tracing::span::Id, _values: &tracing::span::Record<'_>) {}
496
497 fn record_follows_from(&self, _span: &tracing::span::Id, _follows: &tracing::span::Id) {}
498
499 fn event(&self, event: &tracing::Event<'_>) {
500 let action = match visit_str(|v| event.record(v), "kind").as_str() {
501 "var" => UpdateAction::Var {
502 type_name: visit_str(|v| event.record(v), "type_name"),
503 },
504 "request" => UpdateAction::Update,
505 "info" => UpdateAction::Info,
506 "layout" => UpdateAction::Layout,
507 "render" => UpdateAction::Render,
508 "custom" => UpdateAction::Custom {
509 tag: visit_str(|v| event.record(v), "tag"),
510 },
511 _ => return,
512 };
513
514 let ctx = self.context.lock().clone();
515 let entry = UpdateTrace { ctx, action };
520 self.trace.lock().push(entry);
521 }
522
523 fn enter(&self, _span: &tracing::span::Id) {}
524
525 fn exit(&self, span: &tracing::span::Id) {
526 let mut ctx = self.context.lock();
527 if span == &tracing::span::Id::from_u64(1) {
528 ctx.node_parent = self.node_parents_stack.lock().pop();
529 ctx.tag = self.tags_stack.lock().pop();
530 } else if span == &tracing::span::Id::from_u64(2) {
531 ctx.widget = self.widgets_stack.lock().pop();
532 ctx.node_parent = self.node_parents_stack.lock().pop();
533 ctx.tag = self.tags_stack.lock().pop();
534 } else if span == &tracing::span::Id::from_u64(3) {
535 ctx.window_id = None;
536 ctx.tag = self.tags_stack.lock().pop();
537 } else if span == &tracing::span::Id::from_u64(4) {
538 ctx.app_extension = None;
539 ctx.tag = self.tags_stack.lock().pop();
540 } else if span == &tracing::span::Id::from_u64(5) {
541 ctx.tag = self.tags_stack.lock().pop();
542 }
543 }
544}
545impl UpdatesTrace {
546 const UPDATES_TARGET: &'static str = "zng-updates";
547
548 fn new() -> Self {
549 UpdatesTrace {
550 context: Mutex::new(UpdateContext::default()),
551 trace: Arc::new(Mutex::new(Vec::with_capacity(100))),
552 widgets_stack: Mutex::new(Vec::with_capacity(100)),
553 node_parents_stack: Mutex::new(Vec::with_capacity(100)),
554 tags_stack: Mutex::new(Vec::new()),
555 }
556 }
557
558 pub fn window_span(id: WindowId) -> tracing::span::EnteredSpan {
560 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "Window", %id, raw_id = id.get() as u64).entered()
561 }
562
563 #[cfg(feature = "trace_widget")]
565 pub fn widget_span(id: WidgetId, name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
566 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "widget", %id, raw_id = id.get(), name, %node_mtd).entered()
567 }
568
569 #[cfg(feature = "trace_wgt_item")]
571 pub fn property_span(name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
572 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "property", name, %node_mtd).entered()
573 }
574
575 #[cfg(feature = "trace_wgt_item")]
577 pub fn intrinsic_span(name: &'static str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
578 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "intrinsic", name, %node_mtd).entered()
579 }
580
581 pub fn custom_span(name: &str, node_mtd: &'static str) -> tracing::span::EnteredSpan {
583 tracing::trace_span!(target: UpdatesTrace::UPDATES_TARGET, "tag", %name, %node_mtd).entered()
584 }
585
586 pub fn log_update() {
588 tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
589 kind = "update"
590 });
591 }
592
593 pub fn log_info() {
595 tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
596 kind = "info"
597 });
598 }
599
600 pub fn log_layout() {
602 tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
603 kind = "layout"
604 });
605 }
606
607 pub fn log_render() {
609 tracing::event!(target: UpdatesTrace::UPDATES_TARGET, tracing::Level::TRACE, {
610 kind = "render"
611 });
612 }
613
614 pub fn log_custom(tag: &str) {
616 tracing::event!(
617 target: UpdatesTrace::UPDATES_TARGET,
618 tracing::Level::TRACE,
619 { kind = "custom", %tag }
620 );
621 }
622
623 pub fn log_var(type_name: &str) {
625 tracing::event!(
626 target: UpdatesTrace::UPDATES_TARGET,
627 tracing::Level::TRACE,
628 { kind = "var", type_name = pretty_type_name::pretty_type_name_str(type_name) }
629 );
630 }
631
632 pub fn collect_trace<R>(trace: &mut Vec<UpdateTrace>, action: impl FnOnce() -> R) -> R {
634 let tracer = UpdatesTrace::new();
635 let result = Arc::clone(&tracer.trace);
636 let r = tracing::subscriber::with_default(tracer, action);
637 trace.extend(Arc::try_unwrap(result).unwrap().into_inner());
638
639 r
640 }
641
642 pub fn format_trace(trace: Vec<UpdateTrace>) -> String {
644 let mut frequencies = HashMap::with_capacity(50);
645 for t in trace {
646 match frequencies.entry(t) {
647 hash_map::Entry::Vacant(e) => {
648 e.insert(1);
649 }
650 hash_map::Entry::Occupied(mut e) => {
651 *e.get_mut() += 1;
652 }
653 }
654 }
655 let mut frequencies: Vec<_> = frequencies.into_iter().collect();
656 frequencies.sort_by_key(|(_, c)| -c);
657
658 let mut trace = String::new();
659 for (t, c) in frequencies.into_iter().take(20) {
660 use std::fmt::Write;
661 let _ = writeln!(&mut trace, "{t} ({c} times)");
662 }
663 trace
664 }
665}
666#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
667struct UpdateContext {
668 app_extension: Option<String>,
669 window_id: Option<WindowId>,
670 widget: Option<(WidgetId, String)>,
671 node_parent: Option<String>,
672 tag: Option<String>,
673}
674impl fmt::Display for UpdateContext {
675 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
676 if let Some(e) = &self.app_extension {
677 write!(f, "{}", e.rsplit("::").next().unwrap())?;
678 } else {
679 write!(f, "<unknown>")?;
680 }
681 if let Some(w) = self.window_id {
682 write!(f, "//{w}")?;
683 }
684 if let Some((id, name)) = &self.widget {
685 write!(f, "/../{name}#{id}")?;
686 }
687 if let Some(p) = &self.node_parent
688 && !p.is_empty()
689 {
690 write!(f, "//{p}")?;
691 }
692 if let Some(t) = &self.tag
693 && !t.is_empty()
694 {
695 write!(f, "//{t}")?;
696 }
697 Ok(())
698 }
699}
700
701#[derive(Debug, PartialEq, Eq, Hash)]
702pub(crate) struct UpdateTrace {
703 ctx: UpdateContext,
704 action: UpdateAction,
705}
706impl fmt::Display for UpdateTrace {
707 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
708 write!(f, "{} {}", self.ctx, self.action)
709 }
710}
711#[derive(Debug, PartialEq, Eq, Hash)]
712enum UpdateAction {
713 Info,
714 Update,
715 Layout,
716 Render,
717 Var { type_name: String },
718 Custom { tag: String },
719}
720impl fmt::Display for UpdateAction {
721 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
722 match self {
723 UpdateAction::Info => write!(f, "info"),
724 UpdateAction::Update => write!(f, "update"),
725 UpdateAction::Layout => write!(f, "layout"),
726 UpdateAction::Render => write!(f, "render"),
727 UpdateAction::Var { type_name } => write!(f, "update {type_name}"),
728 UpdateAction::Custom { tag } => write!(f, "{tag}"),
729 }
730 }
731}
732
733fn visit_str(record: impl FnOnce(&mut dyn tracing::field::Visit), name: &str) -> String {
734 struct Visitor<'a> {
735 name: &'a str,
736 result: String,
737 }
738 impl tracing::field::Visit for Visitor<'_> {
739 fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
740 if field.name() == self.name {
741 self.result = format!("{value:?}");
742 }
743 }
744 fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
745 if field.name() == self.name {
746 value.clone_into(&mut self.result);
747 }
748 }
749 }
750
751 let mut visitor = Visitor {
752 name,
753 result: String::new(),
754 };
755 record(&mut visitor);
756 visitor.result
757}
758fn visit_u64(record: impl FnOnce(&mut dyn tracing::field::Visit), name: &str) -> Option<u64> {
759 struct Visitor<'a> {
760 name: &'a str,
761 result: Option<u64>,
762 }
763 impl tracing::field::Visit for Visitor<'_> {
764 fn record_debug(&mut self, _field: &tracing::field::Field, _value: &dyn std::fmt::Debug) {}
765 fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
766 if field.name() == self.name {
767 self.result = Some(value)
768 }
769 }
770 }
771
772 let mut visitor = Visitor { name, result: None };
773 record(&mut visitor);
774 visitor.result
775}
776
777pub struct UPDATES;
779impl UPDATES {
780 pub(crate) fn init(&self, event_sender: AppEventSender) {
781 UPDATES_SV.write().event_sender = Some(event_sender);
782 }
783
784 #[must_use]
785 #[cfg(any(test, doc, feature = "test_util"))]
786 pub(crate) fn apply(&self) -> ContextUpdates {
787 self.apply_updates() | self.apply_info() | self.apply_layout_render()
788 }
789
790 #[must_use]
791 pub(crate) fn apply_updates(&self) -> ContextUpdates {
792 VARS_APP.apply_updates();
793
794 let (update, update_widgets) = UPDATES.take_update();
795
796 ContextUpdates {
797 update,
798 update_widgets,
799 info: false,
800 info_widgets: InfoUpdates::default(),
801 layout: false,
802 layout_widgets: LayoutUpdates::default(),
803 render: false,
804 render_widgets: RenderUpdates::default(),
805 render_update_widgets: RenderUpdates::default(),
806 }
807 }
808 #[must_use]
809 pub(crate) fn apply_info(&self) -> ContextUpdates {
810 let (info, info_widgets) = UPDATES.take_info();
811
812 ContextUpdates {
813 update: false,
814 update_widgets: WidgetUpdates::default(),
815 info,
816 info_widgets,
817 layout: false,
818 layout_widgets: LayoutUpdates::default(),
819 render: false,
820 render_widgets: RenderUpdates::default(),
821 render_update_widgets: RenderUpdates::default(),
822 }
823 }
824 #[must_use]
825 pub(crate) fn apply_layout_render(&self) -> ContextUpdates {
826 let (layout, layout_widgets) = UPDATES.take_layout();
827 let (render, render_widgets, render_update_widgets) = UPDATES.take_render();
828
829 ContextUpdates {
830 update: false,
831 update_widgets: WidgetUpdates::default(),
832 info: false,
833 info_widgets: InfoUpdates::default(),
834 layout,
835 layout_widgets,
836 render,
837 render_widgets,
838 render_update_widgets,
839 }
840 }
841
842 pub(crate) fn on_app_awake(&self) {
843 UPDATES_SV.write().app_awake(true);
844 }
845
846 pub(crate) fn on_app_sleep(&self) {
847 UPDATES_SV.write().app_awake(false);
848 }
849
850 pub(crate) fn next_deadline(&self, timer: &mut LoopTimer) {
852 TIMERS_SV.write().next_deadline(timer);
853 VARS_APP.next_deadline(timer);
854 }
855
856 pub(crate) fn update_timers(&self, timer: &mut LoopTimer) {
858 TIMERS_SV.write().apply_updates(timer);
859 VARS_APP.update_animations(timer);
860 }
861
862 #[must_use]
864 pub(crate) fn has_pending_updates(&self) -> bool {
865 UPDATES_SV.read().update_ext.intersects(UpdateFlags::UPDATE | UpdateFlags::INFO)
866 || VARS_APP.has_pending_updates()
867 || TIMERS_SV.read().has_pending_updates()
868 }
869
870 #[must_use]
871 pub(crate) fn has_pending_layout_or_render(&self) -> bool {
872 UPDATES_SV
873 .read()
874 .update_ext
875 .intersects(UpdateFlags::LAYOUT | UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE)
876 }
877
878 pub fn sender(&self) -> AppEventSender {
880 UPDATES_SV.read().event_sender.as_ref().unwrap().clone()
881 }
882
883 pub fn waker(&self, also_update: Option<WidgetId>) -> Waker {
885 UPDATES_SV.read().event_sender.as_ref().unwrap().waker(also_update)
886 }
887
888 pub(crate) fn update_flags_root(&self, flags: UpdateFlags, window_id: WindowId, root_id: WidgetId) {
889 if flags.is_empty() {
890 return;
891 }
892
893 let mut u = UPDATES_SV.write();
894 if flags.contains(UpdateFlags::UPDATE) {
895 u.update_widgets.insert_updates_root(window_id, root_id);
896 }
897 if flags.contains(UpdateFlags::INFO) {
898 u.info_widgets.insert_updates_root(window_id, root_id);
899 }
900 if flags.contains(UpdateFlags::LAYOUT) {
901 u.layout_widgets.insert_updates_root(window_id, root_id);
902 }
903
904 if flags.contains(UpdateFlags::RENDER) {
905 u.render_widgets.insert_updates_root(window_id, root_id);
906 } else if flags.contains(UpdateFlags::RENDER_UPDATE) {
907 u.render_update_widgets.insert_updates_root(window_id, root_id);
908 }
909
910 u.update_ext |= flags;
911 }
912
913 pub(crate) fn update_flags(&self, flags: UpdateFlags, target: WidgetId) {
914 if flags.is_empty() {
915 return;
916 }
917
918 let mut u = UPDATES_SV.write();
919
920 if flags.contains(UpdateFlags::UPDATE) {
921 u.update_widgets.search_widget(target);
922 }
923 if flags.contains(UpdateFlags::INFO) {
924 u.info_widgets.search_widget(target);
925 }
926 if flags.contains(UpdateFlags::LAYOUT) {
927 u.layout_widgets.search_widget(target);
928 }
929
930 if flags.contains(UpdateFlags::RENDER) {
931 u.render_widgets.search_widget(target);
932 } else if flags.contains(UpdateFlags::RENDER_UPDATE) {
933 u.render_update_widgets.search_widget(target);
934 }
935
936 u.update_ext |= flags;
937 }
938
939 pub fn update_op(&self, op: UpdateOp, target: WidgetId) -> &Self {
941 match op {
942 UpdateOp::Update => self.update(target),
943 UpdateOp::Info => self.update_info(target),
944 UpdateOp::Layout => self.layout(target),
945 UpdateOp::Render => self.render(target),
946 UpdateOp::RenderUpdate => self.render_update(target),
947 }
948 }
949
950 pub fn update_op_window(&self, op: UpdateOp, target: WindowId) -> &Self {
952 match op {
953 UpdateOp::Update => self.update_window(target),
954 UpdateOp::Info => self.update_info_window(target),
955 UpdateOp::Layout => self.layout_window(target),
956 UpdateOp::Render => self.render_window(target),
957 UpdateOp::RenderUpdate => self.render_update_window(target),
958 }
959 }
960
961 pub fn update(&self, target: WidgetId) -> &Self {
965 UpdatesTrace::log_update();
966 self.update_internal(target)
967 }
968 pub(crate) fn update_internal(&self, target: WidgetId) -> &UPDATES {
970 let mut u = UPDATES_SV.write();
971 u.update_ext.insert(UpdateFlags::UPDATE);
972 u.send_awake();
973 u.update_widgets.search_widget(target);
974 self
975 }
976
977 pub fn update_window(&self, target: WindowId) -> &Self {
979 let mut u = UPDATES_SV.write();
980 u.update_ext.insert(UpdateFlags::UPDATE);
981 u.send_awake();
982 u.update_widgets.insert_window(target);
983 self
984 }
985
986 pub fn update_app(&self) {
988 let mut u = UPDATES_SV.write();
989 u.update_ext.insert(UpdateFlags::UPDATE);
990 u.send_awake();
991 }
992
993 pub fn update_info(&self, target: WidgetId) -> &Self {
997 UpdatesTrace::log_info();
998 let mut u = UPDATES_SV.write();
999 u.update_ext.insert(UpdateFlags::INFO);
1000 u.send_awake();
1001 u.info_widgets.search_widget(target);
1002 self
1003 }
1004
1005 pub fn update_info_window(&self, target: WindowId) -> &Self {
1007 UpdatesTrace::log_info();
1008 let mut u = UPDATES_SV.write();
1009 u.update_ext.insert(UpdateFlags::INFO);
1010 u.send_awake();
1011 u.info_widgets.insert_window(target);
1012 self
1013 }
1014
1015 pub fn layout(&self, target: WidgetId) -> &Self {
1019 UpdatesTrace::log_layout();
1020 let mut u = UPDATES_SV.write();
1021 u.update_ext.insert(UpdateFlags::LAYOUT);
1022 u.send_awake();
1023 u.layout_widgets.search_widget(target);
1024 self
1025 }
1026
1027 pub fn layout_window(&self, target: WindowId) -> &Self {
1029 UpdatesTrace::log_layout();
1030 let mut u = UPDATES_SV.write();
1031 u.update_ext.insert(UpdateFlags::LAYOUT);
1032 u.send_awake();
1033 u.layout_widgets.insert_window(target);
1034 self
1035 }
1036
1037 pub fn render(&self, target: WidgetId) -> &Self {
1044 UpdatesTrace::log_render();
1045 let mut u = UPDATES_SV.write();
1046 u.update_ext.insert(UpdateFlags::RENDER);
1047 u.send_awake();
1048 u.render_widgets.search_widget(target);
1049 self
1050 }
1051
1052 pub fn render_window(&self, target: WindowId) -> &Self {
1054 UpdatesTrace::log_render();
1055 let mut u = UPDATES_SV.write();
1056 u.update_ext.insert(UpdateFlags::RENDER);
1057 u.send_awake();
1058 u.render_widgets.insert_window(target);
1059 self
1060 }
1061
1062 pub fn render_update(&self, target: WidgetId) -> &Self {
1068 UpdatesTrace::log_render();
1069 let mut u = UPDATES_SV.write();
1070 u.update_ext.insert(UpdateFlags::RENDER_UPDATE);
1071 u.send_awake();
1072 u.render_update_widgets.search_widget(target);
1073 self
1074 }
1075
1076 pub fn render_update_window(&self, target: WindowId) -> &Self {
1078 UpdatesTrace::log_render();
1079 let mut u = UPDATES_SV.write();
1080 u.update_ext.insert(UpdateFlags::RENDER_UPDATE);
1081 u.send_awake();
1082 u.render_update_widgets.insert_window(target);
1083 self
1084 }
1085
1086 pub fn is_pending_render(&self, window_id: WindowId) -> bool {
1088 let u = UPDATES_SV.read();
1089 u.render_widgets.enter_window(window_id) || u.render_update_widgets.enter_window(window_id)
1090 }
1091
1092 pub fn run<F: Future<Output = ()> + Send + 'static>(&self, future: impl IntoFuture<Output = (), IntoFuture = F>) -> OnUpdateHandle {
1098 let future = future.into_future();
1099 self.run_hn_once(async_hn_once!(|_| future.await))
1100 }
1101
1102 pub fn run_hn_once(&self, handler: Handler<UpdateArgs>) -> OnUpdateHandle {
1109 let mut u = UPDATES_SV.write();
1110 u.update_ext.insert(UpdateFlags::UPDATE);
1111 u.send_awake();
1112 Self::push_handler(u.pre_handlers.get_mut(), true, handler.into_once(), true)
1113 }
1114
1115 pub fn on_pre_update(&self, handler: Handler<UpdateArgs>) -> OnUpdateHandle {
1130 let u = UPDATES_SV.read();
1131 Self::push_handler(&mut u.pre_handlers.lock(), true, handler, false)
1132 }
1133
1134 pub fn on_update(&self, handler: Handler<UpdateArgs>) -> OnUpdateHandle {
1149 let u = UPDATES_SV.read();
1150 Self::push_handler(&mut u.pos_handlers.lock(), false, handler, false)
1151 }
1152
1153 pub fn once_update(&self, debug_name: &'static str, u: impl FnOnce() + Send + 'static) {
1157 VARS.modify(debug_name, u);
1158 }
1159
1160 pub fn once_next_update(&self, debug_name: &'static str, u: impl FnOnce() + Send + 'static) {
1164 self.run_hn_once(hn_once!(|_| {
1165 UPDATES.once_update(debug_name, u);
1166 }))
1167 .perm();
1168 }
1169
1170 fn push_handler(
1171 entries: &mut Vec<UpdateHandler>,
1172 is_preview: bool,
1173 mut handler: Handler<UpdateArgs>,
1174 force_once: bool,
1175 ) -> OnUpdateHandle {
1176 let (handle_owner, handle) = OnUpdateHandle::new();
1177 entries.push(UpdateHandler {
1178 handle: handle_owner,
1179 count: 0,
1180 handler: Box::new(move |args, handle| {
1181 handler.app_event(handle.clone_boxed(), is_preview, args);
1182 if force_once {
1183 handle.unsubscribe();
1184 }
1185 }),
1186 });
1187 handle
1188 }
1189
1190 pub(crate) fn on_pre_updates(&self) {
1191 let _s = tracing::trace_span!("UPDATES.on_pre_updates");
1192 let mut handlers = mem::take(UPDATES_SV.write().pre_handlers.get_mut());
1193 Self::retain_updates(&mut handlers);
1194
1195 let mut u = UPDATES_SV.write();
1196 handlers.append(u.pre_handlers.get_mut());
1197 *u.pre_handlers.get_mut() = handlers;
1198 }
1199
1200 pub(crate) fn on_updates(&self) {
1201 let _s = tracing::trace_span!("UPDATES.on_updates");
1202 let mut handlers = mem::take(UPDATES_SV.write().pos_handlers.get_mut());
1203 Self::retain_updates(&mut handlers);
1204
1205 let mut u = UPDATES_SV.write();
1206 handlers.append(u.pos_handlers.get_mut());
1207 *u.pos_handlers.get_mut() = handlers;
1208 }
1209
1210 fn retain_updates(handlers: &mut Vec<UpdateHandler>) {
1211 handlers.retain_mut(|e| {
1212 !e.handle.is_dropped() && {
1213 e.count = e.count.wrapping_add(1);
1214 (e.handler)(&UpdateArgs { count: e.count }, &e.handle.weak_handle());
1215 !e.handle.is_dropped()
1216 }
1217 });
1218 }
1219
1220 pub(super) fn take_update(&self) -> (bool, WidgetUpdates) {
1222 let mut u = UPDATES_SV.write();
1223
1224 let ext = u.update_ext.contains(UpdateFlags::UPDATE);
1225 u.update_ext.remove(UpdateFlags::UPDATE);
1226
1227 (
1228 ext,
1229 WidgetUpdates {
1230 delivery_list: mem::take(&mut u.update_widgets),
1231 },
1232 )
1233 }
1234
1235 pub(super) fn take_info(&self) -> (bool, InfoUpdates) {
1237 let mut u = UPDATES_SV.write();
1238
1239 let ext = u.update_ext.contains(UpdateFlags::INFO);
1240 u.update_ext.remove(UpdateFlags::INFO);
1241
1242 (
1243 ext,
1244 InfoUpdates {
1245 delivery_list: mem::take(&mut u.info_widgets),
1246 },
1247 )
1248 }
1249
1250 pub(super) fn take_layout(&self) -> (bool, LayoutUpdates) {
1252 let mut u = UPDATES_SV.write();
1253
1254 let ext = u.update_ext.contains(UpdateFlags::LAYOUT);
1255 u.update_ext.remove(UpdateFlags::LAYOUT);
1256
1257 (
1258 ext,
1259 LayoutUpdates {
1260 delivery_list: mem::take(&mut u.layout_widgets),
1261 },
1262 )
1263 }
1264
1265 pub(super) fn take_render(&self) -> (bool, RenderUpdates, RenderUpdates) {
1267 let mut u = UPDATES_SV.write();
1268
1269 let ext = u.update_ext.intersects(UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE);
1270 u.update_ext.remove(UpdateFlags::RENDER | UpdateFlags::RENDER_UPDATE);
1271
1272 (
1273 ext,
1274 RenderUpdates {
1275 delivery_list: mem::take(&mut u.render_widgets),
1276 },
1277 RenderUpdates {
1278 delivery_list: mem::take(&mut u.render_update_widgets),
1279 },
1280 )
1281 }
1282}
1283
1284app_local! {
1285 static UPDATES_SV: UpdatesService = UpdatesService::new();
1286}
1287struct UpdatesService {
1288 event_sender: Option<AppEventSender>,
1289
1290 update_ext: UpdateFlags,
1291 update_widgets: UpdateDeliveryList,
1292 info_widgets: UpdateDeliveryList,
1293 layout_widgets: UpdateDeliveryList,
1294 render_widgets: UpdateDeliveryList,
1295 render_update_widgets: UpdateDeliveryList,
1296
1297 pre_handlers: Mutex<Vec<UpdateHandler>>,
1298 pos_handlers: Mutex<Vec<UpdateHandler>>,
1299
1300 app_is_awake: bool,
1301 awake_pending: bool,
1302}
1303impl UpdatesService {
1304 fn new() -> Self {
1305 Self {
1306 event_sender: None,
1307 update_ext: UpdateFlags::empty(),
1308 update_widgets: UpdateDeliveryList::new(),
1309 info_widgets: UpdateDeliveryList::new(),
1310 layout_widgets: UpdateDeliveryList::new(),
1311 render_widgets: UpdateDeliveryList::new(),
1312 render_update_widgets: UpdateDeliveryList::new(),
1313
1314 pre_handlers: Mutex::new(vec![]),
1315 pos_handlers: Mutex::new(vec![]),
1316
1317 app_is_awake: false,
1318 awake_pending: false,
1319 }
1320 }
1321
1322 fn send_awake(&mut self) {
1323 if !self.app_is_awake && !self.awake_pending {
1324 self.awake_pending = true;
1325 match self.event_sender.as_ref() {
1326 Some(s) => {
1327 if let Err(ChannelError::Disconnected { .. }) = s.send_update_app() {
1328 tracing::debug!("no app connected to update");
1329 }
1330 }
1331 None => {
1332 tracing::debug!("no app connected yet to update");
1333 }
1334 }
1335 }
1336 }
1337
1338 fn app_awake(&mut self, wake: bool) {
1339 self.awake_pending = false;
1340 self.app_is_awake = wake;
1341 }
1342}
1343
1344#[non_exhaustive]
1348#[derive(Default)]
1349pub struct ContextUpdates {
1350 pub update: bool,
1355
1356 pub info: bool,
1361
1362 pub layout: bool,
1367
1368 pub render: bool,
1373
1374 pub update_widgets: WidgetUpdates,
1378
1379 pub info_widgets: InfoUpdates,
1383
1384 pub layout_widgets: LayoutUpdates,
1388
1389 pub render_widgets: RenderUpdates,
1393
1394 pub render_update_widgets: RenderUpdates,
1398}
1399
1400impl fmt::Debug for ContextUpdates {
1401 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1402 if f.alternate() {
1403 f.debug_struct("ContextUpdates")
1404 .field("update", &self.update)
1405 .field("info", &self.info)
1406 .field("layout", &self.layout)
1407 .field("render", &self.render)
1408 .field("update_widgets", &self.update_widgets)
1409 .field("info_widgets", &self.info_widgets)
1410 .field("layout_widgets", &self.layout_widgets)
1411 .field("render_widgets", &self.render_widgets)
1412 .field("render_update_widgets", &self.render_update_widgets)
1413 .finish()
1414 } else {
1415 write!(f, "ContextUpdates: ")?;
1416 let mut sep = "";
1417 if self.update {
1418 write!(f, "{sep}update")?;
1419 sep = ", ";
1420 }
1421 if self.info {
1422 write!(f, "{sep}info")?;
1423 sep = ", ";
1424 }
1425 if self.layout {
1426 write!(f, "{sep}layout")?;
1427 sep = ", ";
1428 }
1429 if self.render {
1430 write!(f, "{sep}render")?;
1431 sep = ", ";
1432 }
1433 if sep.is_empty() {
1434 write!(f, "<none>")?;
1435 }
1436 Ok(())
1437 }
1438 }
1439}
1440impl ContextUpdates {
1441 pub fn has_updates(&self) -> bool {
1443 self.update || self.info || self.layout || self.render
1444 }
1445}
1446impl std::ops::BitOrAssign for ContextUpdates {
1447 fn bitor_assign(&mut self, rhs: Self) {
1448 self.update |= rhs.update;
1449 self.update_widgets.extend(rhs.update_widgets);
1450 self.info |= rhs.info;
1451 self.info_widgets.extend(rhs.info_widgets);
1452 self.layout |= rhs.layout;
1453 self.layout_widgets.extend(rhs.layout_widgets);
1454 self.render |= rhs.render;
1455 self.render_widgets.extend(rhs.render_widgets);
1456 self.render_update_widgets.extend(rhs.render_update_widgets);
1457 }
1458}
1459impl std::ops::BitOr for ContextUpdates {
1460 type Output = Self;
1461
1462 fn bitor(mut self, rhs: Self) -> Self {
1463 self |= rhs;
1464 self
1465 }
1466}
1467
1468bitflags::bitflags! {
1469 #[derive(Clone, Copy, Debug, bytemuck::NoUninit)]
1470 #[repr(transparent)]
1471 pub(crate) struct UpdateFlags: u8 {
1472 const REINIT = 0b1000_0000;
1473 const INFO = 0b0001_0000;
1474 const UPDATE = 0b0000_0001;
1475 const LAYOUT = 0b0000_0010;
1476 const RENDER = 0b0000_0100;
1477 const RENDER_UPDATE = 0b0000_1000;
1478 }
1479}
1480
1481#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1486#[repr(transparent)]
1487#[must_use = "dropping the handle unsubscribes update handler"]
1488pub struct OnUpdateHandle(Handle<()>);
1489impl OnUpdateHandle {
1490 fn new() -> (HandleOwner<()>, OnUpdateHandle) {
1491 let (owner, handle) = Handle::new(());
1492 (owner, OnUpdateHandle(handle))
1493 }
1494
1495 pub fn dummy() -> Self {
1499 OnUpdateHandle(Handle::dummy(()))
1500 }
1501
1502 pub fn perm(self) {
1506 self.0.perm();
1507 }
1508
1509 pub fn is_permanent(&self) -> bool {
1513 self.0.is_permanent()
1514 }
1515
1516 pub fn unsubscribe(self) {
1518 self.0.force_drop()
1519 }
1520
1521 pub fn is_unsubscribed(&self) -> bool {
1525 self.0.is_dropped()
1526 }
1527
1528 pub fn downgrade(&self) -> WeakOnUpdateHandle {
1530 WeakOnUpdateHandle(self.0.downgrade())
1531 }
1532}
1533
1534#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)]
1536pub struct WeakOnUpdateHandle(WeakHandle<()>);
1537impl WeakOnUpdateHandle {
1538 pub fn new() -> Self {
1540 Self(WeakHandle::new())
1541 }
1542
1543 pub fn upgrade(&self) -> Option<OnUpdateHandle> {
1545 self.0.upgrade().map(OnUpdateHandle)
1546 }
1547}
1548
1549#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1551pub enum UpdateOp {
1552 Update,
1562 Info,
1569 Layout,
1575 Render,
1581 RenderUpdate,
1590}
1591
1592#[derive(Debug, Clone, Copy)]
1594#[non_exhaustive]
1595pub struct UpdateArgs {
1596 pub count: usize,
1598}
1599
1600struct UpdateHandler {
1601 handle: HandleOwner<()>,
1602 count: usize,
1603 handler: Box<dyn FnMut(&UpdateArgs, &dyn AppWeakHandle) + Send>,
1604}