1mod common;
9mod event_loop;
10mod runner;
11mod shared;
12mod window;
13
14use crate::messages::Erased;
15use crate::window::{BoxedWindow, PopupDescriptor, WindowId};
16use event_loop::Loop;
17pub(crate) use shared::RunnerT;
18use shared::Shared;
19use std::fmt::Debug;
20pub use window::Window;
21pub(crate) use window::WindowDataErased;
22
23pub use common::{Error, Platform, Result};
24pub use runner::{ClosedError, PreLaunchState, Proxy};
25
26#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
27#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
28pub use common::{GraphicsInstance, WindowSurface};
29
30#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
31#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
32pub extern crate raw_window_handle;
33
34#[must_use]
40#[derive(Debug, Default)]
41pub struct MessageStack {
42 base: usize,
43 count: usize,
44 stack: Vec<Erased>,
45}
46
47impl MessageStack {
48 #[inline]
50 pub fn new() -> Self {
51 MessageStack::default()
52 }
53
54 #[inline]
60 pub(crate) fn set_base(&mut self) {
61 self.base = self.stack.len();
62 }
63
64 #[inline]
68 pub(crate) fn get_op_count(&self) -> usize {
69 self.count
70 }
71
72 #[inline]
74 pub(crate) fn reset_and_has_any(&mut self) -> bool {
75 self.base = 0;
76 !self.stack.is_empty()
77 }
78
79 #[inline]
81 pub fn has_any(&self) -> bool {
82 self.stack.len() > self.base
83 }
84
85 #[inline]
87 pub(crate) fn push_erased(&mut self, msg: Erased) {
88 self.count = self.count.wrapping_add(1);
89 self.stack.push(msg);
90 }
91
92 #[inline]
94 pub fn pop_erased(&mut self) -> Option<Erased> {
95 self.count = self.count.wrapping_add(1);
96 self.stack.pop()
97 }
98
99 pub fn try_pop<M: Debug + 'static>(&mut self) -> Option<M> {
101 if self.has_any() && self.stack.last().map(|m| m.is::<M>()).unwrap_or(false) {
102 self.count = self.count.wrapping_add(1);
103 self.stack.pop().unwrap().downcast::<M>().ok().map(|m| *m)
104 } else {
105 None
106 }
107 }
108
109 pub fn try_peek<M: Debug + 'static>(&self) -> Option<&M> {
111 if self.has_any() {
112 self.stack.last().and_then(|m| m.downcast_ref::<M>())
113 } else {
114 None
115 }
116 }
117
118 pub fn peek_debug(&self) -> Option<&dyn Debug> {
120 self.stack.last().map(Erased::debug)
121 }
122}
123
124impl Drop for MessageStack {
125 fn drop(&mut self) {
126 for msg in self.stack.drain(..) {
127 if msg.is::<crate::event::components::KineticStart>() {
128 continue;
130 }
131
132 log::warn!(target: "kas_core::erased", "unhandled: {msg:?}");
133 }
134 }
135}
136
137pub trait AppData: 'static {
148 fn handle_messages(&mut self, messages: &mut MessageStack);
154
155 fn suspended(&mut self) {}
165}
166
167impl AppData for () {
168 fn handle_messages(&mut self, _: &mut MessageStack) {}
169 fn suspended(&mut self) {}
170}
171
172enum Pending<A: AppData> {
173 AddPopup(WindowId, WindowId, PopupDescriptor),
174 RepositionPopup(WindowId, PopupDescriptor),
175 AddWindow(WindowId, BoxedWindow<A>),
176 CloseWindow(WindowId),
177 Action(kas::Action),
178 Exit,
179}
180
181#[derive(Debug)]
182enum ProxyAction {
183 CloseAll,
184 Close(WindowId),
185 Message(kas::messages::SendErased),
186 WakeAsync,
187 #[cfg(feature = "accesskit")]
188 AccessKit(winit::window::WindowId, accesskit_winit::WindowEvent),
189}
190
191#[cfg(feature = "accesskit")]
192impl From<accesskit_winit::Event> for ProxyAction {
193 fn from(event: accesskit_winit::Event) -> Self {
194 ProxyAction::AccessKit(event.window_id, event.window_event)
195 }
196}
197
198#[cfg(test)]
199mod test {
200 use super::*;
201
202 #[test]
203 fn size_of_pending() {
204 assert_eq!(std::mem::size_of::<Pending<()>>(), 40);
205 }
206}