1#![doc(html_favicon_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo-icon.png")]
2#![doc(html_logo_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo.png")]
3#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
13#![recursion_limit = "256"]
14#![expect(clippy::type_complexity)]
16#![warn(unused_extern_crates)]
17#![warn(missing_docs)]
18
19use std::{
20    any::{TypeId, type_name},
21    collections::HashMap,
22    fmt, ops,
23    path::PathBuf,
24    sync::Arc,
25};
26
27pub mod access;
28pub mod crash_handler;
29pub mod event;
30pub mod handler;
31pub mod render;
32pub mod shortcut;
33pub mod third_party;
34pub mod timer;
35pub mod trace_recorder;
36pub mod update;
37pub mod view_process;
38pub mod widget;
39pub mod window;
40
41mod tests;
42
43use view_process::VIEW_PROCESS;
44use widget::UiTaskWidget;
45#[doc(hidden)]
46pub use zng_layout as layout;
47use zng_txt::Txt;
48#[doc(hidden)]
49pub use zng_var as var;
50use zng_var::Var;
51
52pub use zng_time::{DInstant, Deadline, INSTANT, InstantMode};
53
54use update::{EventUpdate, InfoUpdates, LayoutUpdates, RenderUpdates, UPDATES, UpdatesTrace, WidgetUpdates};
55use window::WindowMode;
56use zng_app_context::{AppId, AppScope, LocalContext};
57use zng_task::UiTask;
58
59pub use zng_unique_id::static_id;
60
61#[macro_export]
71macro_rules! enable_widget_macros {
72    () => {
73        #[doc(hidden)]
74        #[allow(unused_extern_crates)]
75        extern crate self as zng;
76
77        #[doc(hidden)]
78        pub use $crate::__proc_macro_util;
79    };
80}
81
82#[doc(hidden)]
83#[allow(unused_extern_crates)]
84extern crate self as zng;
85
86#[doc(hidden)]
87#[allow(unused_extern_crates)]
88extern crate self as zng_app; #[doc(hidden)]
91pub mod __proc_macro_util {
92    #[doc(hidden)]
96    pub use zng_unique_id::static_id;
97
98    #[doc(hidden)]
99    pub mod widget {
100        #[doc(hidden)]
101        pub mod builder {
102            #[doc(hidden)]
103            pub use crate::widget::builder::{
104                AnyArcWidgetHandler, ArcWidgetHandler, Importance, InputKind, PropertyArgs, PropertyId, PropertyInfo, PropertyInput,
105                PropertyInputTypes, PropertyNewArgs, SourceLocation, UiNodeInWhenExprError, WgtInfo, WhenInput, WhenInputMember,
106                WhenInputVar, WidgetHandlerInWhenExprError, WidgetType, iter_input_build_actions, nest_group_items, new_dyn_other,
107                new_dyn_ui_node, new_dyn_var, new_dyn_widget_handler, panic_input, ui_node_to_args, value_to_args, var_getter, var_state,
108                var_to_args, widget_handler_to_args,
109            };
110        }
111
112        #[doc(hidden)]
113        pub mod base {
114            pub use crate::widget::base::{NonWidgetBase, WidgetBase, WidgetExt, WidgetImpl};
115        }
116
117        #[doc(hidden)]
118        pub mod node {
119            pub use crate::widget::node::{ArcNode, IntoUiNode, UiNode};
120        }
121
122        #[doc(hidden)]
123        pub mod info {
124            pub use crate::widget::info::{WidgetInfoBuilder, WidgetLayout, WidgetMeasure};
125        }
126
127        #[doc(hidden)]
128        pub use crate::widget::{easing_property, widget_new};
129
130        #[doc(hidden)]
131        pub use crate::widget::WIDGET;
132    }
133
134    #[doc(hidden)]
135    pub mod update {
136        pub use crate::update::{EventUpdate, WidgetUpdates};
137    }
138
139    #[doc(hidden)]
140    pub mod layout {
141        #[doc(hidden)]
142        pub mod unit {
143            #[doc(hidden)]
144            pub use crate::layout::unit::{PxSize, TimeUnits};
145        }
146
147        #[doc(hidden)]
148        pub mod context {
149            #[doc(hidden)]
150            pub use crate::layout::context::LAYOUT;
151        }
152    }
153
154    #[doc(hidden)]
155    pub mod render {
156        pub use crate::render::{FrameBuilder, FrameUpdate};
157    }
158
159    #[doc(hidden)]
160    pub mod handler {
161        #[doc(hidden)]
162        pub use crate::handler::hn;
163    }
164
165    #[doc(hidden)]
166    pub mod var {
167        #[doc(hidden)]
168        pub use crate::var::{AnyVar, AnyVarValue, Var, expr_var};
169
170        #[doc(hidden)]
171        pub mod animation {
172            #[doc(hidden)]
173            pub mod easing {
174                #[doc(hidden)]
175                pub use crate::var::animation::easing::{
176                    back, bounce, circ, cubic, cubic_bezier, ease_in, ease_in_out, ease_out, ease_out_in, elastic, expo, linear, none,
177                    quad, quart, quint, reverse, reverse_out, sine, step_ceil, step_floor,
178                };
179            }
180        }
181    }
182}
183
184pub trait AppExtension: 'static {
192    #[inline(always)]
194    fn register(&self, info: &mut AppExtensionsInfo)
195    where
196        Self: Sized,
197    {
198        info.push::<Self>()
199    }
200
201    #[inline(always)]
203    fn init(&mut self) {}
204
205    #[inline(always)]
212    fn event_preview(&mut self, update: &mut EventUpdate) {
213        let _ = update;
214    }
215
216    #[inline(always)]
221    fn event_ui(&mut self, update: &mut EventUpdate) {
222        let _ = update;
223    }
224
225    #[inline(always)]
229    fn event(&mut self, update: &mut EventUpdate) {
230        let _ = update;
231    }
232
233    #[inline(always)]
239    fn info(&mut self, info_widgets: &mut InfoUpdates) {
240        let _ = info_widgets;
241    }
242
243    #[inline(always)]
250    fn update_preview(&mut self) {}
251
252    #[inline(always)]
260    fn update_ui(&mut self, update_widgets: &mut WidgetUpdates) {
261        let _ = update_widgets;
262    }
263
264    #[inline(always)]
269    fn update(&mut self) {}
270
271    #[inline(always)]
277    fn layout(&mut self, layout_widgets: &mut LayoutUpdates) {
278        let _ = layout_widgets;
279    }
280
281    #[inline(always)]
288    fn render(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates) {
289        let _ = (render_widgets, render_update_widgets);
290    }
291
292    #[inline(always)]
297    fn deinit(&mut self) {}
298
299    #[inline(always)]
303    fn boxed(self) -> Box<dyn AppExtensionBoxed>
304    where
305        Self: Sized,
306    {
307        Box::new(self)
308    }
309}
310
311#[doc(hidden)]
313pub trait AppExtensionBoxed: 'static {
314    fn register_boxed(&self, info: &mut AppExtensionsInfo);
315    fn init_boxed(&mut self);
316    fn update_preview_boxed(&mut self);
317    fn update_ui_boxed(&mut self, updates: &mut WidgetUpdates);
318    fn update_boxed(&mut self);
319    fn event_preview_boxed(&mut self, update: &mut EventUpdate);
320    fn event_ui_boxed(&mut self, update: &mut EventUpdate);
321    fn event_boxed(&mut self, update: &mut EventUpdate);
322    fn info_boxed(&mut self, info_widgets: &mut InfoUpdates);
323    fn layout_boxed(&mut self, layout_widgets: &mut LayoutUpdates);
324    fn render_boxed(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates);
325    fn deinit_boxed(&mut self);
326}
327impl<T: AppExtension> AppExtensionBoxed for T {
328    fn register_boxed(&self, info: &mut AppExtensionsInfo) {
329        self.register(info);
330    }
331
332    fn init_boxed(&mut self) {
333        self.init();
334    }
335
336    fn update_preview_boxed(&mut self) {
337        self.update_preview();
338    }
339
340    fn update_ui_boxed(&mut self, updates: &mut WidgetUpdates) {
341        self.update_ui(updates);
342    }
343
344    fn info_boxed(&mut self, info_widgets: &mut InfoUpdates) {
345        self.info(info_widgets);
346    }
347
348    fn update_boxed(&mut self) {
349        self.update();
350    }
351
352    fn event_preview_boxed(&mut self, update: &mut EventUpdate) {
353        self.event_preview(update);
354    }
355
356    fn event_ui_boxed(&mut self, update: &mut EventUpdate) {
357        self.event_ui(update);
358    }
359
360    fn event_boxed(&mut self, update: &mut EventUpdate) {
361        self.event(update);
362    }
363
364    fn layout_boxed(&mut self, layout_widgets: &mut LayoutUpdates) {
365        self.layout(layout_widgets);
366    }
367
368    fn render_boxed(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates) {
369        self.render(render_widgets, render_update_widgets);
370    }
371
372    fn deinit_boxed(&mut self) {
373        self.deinit();
374    }
375}
376impl AppExtension for Box<dyn AppExtensionBoxed> {
377    fn register(&self, info: &mut AppExtensionsInfo) {
378        self.as_ref().register_boxed(info);
379    }
380
381    fn init(&mut self) {
382        self.as_mut().init_boxed();
383    }
384
385    fn update_preview(&mut self) {
386        self.as_mut().update_preview_boxed();
387    }
388
389    fn update_ui(&mut self, update_widgets: &mut WidgetUpdates) {
390        self.as_mut().update_ui_boxed(update_widgets);
391    }
392
393    fn update(&mut self) {
394        self.as_mut().update_boxed();
395    }
396
397    fn event_preview(&mut self, update: &mut EventUpdate) {
398        self.as_mut().event_preview_boxed(update);
399    }
400
401    fn event_ui(&mut self, update: &mut EventUpdate) {
402        self.as_mut().event_ui_boxed(update);
403    }
404
405    fn event(&mut self, update: &mut EventUpdate) {
406        self.as_mut().event_boxed(update);
407    }
408
409    fn info(&mut self, info_widgets: &mut InfoUpdates) {
410        self.as_mut().info_boxed(info_widgets);
411    }
412
413    fn layout(&mut self, layout_widgets: &mut LayoutUpdates) {
414        self.as_mut().layout_boxed(layout_widgets);
415    }
416
417    fn render(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates) {
418        self.as_mut().render_boxed(render_widgets, render_update_widgets);
419    }
420
421    fn deinit(&mut self) {
422        self.as_mut().deinit_boxed();
423    }
424
425    fn boxed(self) -> Box<dyn AppExtensionBoxed>
426    where
427        Self: Sized,
428    {
429        self
430    }
431}
432
433struct TraceAppExt<E: AppExtension>(E);
434impl<E: AppExtension> AppExtension for TraceAppExt<E> {
435    fn register(&self, info: &mut AppExtensionsInfo) {
436        self.0.register(info)
437    }
438
439    fn init(&mut self) {
440        let _span = UpdatesTrace::extension_span::<E>("init");
441        self.0.init();
442    }
443
444    fn event_preview(&mut self, update: &mut EventUpdate) {
445        let _span = UpdatesTrace::extension_span::<E>("event_preview");
446        self.0.event_preview(update);
447    }
448
449    fn event_ui(&mut self, update: &mut EventUpdate) {
450        let _span = UpdatesTrace::extension_span::<E>("event_ui");
451        self.0.event_ui(update);
452    }
453
454    fn event(&mut self, update: &mut EventUpdate) {
455        let _span = UpdatesTrace::extension_span::<E>("event");
456        self.0.event(update);
457    }
458
459    fn update_preview(&mut self) {
460        let _span = UpdatesTrace::extension_span::<E>("update_preview");
461        self.0.update_preview();
462    }
463
464    fn update_ui(&mut self, update_widgets: &mut WidgetUpdates) {
465        let _span = UpdatesTrace::extension_span::<E>("update_ui");
466        self.0.update_ui(update_widgets);
467    }
468
469    fn update(&mut self) {
470        let _span = UpdatesTrace::extension_span::<E>("update");
471        self.0.update();
472    }
473
474    fn info(&mut self, info_widgets: &mut InfoUpdates) {
475        let _span = UpdatesTrace::extension_span::<E>("info");
476        self.0.info(info_widgets);
477    }
478
479    fn layout(&mut self, layout_widgets: &mut LayoutUpdates) {
480        let _span = UpdatesTrace::extension_span::<E>("layout");
481        self.0.layout(layout_widgets);
482    }
483
484    fn render(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates) {
485        let _span = UpdatesTrace::extension_span::<E>("render");
486        self.0.render(render_widgets, render_update_widgets);
487    }
488
489    fn deinit(&mut self) {
490        let _span = UpdatesTrace::extension_span::<E>("deinit");
491        self.0.deinit();
492    }
493
494    fn boxed(self) -> Box<dyn AppExtensionBoxed>
495    where
496        Self: Sized,
497    {
498        Box::new(self)
499    }
500}
501
502#[derive(Clone, Copy)]
506#[non_exhaustive]
507pub struct AppExtensionInfo {
508    pub type_id: TypeId,
510    pub type_name: &'static str,
512}
513impl PartialEq for AppExtensionInfo {
514    fn eq(&self, other: &Self) -> bool {
515        self.type_id == other.type_id
516    }
517}
518impl fmt::Debug for AppExtensionInfo {
519    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
520        write!(f, "{}", self.type_name)
521    }
522}
523impl Eq for AppExtensionInfo {}
524impl AppExtensionInfo {
525    pub fn new<E: AppExtension>() -> Self {
527        Self {
528            type_id: TypeId::of::<E>(),
529            type_name: type_name::<E>(),
530        }
531    }
532}
533
534#[derive(Clone, PartialEq)]
536pub struct AppExtensionsInfo {
537    infos: Vec<AppExtensionInfo>,
538}
539impl fmt::Debug for AppExtensionsInfo {
540    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541        f.debug_list().entries(&self.infos).finish()
542    }
543}
544impl AppExtensionsInfo {
545    pub(crate) fn start() -> Self {
546        Self { infos: vec![] }
547    }
548
549    pub fn push<E: AppExtension>(&mut self) {
551        let info = AppExtensionInfo::new::<E>();
552        assert!(!self.contains::<E>(), "app-extension `{info:?}` is already in the list");
553        self.infos.push(info);
554    }
555
556    pub fn contains<E: AppExtension>(&self) -> bool {
558        self.contains_info(AppExtensionInfo::new::<E>())
559    }
560
561    pub fn contains_info(&self, info: AppExtensionInfo) -> bool {
563        self.infos.iter().any(|e| e.type_id == info.type_id)
564    }
565
566    #[track_caller]
568    pub fn require<E: AppExtension>(&self) {
569        let info = AppExtensionInfo::new::<E>();
570        assert!(self.contains_info(info), "app-extension `{info:?}` is required");
571    }
572}
573impl ops::Deref for AppExtensionsInfo {
574    type Target = [AppExtensionInfo];
575
576    fn deref(&self) -> &Self::Target {
577        &self.infos
578    }
579}
580
581#[derive(Copy, Clone, Debug, PartialEq, Eq)]
583#[must_use = "methods that return `AppControlFlow` expect to be inside a controlled loop"]
584pub enum AppControlFlow {
585    Poll,
587    Wait,
591    Exit,
593}
594impl AppControlFlow {
595    #[track_caller]
597    pub fn assert_wait(self) {
598        assert_eq!(AppControlFlow::Wait, self)
599    }
600
601    #[track_caller]
603    pub fn assert_exit(self) {
604        assert_eq!(AppControlFlow::Exit, self)
605    }
606}
607
608pub struct HeadlessApp {
615    app: RunningApp<Box<dyn AppExtensionBoxed>>,
616}
617impl HeadlessApp {
618    pub fn renderer_enabled(&mut self) -> bool {
629        VIEW_PROCESS.is_available()
630    }
631
632    pub fn update(&mut self, wait_app_event: bool) -> AppControlFlow {
638        self.update_observed(&mut (), wait_app_event)
639    }
640
641    pub fn update_observe(&mut self, on_update: impl FnMut(), wait_app_event: bool) -> AppControlFlow {
648        struct Observer<F>(F);
649        impl<F: FnMut()> AppEventObserver for Observer<F> {
650            fn update(&mut self) {
651                (self.0)()
652            }
653        }
654        let mut observer = Observer(on_update);
655
656        self.update_observed(&mut observer, wait_app_event)
657    }
658
659    pub fn update_observe_event(&mut self, on_event: impl FnMut(&mut EventUpdate), wait_app_event: bool) -> AppControlFlow {
666        struct Observer<F>(F);
667        impl<F: FnMut(&mut EventUpdate)> AppEventObserver for Observer<F> {
668            fn event(&mut self, update: &mut EventUpdate) {
669                (self.0)(update);
670            }
671        }
672        let mut observer = Observer(on_event);
673        self.update_observed(&mut observer, wait_app_event)
674    }
675
676    pub fn update_observed<O: AppEventObserver>(&mut self, observer: &mut O, mut wait_app_event: bool) -> AppControlFlow {
681        if self.app.has_exited() {
682            return AppControlFlow::Exit;
683        }
684
685        loop {
686            match self.app.poll(wait_app_event, observer) {
687                AppControlFlow::Poll => {
688                    wait_app_event = false;
689                    continue;
690                }
691                flow => return flow,
692            }
693        }
694    }
695
696    pub fn run_task<R, T>(&mut self, task: impl IntoFuture<IntoFuture = T>) -> Option<R>
700    where
701        R: 'static,
702        T: Future<Output = R> + Send + Sync + 'static,
703    {
704        let mut task = UiTask::new(None, task);
705
706        let mut flow = self.update_observe(
707            || {
708                task.update();
709            },
710            false,
711        );
712
713        if task.update().is_some() {
714            let r = task.into_result().ok();
715            debug_assert!(r.is_some());
716            return r;
717        }
718
719        let mut n = 0;
720        while flow != AppControlFlow::Exit {
721            flow = self.update_observe(
722                || {
723                    task.update();
724                },
725                true,
726            );
727
728            if n == 10_000 {
729                tracing::error!("excessive future awaking, run_task ran 10_000 update cycles without finishing");
730            } else if n == 100_000 {
731                panic!("run_task stuck, ran 100_000 update cycles without finishing");
732            }
733            n += 1;
734
735            match task.into_result() {
736                Ok(r) => return Some(r),
737                Err(t) => task = t,
738            }
739        }
740        task.cancel();
741
742        None
743    }
744
745    pub fn exit(mut self) {
749        self.run_task(async move {
750            let req = APP.exit();
751            req.wait_rsp().await;
752        });
753    }
754
755    pub fn has_exited(&self) -> bool {
759        self.app.has_exited()
760    }
761}
762
763pub trait AppEventObserver {
767    fn raw_event(&mut self, ev: &zng_view_api::Event) {
769        let _ = ev;
770    }
771
772    fn event_preview(&mut self, update: &mut EventUpdate) {
774        let _ = update;
775    }
776
777    fn event_ui(&mut self, update: &mut EventUpdate) {
779        let _ = update;
780    }
781
782    fn event(&mut self, update: &mut EventUpdate) {
784        let _ = update;
785    }
786
787    fn update_preview(&mut self) {}
789
790    fn update_ui(&mut self, update_widgets: &mut WidgetUpdates) {
792        let _ = update_widgets;
793    }
794
795    fn update(&mut self) {}
797
798    fn info(&mut self, info_widgets: &mut InfoUpdates) {
800        let _ = info_widgets;
801    }
802
803    fn layout(&mut self, layout_widgets: &mut LayoutUpdates) {
805        let _ = layout_widgets;
806    }
807
808    fn render(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates) {
810        let _ = (render_widgets, render_update_widgets);
811    }
812
813    fn as_dyn(&mut self) -> DynAppEventObserver<'_>
817    where
818        Self: Sized,
819    {
820        DynAppEventObserver(self)
821    }
822}
823impl AppEventObserver for () {}
825
826#[doc(hidden)]
827pub struct DynAppEventObserver<'a>(&'a mut dyn AppEventObserverDyn);
828
829trait AppEventObserverDyn {
830    fn raw_event_dyn(&mut self, ev: &zng_view_api::Event);
831    fn event_preview_dyn(&mut self, update: &mut EventUpdate);
832    fn event_ui_dyn(&mut self, update: &mut EventUpdate);
833    fn event_dyn(&mut self, update: &mut EventUpdate);
834    fn update_preview_dyn(&mut self);
835    fn update_ui_dyn(&mut self, updates: &mut WidgetUpdates);
836    fn update_dyn(&mut self);
837    fn info_dyn(&mut self, info_widgets: &mut InfoUpdates);
838    fn layout_dyn(&mut self, layout_widgets: &mut LayoutUpdates);
839    fn render_dyn(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates);
840}
841impl<O: AppEventObserver> AppEventObserverDyn for O {
842    fn raw_event_dyn(&mut self, ev: &zng_view_api::Event) {
843        self.raw_event(ev)
844    }
845
846    fn event_preview_dyn(&mut self, update: &mut EventUpdate) {
847        self.event_preview(update)
848    }
849
850    fn event_ui_dyn(&mut self, update: &mut EventUpdate) {
851        self.event_ui(update)
852    }
853
854    fn event_dyn(&mut self, update: &mut EventUpdate) {
855        self.event(update)
856    }
857
858    fn update_preview_dyn(&mut self) {
859        self.update_preview()
860    }
861
862    fn update_ui_dyn(&mut self, update_widgets: &mut WidgetUpdates) {
863        self.update_ui(update_widgets)
864    }
865
866    fn update_dyn(&mut self) {
867        self.update()
868    }
869
870    fn info_dyn(&mut self, info_widgets: &mut InfoUpdates) {
871        self.info(info_widgets)
872    }
873
874    fn layout_dyn(&mut self, layout_widgets: &mut LayoutUpdates) {
875        self.layout(layout_widgets)
876    }
877
878    fn render_dyn(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates) {
879        self.render(render_widgets, render_update_widgets)
880    }
881}
882impl AppEventObserver for DynAppEventObserver<'_> {
883    fn raw_event(&mut self, ev: &zng_view_api::Event) {
884        self.0.raw_event_dyn(ev)
885    }
886
887    fn event_preview(&mut self, update: &mut EventUpdate) {
888        self.0.event_preview_dyn(update)
889    }
890
891    fn event_ui(&mut self, update: &mut EventUpdate) {
892        self.0.event_ui_dyn(update)
893    }
894
895    fn event(&mut self, update: &mut EventUpdate) {
896        self.0.event_dyn(update)
897    }
898
899    fn update_preview(&mut self) {
900        self.0.update_preview_dyn()
901    }
902
903    fn update_ui(&mut self, update_widgets: &mut WidgetUpdates) {
904        self.0.update_ui_dyn(update_widgets)
905    }
906
907    fn update(&mut self) {
908        self.0.update_dyn()
909    }
910
911    fn info(&mut self, info_widgets: &mut InfoUpdates) {
912        self.0.info_dyn(info_widgets)
913    }
914
915    fn layout(&mut self, layout_widgets: &mut LayoutUpdates) {
916        self.0.layout_dyn(layout_widgets)
917    }
918
919    fn render(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates) {
920        self.0.render_dyn(render_widgets, render_update_widgets)
921    }
922
923    fn as_dyn(&mut self) -> DynAppEventObserver<'_> {
924        DynAppEventObserver(self.0)
925    }
926}
927
928impl AppExtension for () {
929    fn register(&self, _: &mut AppExtensionsInfo) {}
930}
931impl<A: AppExtension, B: AppExtension> AppExtension for (A, B) {
932    fn init(&mut self) {
933        self.0.init();
934        self.1.init();
935    }
936
937    fn register(&self, info: &mut AppExtensionsInfo) {
938        self.0.register(info);
939        self.1.register(info);
940    }
941
942    fn update_preview(&mut self) {
943        self.0.update_preview();
944        self.1.update_preview();
945    }
946
947    fn update_ui(&mut self, update_widgets: &mut WidgetUpdates) {
948        self.0.update_ui(update_widgets);
949        self.1.update_ui(update_widgets);
950    }
951
952    fn update(&mut self) {
953        self.0.update();
954        self.1.update();
955    }
956
957    fn info(&mut self, info_widgets: &mut InfoUpdates) {
958        self.0.info(info_widgets);
959        self.1.info(info_widgets);
960    }
961
962    fn layout(&mut self, layout_widgets: &mut LayoutUpdates) {
963        self.0.layout(layout_widgets);
964        self.1.layout(layout_widgets);
965    }
966
967    fn render(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates) {
968        self.0.render(render_widgets, render_update_widgets);
969        self.1.render(render_widgets, render_update_widgets);
970    }
971
972    fn event_preview(&mut self, update: &mut EventUpdate) {
973        self.0.event_preview(update);
974        self.1.event_preview(update);
975    }
976
977    fn event_ui(&mut self, update: &mut EventUpdate) {
978        self.0.event_ui(update);
979        self.1.event_ui(update);
980    }
981
982    fn event(&mut self, update: &mut EventUpdate) {
983        self.0.event(update);
984        self.1.event(update);
985    }
986
987    fn deinit(&mut self) {
988        self.1.deinit();
989        self.0.deinit();
990    }
991}
992
993#[cfg(feature = "dyn_app_extension")]
994impl AppExtension for Vec<Box<dyn AppExtensionBoxed>> {
995    fn init(&mut self) {
996        for ext in self {
997            ext.init();
998        }
999    }
1000
1001    fn register(&self, info: &mut AppExtensionsInfo) {
1002        for ext in self {
1003            ext.register(info);
1004        }
1005    }
1006
1007    fn update_preview(&mut self) {
1008        for ext in self {
1009            ext.update_preview();
1010        }
1011    }
1012
1013    fn update_ui(&mut self, update_widgets: &mut WidgetUpdates) {
1014        for ext in self {
1015            ext.update_ui(update_widgets);
1016        }
1017    }
1018
1019    fn update(&mut self) {
1020        for ext in self {
1021            ext.update();
1022        }
1023    }
1024
1025    fn event_preview(&mut self, update: &mut EventUpdate) {
1026        for ext in self {
1027            ext.event_preview(update);
1028        }
1029    }
1030
1031    fn event_ui(&mut self, update: &mut EventUpdate) {
1032        for ext in self {
1033            ext.event_ui(update);
1034        }
1035    }
1036
1037    fn event(&mut self, update: &mut EventUpdate) {
1038        for ext in self {
1039            ext.event(update);
1040        }
1041    }
1042
1043    fn info(&mut self, info_widgets: &mut InfoUpdates) {
1044        for ext in self {
1045            ext.info(info_widgets);
1046        }
1047    }
1048
1049    fn layout(&mut self, layout_widgets: &mut LayoutUpdates) {
1050        for ext in self {
1051            ext.layout(layout_widgets);
1052        }
1053    }
1054
1055    fn render(&mut self, render_widgets: &mut RenderUpdates, render_update_widgets: &mut RenderUpdates) {
1056        for ext in self {
1057            ext.render(render_widgets, render_update_widgets);
1058        }
1059    }
1060
1061    fn deinit(&mut self) {
1062        for ext in self.iter_mut().rev() {
1063            ext.deinit();
1064        }
1065    }
1066}
1067
1068pub struct APP;
1070impl APP {
1071    pub fn multi_app_enabled(&self) -> bool {
1075        cfg!(feature = "multi_app")
1076    }
1077
1078    pub fn is_running(&self) -> bool {
1087        LocalContext::current_app().is_some()
1088    }
1089
1090    pub fn id(&self) -> Option<AppId> {
1098        LocalContext::current_app()
1099    }
1100
1101    #[cfg(not(feature = "multi_app"))]
1102    fn assert_can_run_single() {
1103        use std::sync::atomic::*;
1104        static CAN_RUN: AtomicBool = AtomicBool::new(true);
1105
1106        if !CAN_RUN.swap(false, Ordering::SeqCst) {
1107            panic!("only one app is allowed per process")
1108        }
1109    }
1110
1111    fn assert_can_run() {
1112        #[cfg(not(feature = "multi_app"))]
1113        Self::assert_can_run_single();
1114        if APP.is_running() {
1115            panic!("only one app is allowed per thread")
1116        }
1117    }
1118
1119    pub fn window_mode(&self) -> WindowMode {
1123        if VIEW_PROCESS.is_available() {
1124            if VIEW_PROCESS.is_headless_with_render() {
1125                WindowMode::HeadlessWithRenderer
1126            } else {
1127                WindowMode::Headed
1128            }
1129        } else {
1130            WindowMode::Headless
1131        }
1132    }
1133    pub fn extensions(&self) -> Arc<AppExtensionsInfo> {
1135        APP_PROCESS_SV.read().extensions()
1136    }
1137
1138    pub fn device_events_filter(&self) -> Var<DeviceEventsFilter> {
1145        APP_PROCESS_SV.read().device_events_filter.clone()
1146    }
1147}
1148
1149impl APP {
1150    #[cfg(feature = "dyn_app_extension")]
1152    pub fn minimal(&self) -> AppExtended<Vec<Box<dyn AppExtensionBoxed>>> {
1153        zng_env::init_process_name("app-process");
1154
1155        #[cfg(debug_assertions)]
1156        print_tracing(tracing::Level::INFO);
1157        assert_not_view_process();
1158        Self::assert_can_run();
1159        spawn_deadlock_detection();
1160
1161        let _ = INSTANT.now();
1162        let scope = LocalContext::start_app(AppId::new_unique());
1163        AppExtended {
1164            extensions: vec![],
1165            view_process_exe: None,
1166            view_process_env: HashMap::new(),
1167            _cleanup: scope,
1168        }
1169    }
1170
1171    #[cfg(not(feature = "dyn_app_extension"))]
1173    pub fn minimal(&self) -> AppExtended<()> {
1174        #[cfg(debug_assertions)]
1175        print_tracing(tracing::Level::INFO);
1176        assert_not_view_process();
1177        Self::assert_can_run();
1178        spawn_deadlock_detection();
1179        let scope = LocalContext::start_app(AppId::new_unique());
1180        AppExtended {
1181            extensions: (),
1182            view_process_exe: None,
1183            view_process_env: HashMap::new(),
1184            _cleanup: scope,
1185        }
1186    }
1187}
1188
1189pub struct AppExtended<E: AppExtension> {
1193    extensions: E,
1194    view_process_exe: Option<PathBuf>,
1195    view_process_env: HashMap<Txt, Txt>,
1196
1197    _cleanup: AppScope,
1199}
1200#[cfg(feature = "dyn_app_extension")]
1201impl AppExtended<Vec<Box<dyn AppExtensionBoxed>>> {
1202    pub fn extend<F: AppExtension>(mut self, extension: F) -> AppExtended<Vec<Box<dyn AppExtensionBoxed>>> {
1204        self.extensions.push(TraceAppExt(extension).boxed());
1205        self
1206    }
1207
1208    fn run_dyn(self, start: std::pin::Pin<Box<dyn Future<Output = ()> + Send + 'static>>) {
1209        let app = RunningApp::start(
1210            self._cleanup,
1211            self.extensions,
1212            true,
1213            true,
1214            self.view_process_exe,
1215            self.view_process_env,
1216        );
1217
1218        UPDATES.run(start).perm();
1219
1220        app.run_headed();
1221    }
1222
1223    fn run_headless_dyn(self, with_renderer: bool) -> HeadlessApp {
1224        let app = RunningApp::start(
1225            self._cleanup,
1226            self.extensions.boxed(),
1227            false,
1228            with_renderer,
1229            self.view_process_exe,
1230            self.view_process_env,
1231        );
1232
1233        HeadlessApp { app }
1234    }
1235}
1236
1237#[cfg(feature = "dyn_app_extension")]
1239impl<E: AppExtension> AppExtended<E> {
1240    fn cast_app(self) -> AppExtended<Vec<Box<dyn AppExtensionBoxed>>> {
1241        let app: Box<dyn std::any::Any> = Box::new(self);
1242        match app.downcast::<AppExtended<Vec<Box<dyn AppExtensionBoxed>>>>() {
1243            Ok(ok) => *ok,
1244            Err(e) => {
1245                let app = *e.downcast::<Self>().unwrap();
1246                AppExtended {
1247                    extensions: vec![app.extensions.boxed()],
1248                    view_process_exe: app.view_process_exe,
1249                    view_process_env: app.view_process_env,
1250                    _cleanup: app._cleanup,
1251                }
1252            }
1253        }
1254    }
1255
1256    fn run_impl(self, start: impl Future<Output = ()> + Send + 'static) {
1257        self.cast_app().run_dyn(Box::pin(start))
1258    }
1259
1260    fn run_headless_impl(self, with_renderer: bool) -> HeadlessApp {
1261        self.cast_app().run_headless_dyn(with_renderer)
1262    }
1263}
1264
1265#[cfg(not(feature = "dyn_app_extension"))]
1266impl<E: AppExtension> AppExtended<E> {
1267    pub fn extend<F: AppExtension>(self, extension: F) -> AppExtended<impl AppExtension> {
1269        AppExtended {
1270            _cleanup: self._cleanup,
1271            extensions: (self.extensions, TraceAppExt(extension)),
1272            view_process_exe: self.view_process_exe,
1273            view_process_env: self.view_process_env,
1274        }
1275    }
1276
1277    fn run_impl(self, start: impl Future<Output = ()> + Send + 'static) {
1278        let app = RunningApp::start(
1279            self._cleanup,
1280            self.extensions,
1281            true,
1282            true,
1283            self.view_process_exe,
1284            self.view_process_env,
1285        );
1286
1287        UPDATES.run(start).perm();
1288
1289        app.run_headed();
1290    }
1291
1292    fn run_headless_impl(self, with_renderer: bool) -> HeadlessApp {
1293        let app = RunningApp::start(
1294            self._cleanup,
1295            self.extensions.boxed(),
1296            false,
1297            with_renderer,
1298            self.view_process_exe,
1299            self.view_process_env,
1300        );
1301
1302        HeadlessApp { app }
1303    }
1304}
1305impl<E: AppExtension> AppExtended<E> {
1306    pub fn view_process_exe(mut self, view_process_exe: impl Into<PathBuf>) -> Self {
1316        self.view_process_exe = Some(view_process_exe.into());
1317        self
1318    }
1319
1320    pub fn view_process_env(mut self, name: impl Into<Txt>, value: impl Into<Txt>) -> Self {
1322        self.view_process_env.insert(name.into(), value.into());
1323        self
1324    }
1325
1326    pub fn run<F: Future<Output = ()> + Send + 'static>(self, start: impl IntoFuture<IntoFuture = F>) {
1333        let start = start.into_future();
1334        self.run_impl(start)
1335    }
1336
1337    pub fn run_headless(self, with_renderer: bool) -> HeadlessApp {
1342        self.run_headless_impl(with_renderer)
1343    }
1344}
1345
1346mod running;
1348pub use running::*;
1349use zng_view_api::DeviceEventsFilter;
1350
1351mod private {
1352    pub trait Sealed {}
1354}
1355
1356pub fn print_tracing(max: tracing::Level) -> bool {
1372    use tracing_subscriber::prelude::*;
1373
1374    let layers = tracing_subscriber::registry().with(FilterLayer(max));
1375
1376    #[cfg(target_os = "android")]
1377    let layers = layers.with(tracing_android::layer(&zng_env::about().pkg_name).unwrap());
1378
1379    #[cfg(not(target_os = "android"))]
1380    let layers = {
1381        let fmt_layer = tracing_subscriber::fmt::layer().without_time();
1382
1383        #[cfg(target_arch = "wasm32")]
1384        let fmt_layer = fmt_layer.with_ansi(false).with_writer(tracing_web::MakeWebConsoleWriter::new());
1385
1386        layers.with(fmt_layer)
1387    };
1388
1389    layers.try_init().is_ok()
1390}
1391
1392struct FilterLayer(tracing::Level);
1393impl<S: tracing::Subscriber> tracing_subscriber::Layer<S> for FilterLayer {
1394    fn enabled(&self, metadata: &tracing::Metadata<'_>, _: tracing_subscriber::layer::Context<'_, S>) -> bool {
1395        print_tracing_filter(&self.0, metadata)
1396    }
1397
1398    fn max_level_hint(&self) -> Option<tracing::metadata::LevelFilter> {
1399        Some(self.0.into())
1400    }
1401
1402    #[cfg(any(test, feature = "test_util"))]
1403    fn on_event(&self, event: &tracing::Event<'_>, _ctx: tracing_subscriber::layer::Context<'_, S>) {
1404        if event.metadata().level() == &tracing::Level::ERROR && APP.is_running() && TEST_LOG.get() {
1405            struct MsgCollector<'a>(&'a mut String);
1406            impl tracing::field::Visit for MsgCollector<'_> {
1407                fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn fmt::Debug) {
1408                    use std::fmt::Write;
1409                    write!(self.0, "\n  {} = {:?}", field.name(), value).unwrap();
1410                }
1411            }
1412
1413            let meta = event.metadata();
1414            let file = meta.file().unwrap_or("");
1415            let line = meta.line().unwrap_or(0);
1416
1417            let mut msg = format!("[{file}:{line}]");
1418            event.record(&mut MsgCollector(&mut msg));
1419
1420            panic!("[LOG-ERROR]{msg}")
1421        }
1422    }
1423}
1424pub fn print_tracing_filter(level: &tracing::Level, metadata: &tracing::Metadata) -> bool {
1428    if metadata.level() > level {
1429        return false;
1430    }
1431
1432    if metadata.level() == &tracing::Level::INFO {
1433        if metadata.target() == "zng_webrender::device::gl" {
1435            return false;
1436        }
1437        if metadata.target() == "zng_webrender::renderer::init" {
1439            return false;
1440        }
1441    } else if metadata.level() == &tracing::Level::WARN {
1442        if metadata.target() == "zng_webrender::device::gl" {
1445            if metadata.line() == Some(4647) {
1448                return false;
1449            }
1450        }
1451
1452        if metadata.target() == "font_kit::loaders::freetype" {
1455            if metadata.line() == Some(734) {
1459                return false;
1460            }
1461        }
1462    }
1463
1464    true
1465}
1466
1467#[cfg(any(test, feature = "test_util"))]
1469pub fn test_log() {
1470    TEST_LOG.set(true);
1471}
1472
1473#[cfg(any(test, feature = "test_util"))]
1474zng_app_context::app_local! {
1475    static TEST_LOG: bool = false;
1476}
1477
1478#[doc(hidden)]
1479pub fn name_from_pkg_name(name: &'static str) -> Txt {
1480    let mut n = String::new();
1481    let mut sep = "";
1482    for part in name.split(&['-', '_']) {
1483        n.push_str(sep);
1484        let mut chars = part.char_indices();
1485        let (_, c) = chars.next().unwrap();
1486        c.to_uppercase().for_each(|c| n.push(c));
1487        if let Some((i, _)) = chars.next() {
1488            n.push_str(&part[i..]);
1489        }
1490        sep = " ";
1491    }
1492    n.into()
1493}
1494
1495#[doc(hidden)]
1496pub fn txt_from_pkg_meta(value: &'static str) -> Txt {
1497    value.into()
1498}