Skip to main content

telar_platform_headless/
window.rs

1use std::sync::Arc;
2
3use platform_core::Window;
4use raw_window_handle::{
5    DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, WindowHandle,
6};
7
8/// The one canonical offscreen window marker. It implements [`platform_core::Window`], so a single type
9/// satisfies both the renderer bound (which needs only the raw-window-handle traits) and the platform bound
10/// (`Window`). Its handles are always [`HandleError::Unavailable`] — there is no surface — so a renderer built
11/// against it must use its `new_headless` constructor, and `AppHandler` detects the unavailable handle to
12/// build an offscreen renderer. `request_redraw` is a no-op: [`crate::HeadlessPlatform`] drives frames
13/// explicitly rather than through a windowing system's redraw queue.
14///
15/// This replaces the ad-hoc `HeadlessWindow` that lived in `renderer-hardware` and the per-test `struct Fake;`
16/// markers that renderer tests each defined for themselves.
17#[derive(Clone)]
18pub struct HeadlessWindow {
19    inner: Arc<Inner>,
20}
21
22struct Inner {
23    width: u32,
24    height: u32,
25    scale_factor: f64,
26    prefers_dark: Option<bool>,
27}
28
29impl HeadlessWindow {
30    /// A logical `width`×`height` offscreen surface at scale 1.0 reporting no OS light/dark preference.
31    pub fn new(width: u32, height: u32) -> Self {
32        Self::with_options(width, height, 1.0, None)
33    }
34
35    /// Full control over the reported [`Window::scale_factor`] and [`Window::prefers_dark`].
36    pub fn with_options(
37        width: u32,
38        height: u32,
39        scale_factor: f64,
40        prefers_dark: Option<bool>,
41    ) -> Self {
42        Self {
43            inner: Arc::new(Inner {
44                width,
45                height,
46                scale_factor,
47                prefers_dark,
48            }),
49        }
50    }
51}
52
53impl HasWindowHandle for HeadlessWindow {
54    fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
55        Err(HandleError::Unavailable)
56    }
57}
58
59impl HasDisplayHandle for HeadlessWindow {
60    fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
61        Err(HandleError::Unavailable)
62    }
63}
64
65impl Window for HeadlessWindow {
66    fn width(&self) -> u32 {
67        self.inner.width
68    }
69    fn height(&self) -> u32 {
70        self.inner.height
71    }
72    fn request_redraw(&self) {}
73    fn scale_factor(&self) -> f64 {
74        self.inner.scale_factor
75    }
76    fn prefers_dark(&self) -> Option<bool> {
77        self.inner.prefers_dark
78    }
79    fn is_offscreen(&self) -> bool {
80        true
81    }
82}