//! Platform-independent window API and handler trait. use std::marker::PhantomData; use raw_window_handle::{ HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, }; use crate::event::{Event, EventStatus}; use crate::window_open_options::WindowOpenOptions; use crate::{MouseCursor, PhySize, Size}; #[cfg(target_os = "macos")] use crate::macos as platform; #[cfg(target_os = "windows")] use crate::win as platform; #[cfg(target_os = "linux")] use crate::x11 as platform; /// Opaque handle to an open window, used to close it or check liveness. pub struct WindowHandle { window_handle: platform::WindowHandle, // so that WindowHandle is !Send on all platforms phantom: PhantomData<*mut ()>, } impl WindowHandle { fn new(window_handle: platform::WindowHandle) -> Self { Self { window_handle, phantom: PhantomData } } /// Close the window pub fn close(&mut self) { self.window_handle.close(); } /// Returns `true` if the window is still open, and returns `false` /// if the window was closed/dropped. pub fn is_open(&self) -> bool { self.window_handle.is_open() } } unsafe impl HasRawWindowHandle for WindowHandle { fn raw_window_handle(&self) -> RawWindowHandle { self.window_handle.raw_window_handle() } } /// Trait implemented by the application to receive window events and frame callbacks. pub trait WindowHandler { fn on_frame(&mut self, window: &mut Window); fn on_event(&mut self, window: &mut Window, event: Event) -> EventStatus; } /// A window that can be drawn to and receive events. pub struct Window<'a> { window: platform::Window<'a>, // so that Window is !Send on all platforms phantom: PhantomData<*mut ()>, } impl<'a> Window<'a> { #[cfg(target_os = "windows")] pub(crate) fn new(window: platform::Window<'a>) -> Window<'a> { Window { window, phantom: PhantomData } } #[cfg(not(target_os = "windows"))] pub(crate) fn new(window: platform::Window) -> Window { Window { window, phantom: PhantomData } } /// Open a window as a child of the given parent. pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> WindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, B: FnOnce(&mut Window) -> H, B: Send + 'static, { let window_handle = platform::Window::open_parented::(parent, options, build); WindowHandle::new(window_handle) } /// Open a standalone window and block until it is closed. pub fn open_blocking(options: WindowOpenOptions, build: B) where H: WindowHandler + 'static, B: FnOnce(&mut Window) -> H, B: Send + 'static, { platform::Window::open_blocking::(options, build) } /// Close the window pub fn close(&mut self) { self.window.close(); } /// Returns the current physical size of the window by querying the OS directly. pub fn physical_size(&self) -> PhySize { self.window.physical_size() } /// Resize the window to the given size. The size is always in logical pixels. DPI scaling will /// automatically be accounted for. pub fn resize(&mut self, size: Size) { self.window.resize(size); } /// Set the mouse cursor icon. pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) { self.window.set_mouse_cursor(cursor); } /// Whether this window currently has keyboard focus. pub fn has_focus(&mut self) -> bool { self.window.has_focus() } /// Request keyboard focus for this window. pub fn focus(&mut self) { self.window.focus() } /// If provided, then an OpenGL context will be created for this window. You'll be able to /// access this context through [crate::Window::gl_context]. #[cfg(feature = "opengl")] pub fn gl_context(&self) -> Option<&crate::gl::GlContext> { self.window.gl_context() } } unsafe impl<'a> HasRawWindowHandle for Window<'a> { fn raw_window_handle(&self) -> RawWindowHandle { self.window.raw_window_handle() } } unsafe impl<'a> HasRawDisplayHandle for Window<'a> { fn raw_display_handle(&self) -> RawDisplayHandle { self.window.raw_display_handle() } }