Skip to main content

incular_runtime/
application_types.rs

1use crate::context::BuildContext;
2use crate::profiling::SchedulerCounters;
3use crate::tasks::TaskFailure;
4use incular_core::RestorationKey;
5use incular_platform::WindowOptionsError;
6use incular_widgets::Widget;
7use incular_widgets::internal::TreeError;
8use std::rc::Rc;
9
10#[derive(Clone, Copy, Debug, Default)]
11pub(crate) struct ApplicationSchedulerCounters {
12    pub(crate) runtime_wakes: u64,
13    pub(crate) redraw_requests: u64,
14    pub(crate) frames_started: u64,
15    pub(crate) frames_presented: u64,
16    pub(crate) frames_skipped: u64,
17}
18
19impl ApplicationSchedulerCounters {
20    pub(crate) fn apply_to(self, scheduler: &mut SchedulerCounters) {
21        scheduler.runtime_wakes = self.runtime_wakes;
22        scheduler.redraw_requests = self.redraw_requests;
23        scheduler.frames_started = self.frames_started;
24        scheduler.frames_presented = self.frames_presented;
25        scheduler.frames_skipped = self.frames_skipped;
26    }
27}
28
29/// Backend-neutral application lifecycle. Desktop adapters may only emit a
30/// subset; runtime users must therefore treat transitions as advisory rather
31/// than assume every state is observable on every platform.
32#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
33pub enum ApplicationLifecycle {
34    #[default]
35    Starting,
36    Active,
37    Inactive,
38    Suspended,
39    Stopping,
40    Terminated,
41}
42
43/// A lifecycle update normalized by a platform adapter.
44#[derive(Clone, Copy, Debug, PartialEq, Eq)]
45pub struct LifecycleTransition {
46    pub previous: ApplicationLifecycle,
47    pub current: ApplicationLifecycle,
48}
49
50/// Runtime-level failure report intended for application logging/telemetry
51/// hooks. Framework panics never unwind into the native event-loop callback.
52#[derive(Clone, Debug, PartialEq, Eq)]
53pub struct RuntimeErrorReport {
54    pub failure: TaskFailure,
55}
56
57/// Policy applied after a close accepts the final visible Incular window.
58/// `ExitOnLastWindow` is the default so a hidden auxiliary window cannot keep
59/// an application alive accidentally. `KeepRunning` is explicit headless or
60/// background-service policy; a native adapter remains free to wait idle.
61#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
62pub enum LastWindowPolicy {
63    #[default]
64    ExitOnLastWindow,
65    KeepRunning,
66}
67
68/// Failure while creating or addressing an Incular-owned window.
69#[derive(Debug)]
70pub enum WindowError {
71    Options(WindowOptionsError),
72    Tree(TreeError),
73    Restoration(String),
74    ApplicationStopped,
75}
76
77impl From<WindowOptionsError> for WindowError {
78    fn from(error: WindowOptionsError) -> Self {
79        Self::Options(error)
80    }
81}
82
83impl From<TreeError> for WindowError {
84    fn from(error: TreeError) -> Self {
85        Self::Tree(error)
86    }
87}
88
89impl std::fmt::Display for WindowError {
90    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91        match self {
92            Self::Options(error) => write!(formatter, "invalid window options: {error}"),
93            Self::Tree(error) => write!(formatter, "window tree error: {error}"),
94            Self::Restoration(error) => write!(formatter, "invalid restoration window: {error}"),
95            Self::ApplicationStopped => formatter.write_str("the Incular application has stopped"),
96        }
97    }
98}
99
100/// Application-defined identity for a window that should survive a restart.
101/// It is intentionally unrelated to the session-local generational
102/// window ID.
103#[derive(Clone, Debug, PartialEq, Eq, Hash)]
104pub struct WindowRestorationId(pub(crate) RestorationKey);
105
106impl WindowRestorationId {
107    pub fn new(value: impl Into<String>) -> Result<Self, incular_core::RestorationKeyError> {
108        RestorationKey::new(value).map(Self)
109    }
110
111    #[must_use]
112    pub fn as_key(&self) -> &RestorationKey {
113        &self.0
114    }
115}
116
117/// Application-owned factory for a persisted auxiliary window kind. It is
118/// registered in memory at startup; it is never serialized.
119pub type RestorableWindowFactory = Rc<dyn Fn(&mut BuildContext) -> Widget>;
120
121impl TryFrom<&str> for WindowRestorationId {
122    type Error = incular_core::RestorationKeyError;
123
124    fn try_from(value: &str) -> Result<Self, Self::Error> {
125        Self::new(value)
126    }
127}
128
129#[derive(Clone)]
130pub(crate) struct RestorableWindowMetadata {
131    pub(crate) id: WindowRestorationId,
132    pub(crate) kind: String,
133}
134
135impl RestorableWindowMetadata {
136    pub(crate) fn new(
137        id: WindowRestorationId,
138        kind: impl Into<String>,
139    ) -> Result<Self, WindowError> {
140        let kind = kind.into();
141        if kind.trim().is_empty() || kind.chars().any(char::is_control) {
142            return Err(WindowError::Restoration(
143                "window kind must be a non-empty printable stable identifier".to_owned(),
144            ));
145        }
146        Ok(Self { id, kind })
147    }
148}
149
150impl std::error::Error for WindowError {}