Skip to main content

baseview/
window.rs

1use std::marker::PhantomData;
2
3use raw_window_handle::{
4    HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
5};
6
7use crate::event::{Event, EventStatus};
8use crate::window_open_options::WindowOpenOptions;
9use crate::{MouseCursor, Size};
10
11#[cfg(target_os = "macos")]
12use crate::macos as platform;
13#[cfg(target_os = "windows")]
14use crate::win as platform;
15#[cfg(target_os = "linux")]
16use crate::x11 as platform;
17
18pub struct WindowHandle {
19    window_handle: platform::WindowHandle,
20    // so that WindowHandle is !Send on all platforms
21    phantom: PhantomData<*mut ()>,
22}
23
24impl WindowHandle {
25    fn new(window_handle: platform::WindowHandle) -> Self {
26        Self { window_handle, phantom: PhantomData }
27    }
28
29    /// Close the window
30    pub fn close(&mut self) {
31        self.window_handle.close();
32    }
33
34    /// Returns `true` if the window is still open, and returns `false`
35    /// if the window was closed/dropped.
36    pub fn is_open(&self) -> bool {
37        self.window_handle.is_open()
38    }
39}
40
41unsafe impl HasRawWindowHandle for WindowHandle {
42    fn raw_window_handle(&self) -> RawWindowHandle {
43        self.window_handle.raw_window_handle()
44    }
45}
46
47pub trait WindowHandler {
48    fn on_frame(&mut self, window: &mut Window);
49    fn on_event(&mut self, window: &mut Window, event: Event) -> EventStatus;
50}
51
52pub struct Window<'a> {
53    window: platform::Window<'a>,
54
55    // so that Window is !Send on all platforms
56    phantom: PhantomData<*mut ()>,
57}
58
59impl<'a> Window<'a> {
60    #[cfg(target_os = "windows")]
61    pub(crate) fn new(window: platform::Window<'a>) -> Window<'a> {
62        Window { window, phantom: PhantomData }
63    }
64
65    #[cfg(not(target_os = "windows"))]
66    pub(crate) fn new(window: platform::Window<'a>) -> Window<'a> {
67        Window { window, phantom: PhantomData }
68    }
69
70    pub fn open_parented<P, H, B>(parent: &P, options: WindowOpenOptions, build: B) -> WindowHandle
71    where
72        P: HasRawWindowHandle,
73        H: WindowHandler + 'static,
74        B: FnOnce(&mut Window) -> H,
75        B: Send + 'static,
76    {
77        let window_handle = platform::Window::open_parented::<P, H, B>(parent, options, build);
78        WindowHandle::new(window_handle)
79    }
80
81    pub fn open_blocking<H, B>(options: WindowOpenOptions, build: B)
82    where
83        H: WindowHandler + 'static,
84        B: FnOnce(&mut Window) -> H,
85        B: Send + 'static,
86    {
87        platform::Window::open_blocking::<H, B>(options, build)
88    }
89
90    /// Close the window
91    pub fn close(&mut self) {
92        self.window.close();
93    }
94
95    /// Resize the window to the given size. The size is always in logical pixels. DPI scaling will
96    /// automatically be accounted for.
97    pub fn resize(&mut self, size: Size) {
98        self.window.resize(size);
99    }
100
101    /// Re-interpret the window at a new content-scale factor, holding the
102    /// logical size constant and growing/shrinking the physical size to match.
103    ///
104    /// This is for embedded plug-in views whose scale becomes known only after
105    /// the window is attached (the `WindowScalePolicy` chosen at open is
106    /// otherwise fixed for the window's lifetime). Implemented on X11, where a
107    /// host may report its content scale late via
108    /// `IPlugViewContentScaleSupport`; a no-op on Windows and macOS, which
109    /// drive DPI through the OS. The change is applied on the next event-loop
110    /// iteration and reported to the handler via a `Resized` event.
111    pub fn set_scale_factor(&mut self, scale: f64) {
112        self.window.set_scale_factor(scale);
113    }
114
115    pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) {
116        self.window.set_mouse_cursor(cursor);
117    }
118
119    pub fn has_focus(&mut self) -> bool {
120        self.window.has_focus()
121    }
122
123    pub fn focus(&mut self) {
124        self.window.focus()
125    }
126
127    /// If provided, then an OpenGL context will be created for this window. You'll be able to
128    /// access this context through [crate::Window::gl_context].
129    #[cfg(feature = "opengl")]
130    pub fn gl_context(&self) -> Option<&crate::gl::GlContext> {
131        self.window.gl_context()
132    }
133}
134
135unsafe impl<'a> HasRawWindowHandle for Window<'a> {
136    fn raw_window_handle(&self) -> RawWindowHandle {
137        self.window.raw_window_handle()
138    }
139}
140
141unsafe impl<'a> HasRawDisplayHandle for Window<'a> {
142    fn raw_display_handle(&self) -> RawDisplayHandle {
143        self.window.raw_display_handle()
144    }
145}