mod common;
mod event_loop;
mod runner;
mod shared;
mod window;
use crate::ConfigAction;
use crate::messages::Erased;
use crate::window::{BoxedWindow, PopupDescriptor, WindowId};
use event_loop::Loop;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
pub(crate) use shared::RunnerT;
use shared::Shared;
use std::fmt::Debug;
pub use window::Window;
pub(crate) use window::WindowDataErased;
pub use common::{Error, Platform, Result};
pub use runner::{ClosedError, PreLaunchState, Proxy};
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
pub use common::{GraphicsFeatures, GraphicsInstance, RunError, WindowSurface};
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
pub extern crate raw_window_handle;
pub trait HasDisplayAndWindowHandle: HasDisplayHandle + HasWindowHandle + 'static {}
impl<W: HasDisplayHandle + HasWindowHandle + 'static> HasDisplayAndWindowHandle for W {}
#[must_use]
#[derive(Debug, Default)]
pub(crate) struct MessageStack {
base: usize,
count: usize,
stack: Vec<Erased>,
}
impl MessageStack {
#[inline]
pub(crate) fn new() -> Self {
MessageStack::default()
}
#[inline]
pub(crate) fn set_base(&mut self) {
self.base = self.stack.len();
}
#[inline]
pub(crate) fn get_op_count(&self) -> usize {
self.count
}
#[inline]
pub(crate) fn reset_and_has_any(&mut self) -> bool {
self.base = 0;
!self.stack.is_empty()
}
#[inline]
pub fn has_any(&self) -> bool {
self.stack.len() > self.base
}
#[inline]
pub(crate) fn push_erased(&mut self, msg: Erased) {
self.count = self.count.wrapping_add(1);
self.stack.push(msg);
}
pub(crate) fn drop_unsent(&mut self) {
self.stack.drain(self.base..);
}
pub(crate) fn clear(&mut self) {
for msg in self.stack.drain(..) {
if msg.is::<crate::event::components::KineticStart>() {
continue;
}
log::warn!(target: "kas_core::erased", "unhandled: {msg:?}");
}
self.base = 0;
self.count = 0;
}
}
pub trait ReadMessage {
fn pop_erased(&mut self) -> Option<Erased>;
fn try_pop<M: Debug + 'static>(&mut self) -> Option<M>;
fn try_peek<M: Debug + 'static>(&self) -> Option<&M>;
fn peek_debug(&self) -> Option<&dyn Debug>;
}
impl ReadMessage for MessageStack {
#[inline]
fn pop_erased(&mut self) -> Option<Erased> {
self.count = self.count.wrapping_add(1);
self.stack.pop()
}
fn try_pop<M: Debug + 'static>(&mut self) -> Option<M> {
if self.has_any() && self.stack.last().map(|m| m.is::<M>()).unwrap_or(false) {
self.count = self.count.wrapping_add(1);
self.stack.pop().unwrap().downcast::<M>().ok().map(|m| *m)
} else {
None
}
}
fn try_peek<M: Debug + 'static>(&self) -> Option<&M> {
if self.has_any() {
self.stack.last().and_then(|m| m.downcast_ref::<M>())
} else {
None
}
}
fn peek_debug(&self) -> Option<&dyn Debug> {
self.stack.last().map(Erased::debug)
}
}
impl Drop for MessageStack {
fn drop(&mut self) {
self.clear();
}
}
pub trait AppData: 'static {
fn handle_message(&mut self, messages: &mut impl ReadMessage);
fn resumed(&mut self) {}
fn suspended(&mut self) {}
fn memory_warning(&mut self) {}
}
impl AppData for () {
fn handle_message(&mut self, _: &mut impl ReadMessage) {}
fn suspended(&mut self) {}
}
enum Pending<A: AppData> {
Update,
ConfigUpdate(ConfigAction),
AddPopup(WindowId, WindowId, PopupDescriptor),
RepositionPopup(WindowId, PopupDescriptor),
AddWindow(WindowId, BoxedWindow<A>),
CloseWindow(WindowId),
Exit,
}
#[derive(Debug)]
enum ProxyAction {
CloseAll,
Close(WindowId),
Message(kas::messages::SendErased),
#[cfg(feature = "accesskit")]
AccessKit(winit::window::WindowId, accesskit_winit::WindowEvent),
}
#[cfg(feature = "accesskit")]
impl From<accesskit_winit::Event> for ProxyAction {
fn from(event: accesskit_winit::Event) -> Self {
compile_error!("AccessKit is not compatible with the current winit version")
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn size_of_pending() {
assert_eq!(std::mem::size_of::<Pending<()>>(), 40);
}
}