use core::fmt;
#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "macos")]
#[doc(hidden)]
pub use macos::integration;
#[cfg(target_os = "macos")]
pub use macos::{Application, SurfaceTarget, Window};
#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "linux")]
#[doc(hidden)]
pub use linux::integration;
#[cfg(target_os = "linux")]
pub use linux::{Application, SurfaceTarget, Window};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct LogicalSize {
width: u32,
height: u32,
}
impl LogicalSize {
#[must_use]
pub const fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
#[must_use]
pub const fn width(self) -> u32 {
self.width
}
#[must_use]
pub const fn height(self) -> u32 {
self.height
}
#[must_use]
pub const fn is_empty(self) -> bool {
self.width == 0 || self.height == 0
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct PhysicalExtent {
width: u32,
height: u32,
}
impl PhysicalExtent {
#[must_use]
pub const fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
#[must_use]
pub const fn width(self) -> u32 {
self.width
}
#[must_use]
pub const fn height(self) -> u32 {
self.height
}
#[must_use]
pub const fn is_empty(self) -> bool {
self.width == 0 || self.height == 0
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct WindowRevision(u64);
impl WindowRevision {
#[cfg_attr(not(any(target_os = "macos", target_os = "linux")), allow(dead_code))]
pub(crate) const INITIAL: Self = Self(1);
#[cfg_attr(not(any(target_os = "macos", target_os = "linux")), allow(dead_code))]
pub(crate) const fn next(self) -> Self {
Self(self.0.saturating_add(1))
}
#[must_use]
pub const fn get(self) -> u64 {
self.0
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct WindowMetrics {
extent: PhysicalExtent,
scale_factor: f64,
revision: WindowRevision,
}
impl WindowMetrics {
#[cfg_attr(not(any(target_os = "macos", target_os = "linux")), allow(dead_code))]
pub(crate) const fn new(
extent: PhysicalExtent,
scale_factor: f64,
revision: WindowRevision,
) -> Self {
Self {
extent,
scale_factor,
revision,
}
}
#[must_use]
pub const fn extent(self) -> PhysicalExtent {
self.extent
}
#[must_use]
pub const fn scale_factor(self) -> f64 {
self.scale_factor
}
#[must_use]
pub const fn revision(self) -> WindowRevision {
self.revision
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct WindowDescriptor {
title: String,
logical_size: LogicalSize,
}
impl WindowDescriptor {
pub fn new(title: impl Into<String>, logical_size: LogicalSize) -> Self {
Self {
title: title.into(),
logical_size,
}
}
#[must_use]
pub fn title(&self) -> &str {
&self.title
}
#[must_use]
pub const fn logical_size(&self) -> LogicalSize {
self.logical_size
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[non_exhaustive]
pub enum WindowEvent {
MetricsChanged(WindowMetrics),
RenderingSuspended,
RenderingResumed(WindowMetrics),
RedrawRequested(WindowMetrics),
CloseRequested,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PumpStatus {
Continue,
Exit,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PlatformError(String);
impl PlatformError {
#[cfg_attr(not(any(target_os = "macos", target_os = "linux")), allow(dead_code))]
pub(crate) fn new(message: impl Into<String>) -> Self {
Self(message.into())
}
}
impl fmt::Display for PlatformError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(&self.0)
}
}
impl std::error::Error for PlatformError {}
#[cfg(test)]
mod tests {
use super::{LogicalSize, PhysicalExtent, WindowDescriptor, WindowRevision};
#[test]
fn empty_extent_requires_a_zero_dimension() {
assert!(PhysicalExtent::new(0, 9).is_empty());
assert!(PhysicalExtent::new(7, 0).is_empty());
assert!(!PhysicalExtent::new(7, 9).is_empty());
}
#[test]
fn window_revisions_are_monotonic() {
let initial = WindowRevision::INITIAL;
assert_eq!(initial.get(), 1);
assert_eq!(initial.next().get(), 2);
}
#[test]
fn window_descriptor_preserves_game_intent() {
let descriptor = WindowDescriptor::new("Mulciber", LogicalSize::new(960, 540));
assert_eq!(descriptor.title(), "Mulciber");
assert_eq!(descriptor.logical_size(), LogicalSize::new(960, 540));
}
}