1mod common;
9mod event_loop;
10mod runner;
11mod shared;
12mod window;
13
14use crate::messages::Erased;
15use crate::window::{PopupDescriptor, WindowId};
16use event_loop::Loop;
17pub(crate) use shared::RunnerT;
18use shared::State;
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
172#[crate::autoimpl(Debug)]
173enum Pending<A: AppData, G: GraphicsInstance, T: kas::theme::Theme<G::Shared>> {
174 AddPopup(WindowId, WindowId, PopupDescriptor),
175 RepositionPopup(WindowId, PopupDescriptor),
176 AddWindow(WindowId, Box<Window<A, G, T>>),
179 CloseWindow(WindowId),
180 Action(kas::Action),
181 Exit,
182}
183
184#[derive(Debug)]
185enum ProxyAction {
186 CloseAll,
187 Close(WindowId),
188 Message(kas::messages::SendErased),
189 WakeAsync,
190 #[cfg(feature = "accesskit")]
191 AccessKit(winit::window::WindowId, accesskit_winit::WindowEvent),
192}
193
194#[cfg(feature = "accesskit")]
195impl From<accesskit_winit::Event> for ProxyAction {
196 fn from(event: accesskit_winit::Event) -> Self {
197 ProxyAction::AccessKit(event.window_id, event.window_event)
198 }
199}
200
201#[cfg(test)]
202mod test {
203 use super::*;
204 use raw_window_handle as rwh;
205 use std::time::Instant;
206
207 struct Draw;
208 impl crate::draw::DrawImpl for Draw {
209 fn common_mut(&mut self) -> &mut crate::draw::WindowCommon {
210 todo!()
211 }
212
213 fn new_pass(
214 &mut self,
215 _: crate::draw::PassId,
216 _: crate::prelude::Rect,
217 _: crate::prelude::Offset,
218 _: crate::draw::PassType,
219 ) -> crate::draw::PassId {
220 todo!()
221 }
222
223 fn get_clip_rect(&self, _: crate::draw::PassId) -> crate::prelude::Rect {
224 todo!()
225 }
226
227 fn rect(
228 &mut self,
229 _: crate::draw::PassId,
230 _: crate::geom::Quad,
231 _: crate::draw::color::Rgba,
232 ) {
233 todo!()
234 }
235
236 fn frame(
237 &mut self,
238 _: crate::draw::PassId,
239 _: crate::geom::Quad,
240 _: crate::geom::Quad,
241 _: crate::draw::color::Rgba,
242 ) {
243 todo!()
244 }
245 }
246 impl crate::draw::DrawRoundedImpl for Draw {
247 fn rounded_line(
248 &mut self,
249 _: crate::draw::PassId,
250 _: crate::geom::Vec2,
251 _: crate::geom::Vec2,
252 _: f32,
253 _: crate::draw::color::Rgba,
254 ) {
255 todo!()
256 }
257
258 fn circle(
259 &mut self,
260 _: crate::draw::PassId,
261 _: crate::geom::Quad,
262 _: f32,
263 _: crate::draw::color::Rgba,
264 ) {
265 todo!()
266 }
267
268 fn circle_2col(
269 &mut self,
270 _: crate::draw::PassId,
271 _: crate::geom::Quad,
272 _: crate::draw::color::Rgba,
273 _: crate::draw::color::Rgba,
274 ) {
275 todo!()
276 }
277
278 fn rounded_frame(
279 &mut self,
280 _: crate::draw::PassId,
281 _: crate::geom::Quad,
282 _: crate::geom::Quad,
283 _: f32,
284 _: crate::draw::color::Rgba,
285 ) {
286 todo!()
287 }
288
289 fn rounded_frame_2col(
290 &mut self,
291 _: crate::draw::PassId,
292 _: crate::geom::Quad,
293 _: crate::geom::Quad,
294 _: crate::draw::color::Rgba,
295 _: crate::draw::color::Rgba,
296 ) {
297 todo!()
298 }
299 }
300
301 struct DrawShared;
302 impl crate::draw::DrawSharedImpl for DrawShared {
303 type Draw = Draw;
304
305 fn max_texture_dimension_2d(&self) -> u32 {
306 todo!()
307 }
308
309 fn set_raster_config(&mut self, _: &crate::config::RasterConfig) {
310 todo!()
311 }
312
313 fn image_alloc(
314 &mut self,
315 _: (u32, u32),
316 ) -> std::result::Result<crate::draw::ImageId, crate::draw::AllocError> {
317 todo!()
318 }
319
320 fn image_upload(&mut self, _: crate::draw::ImageId, _: &[u8], _: crate::draw::ImageFormat) {
321 todo!()
322 }
323
324 fn image_free(&mut self, _: crate::draw::ImageId) {
325 todo!()
326 }
327
328 fn image_size(&self, _: crate::draw::ImageId) -> Option<(u32, u32)> {
329 todo!()
330 }
331
332 fn draw_image(
333 &self,
334 _: &mut Self::Draw,
335 _: crate::draw::PassId,
336 _: crate::draw::ImageId,
337 _: crate::geom::Quad,
338 ) {
339 todo!()
340 }
341
342 fn draw_text(
343 &mut self,
344 _: &mut Self::Draw,
345 _: crate::draw::PassId,
346 _: crate::geom::Vec2,
347 _: crate::geom::Quad,
348 _: &kas_text::TextDisplay,
349 _: crate::draw::color::Rgba,
350 ) {
351 todo!()
352 }
353
354 fn draw_text_effects(
355 &mut self,
356 _: &mut Self::Draw,
357 _: crate::draw::PassId,
358 _: crate::geom::Vec2,
359 _: crate::geom::Quad,
360 _: &kas_text::TextDisplay,
361 _: &[kas_text::Effect],
362 _: &[crate::draw::color::Rgba],
363 ) {
364 todo!()
365 }
366 }
367
368 struct Surface;
369 impl WindowSurface for Surface {
370 type Shared = DrawShared;
371
372 fn size(&self) -> crate::prelude::Size {
373 todo!()
374 }
375
376 fn configure(&mut self, _: &mut Self::Shared, _: crate::prelude::Size) -> bool {
377 todo!()
378 }
379
380 fn draw_iface<'iface>(
381 &'iface mut self,
382 _: &'iface mut crate::draw::SharedState<Self::Shared>,
383 ) -> crate::draw::DrawIface<'iface, Self::Shared> {
384 todo!()
385 }
386
387 fn common_mut(&mut self) -> &mut crate::draw::WindowCommon {
388 todo!()
389 }
390
391 fn present(&mut self, _: &mut Self::Shared, _: crate::draw::color::Rgba) -> Instant {
392 todo!()
393 }
394 }
395
396 struct AGB;
397 impl GraphicsInstance for AGB {
398 type Shared = DrawShared;
399
400 type Surface<'a> = Surface;
401
402 fn new_shared(&mut self, _: Option<&Self::Surface<'_>>) -> Result<Self::Shared> {
403 todo!()
404 }
405
406 fn new_surface<'window, W>(&mut self, _: W, _: bool) -> Result<Self::Surface<'window>>
407 where
408 W: rwh::HasWindowHandle + rwh::HasDisplayHandle + Send + Sync + 'window,
409 Self: Sized,
410 {
411 todo!()
412 }
413 }
414
415 #[test]
416 fn size_of_pending() {
417 assert_eq!(
418 std::mem::size_of::<Pending<(), AGB, crate::theme::SimpleTheme>>(),
419 40
420 );
421 }
422}