1mod common;
9mod event_loop;
10mod runner;
11mod shared;
12mod window;
13
14use crate::ConfigAction;
15use crate::messages::Erased;
16use crate::window::{BoxedWindow, PopupDescriptor, WindowId};
17use event_loop::Loop;
18use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
19pub(crate) use shared::RunnerT;
20use shared::Shared;
21use std::fmt::Debug;
22pub use window::Window;
23pub(crate) use window::WindowDataErased;
24
25pub use common::{Error, Platform, Result};
26pub use runner::{ClosedError, PreLaunchState, Proxy};
27
28#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
29#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
30pub use common::{GraphicsFeatures, GraphicsInstance, RunError, WindowSurface};
31
32#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
33#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
34pub extern crate raw_window_handle;
35
36pub trait HasDisplayAndWindowHandle: HasDisplayHandle + HasWindowHandle + 'static {}
38impl<W: HasDisplayHandle + HasWindowHandle + 'static> HasDisplayAndWindowHandle for W {}
39
40#[must_use]
46#[derive(Debug, Default)]
47pub(crate) struct MessageStack {
48 base: usize,
49 count: usize,
50 stack: Vec<Erased>,
51}
52
53impl MessageStack {
54 #[inline]
56 pub(crate) fn new() -> Self {
57 MessageStack::default()
58 }
59
60 #[inline]
66 pub(crate) fn set_base(&mut self) {
67 self.base = self.stack.len();
68 }
69
70 #[inline]
74 pub(crate) fn get_op_count(&self) -> usize {
75 self.count
76 }
77
78 #[inline]
80 pub(crate) fn reset_and_has_any(&mut self) -> bool {
81 self.base = 0;
82 !self.stack.is_empty()
83 }
84
85 #[inline]
87 pub fn has_any(&self) -> bool {
88 self.stack.len() > self.base
89 }
90
91 #[inline]
93 pub(crate) fn push_erased(&mut self, msg: Erased) {
94 self.count = self.count.wrapping_add(1);
95 self.stack.push(msg);
96 }
97
98 pub(crate) fn drop_unsent(&mut self) {
100 self.stack.drain(self.base..);
101 }
102
103 pub(crate) fn clear(&mut self) {
105 for msg in self.stack.drain(..) {
106 if msg.is::<crate::event::components::KineticStart>() {
107 continue;
109 }
110
111 log::warn!(target: "kas_core::erased", "unhandled: {msg:?}");
112 }
113
114 self.base = 0;
115 self.count = 0;
116 }
117}
118
119pub trait ReadMessage {
121 fn pop_erased(&mut self) -> Option<Erased>;
123
124 fn try_pop<M: Debug + 'static>(&mut self) -> Option<M>;
126
127 fn try_peek<M: Debug + 'static>(&self) -> Option<&M>;
129
130 fn peek_debug(&self) -> Option<&dyn Debug>;
132}
133
134impl ReadMessage for MessageStack {
135 #[inline]
136 fn pop_erased(&mut self) -> Option<Erased> {
137 self.count = self.count.wrapping_add(1);
138 self.stack.pop()
139 }
140
141 fn try_pop<M: Debug + 'static>(&mut self) -> Option<M> {
142 if self.has_any() && self.stack.last().map(|m| m.is::<M>()).unwrap_or(false) {
143 self.count = self.count.wrapping_add(1);
144 self.stack.pop().unwrap().downcast::<M>().ok().map(|m| *m)
145 } else {
146 None
147 }
148 }
149
150 fn try_peek<M: Debug + 'static>(&self) -> Option<&M> {
151 if self.has_any() {
152 self.stack.last().and_then(|m| m.downcast_ref::<M>())
153 } else {
154 None
155 }
156 }
157
158 fn peek_debug(&self) -> Option<&dyn Debug> {
159 self.stack.last().map(Erased::debug)
160 }
161}
162
163impl Drop for MessageStack {
164 fn drop(&mut self) {
165 self.clear();
166 }
167}
168
169pub trait AppData: 'static {
180 fn handle_message(&mut self, messages: &mut impl ReadMessage);
192
193 fn resumed(&mut self) {}
199
200 fn suspended(&mut self) {}
210
211 fn memory_warning(&mut self) {}
216}
217
218impl AppData for () {
219 fn handle_message(&mut self, _: &mut impl ReadMessage) {}
220 fn suspended(&mut self) {}
221}
222
223enum Pending<A: AppData> {
224 Update,
225 ConfigUpdate(ConfigAction),
226 AddPopup(WindowId, WindowId, PopupDescriptor),
227 RepositionPopup(WindowId, PopupDescriptor),
228 AddWindow(WindowId, BoxedWindow<A>),
229 CloseWindow(WindowId),
230 Exit,
231}
232
233#[derive(Debug)]
234enum ProxyAction {
235 CloseAll,
236 Close(WindowId),
237 Message(kas::messages::SendErased),
238 #[cfg(feature = "accesskit")]
239 AccessKit(winit::window::WindowId, accesskit_winit::WindowEvent),
240}
241
242#[cfg(feature = "accesskit")]
243impl From<accesskit_winit::Event> for ProxyAction {
244 fn from(event: accesskit_winit::Event) -> Self {
245 compile_error!("AccessKit is not compatible with the current winit version")
246 }
248}
249
250#[cfg(test)]
251mod test {
252 use super::*;
253
254 #[test]
255 fn size_of_pending() {
256 assert_eq!(std::mem::size_of::<Pending<()>>(), 40);
257 }
258}