use crate::draw::{color::Rgba, DrawIface, WindowCommon};
use crate::draw::{DrawImpl, DrawShared, DrawSharedImpl};
use crate::event::CursorIcon;
use crate::geom::Size;
use crate::theme::{ThemeControl, ThemeSize};
use crate::{Action, Window, WindowId};
use raw_window_handle as raw;
use std::any::TypeId;
use thiserror::Error;
#[non_exhaustive]
#[derive(Error, Debug)]
pub enum Error {
#[error("error from graphics sub-system")]
Graphics(Box<dyn std::error::Error + 'static>),
#[error("config load/save error")]
Config(#[from] kas::config::Error),
#[error("event loop")]
EventLoop(#[from] winit::error::EventLoopError),
}
impl From<winit::error::OsError> for Error {
fn from(error: winit::error::OsError) -> Self {
Error::EventLoop(winit::error::EventLoopError::Os(error))
}
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Platform {
#[cfg(target_os = "android")]
Android,
#[cfg(target_os = "ios")]
IOS,
#[cfg(target_os = "macos")]
MacOS,
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
Wayland,
#[cfg(target_arch = "wasm32")]
Web,
#[cfg(target_os = "windows")]
Windows,
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
X11,
}
impl Platform {
pub fn is_android(&self) -> bool {
cfg_if::cfg_if! {
if #[cfg(target_os = "android")] {
true
} else {
false
}
}
}
pub fn is_ios(&self) -> bool {
cfg_if::cfg_if! {
if #[cfg(target_os = "ios")] {
true
} else {
false
}
}
}
pub fn is_macos(&self) -> bool {
cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
true
} else {
false
}
}
}
pub fn is_wayland(&self) -> bool {
cfg_if::cfg_if! {
if #[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))] {
matches!(self, Platform::Wayland)
} else {
false
}
}
}
pub fn is_web(&self) -> bool {
cfg_if::cfg_if! {
if #[cfg(target_arch = "wasm32")] {
true
} else {
false
}
}
}
pub fn is_windows(&self) -> bool {
cfg_if::cfg_if! {
if #[cfg(target_os = "windows")] {
true
} else {
false
}
}
}
pub fn is_x11(&self) -> bool {
cfg_if::cfg_if! {
if #[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))] {
matches!(self, Platform::X11)
} else {
false
}
}
}
}
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
pub trait GraphicalShell {
type Shared: DrawSharedImpl;
type Window: DrawImpl;
type Surface: WindowSurface<Shared = Self::Shared> + 'static;
fn build(self) -> Result<Self::Shared>;
}
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
pub trait WindowSurface {
type Shared: kas::draw::DrawSharedImpl;
fn new<W: raw::HasRawWindowHandle + raw::HasRawDisplayHandle>(
shared: &mut Self::Shared,
size: Size,
window: W,
) -> Result<Self>
where
Self: Sized;
fn size(&self) -> Size;
fn do_resize(&mut self, shared: &mut Self::Shared, size: Size) -> bool;
fn draw_iface<'iface>(
&'iface mut self,
shared: &'iface mut kas::draw::SharedState<Self::Shared>,
) -> DrawIface<'iface, Self::Shared>;
fn common_mut(&mut self) -> &mut WindowCommon;
fn present(&mut self, shared: &mut Self::Shared, clear_color: Rgba);
}
pub(crate) trait ShellWindow {
fn add_popup(&mut self, popup: crate::PopupDescriptor) -> WindowId;
unsafe fn add_window(&mut self, window: Window<()>, data_type_id: TypeId) -> WindowId;
fn close_window(&mut self, id: WindowId);
fn get_clipboard(&mut self) -> Option<String>;
fn set_clipboard(&mut self, content: String);
fn get_primary(&mut self) -> Option<String>;
fn set_primary(&mut self, content: String);
fn adjust_theme<'s>(&'s mut self, f: Box<dyn FnOnce(&mut dyn ThemeControl) -> Action + 's>);
fn size_and_draw_shared<'s>(
&'s mut self,
f: Box<dyn FnOnce(&dyn ThemeSize, &mut dyn DrawShared) + 's>,
);
fn set_cursor_icon(&mut self, icon: CursorIcon);
fn platform(&self) -> Platform;
#[cfg(winit)]
fn winit_window(&self) -> Option<&winit::window::Window>;
fn waker(&self) -> &std::task::Waker;
}