use std::fmt;
use crate::{
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
error::{ExternalError, NotSupportedError, OsError},
event_loop::EventLoopWindowTarget,
monitor::{MonitorHandle, VideoMode},
platform_impl, SendSyncWrapper,
};
pub use crate::icon::{BadIcon, Icon};
#[doc(inline)]
pub use cursor_icon::{CursorIcon, ParseError as CursorIconParseError};
pub struct Window {
pub(crate) window: platform_impl::Window,
}
impl fmt::Debug for Window {
fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
fmtr.pad("Window { .. }")
}
}
impl Drop for Window {
fn drop(&mut self) {
self.window.maybe_wait_on_main(|w| {
if let Some(Fullscreen::Exclusive(_)) = w.fullscreen().map(|f| f.into()) {
w.set_fullscreen(None);
}
})
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId(pub(crate) platform_impl::WindowId);
impl WindowId {
pub const unsafe fn dummy() -> Self {
#[allow(unused_unsafe)]
WindowId(unsafe { platform_impl::WindowId::dummy() })
}
}
impl From<WindowId> for u64 {
fn from(window_id: WindowId) -> Self {
window_id.0.into()
}
}
impl From<u64> for WindowId {
fn from(raw_id: u64) -> Self {
Self(raw_id.into())
}
}
#[derive(Clone, Default)]
#[must_use]
pub struct WindowBuilder {
pub(crate) window: WindowAttributes,
pub(crate) platform_specific: platform_impl::PlatformSpecificWindowBuilderAttributes,
}
impl fmt::Debug for WindowBuilder {
fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
fmtr.debug_struct("WindowBuilder")
.field("window", &self.window)
.finish()
}
}
#[derive(Debug, Clone)]
pub struct WindowAttributes {
pub inner_size: Option<Size>,
pub min_inner_size: Option<Size>,
pub max_inner_size: Option<Size>,
pub position: Option<Position>,
pub resizable: bool,
pub enabled_buttons: WindowButtons,
pub title: String,
pub maximized: bool,
pub visible: bool,
pub transparent: bool,
pub blur: bool,
pub decorations: bool,
pub window_icon: Option<Icon>,
pub preferred_theme: Option<Theme>,
pub resize_increments: Option<Size>,
pub content_protected: bool,
pub window_level: WindowLevel,
pub active: bool,
#[cfg(feature = "rwh_06")]
pub(crate) parent_window: SendSyncWrapper<Option<rwh_06::RawWindowHandle>>,
pub(crate) fullscreen: SendSyncWrapper<Option<Fullscreen>>,
}
impl Default for WindowAttributes {
#[inline]
fn default() -> WindowAttributes {
WindowAttributes {
inner_size: None,
min_inner_size: None,
max_inner_size: None,
position: None,
resizable: true,
enabled_buttons: WindowButtons::all(),
title: "winit window".to_owned(),
maximized: false,
fullscreen: SendSyncWrapper(None),
visible: true,
transparent: false,
blur: false,
decorations: true,
window_level: Default::default(),
window_icon: None,
preferred_theme: None,
resize_increments: None,
content_protected: false,
#[cfg(feature = "rwh_06")]
parent_window: SendSyncWrapper(None),
active: true,
}
}
}
impl WindowAttributes {
#[cfg(feature = "rwh_06")]
pub fn parent_window(&self) -> Option<&rwh_06::RawWindowHandle> {
self.parent_window.0.as_ref()
}
pub fn fullscreen(&self) -> Option<&Fullscreen> {
self.fullscreen.0.as_ref()
}
}
impl WindowBuilder {
#[inline]
pub fn new() -> Self {
Default::default()
}
}
impl WindowBuilder {
pub fn window_attributes(&self) -> &WindowAttributes {
&self.window
}
#[inline]
pub fn with_inner_size<S: Into<Size>>(mut self, size: S) -> Self {
self.window.inner_size = Some(size.into());
self
}
#[inline]
pub fn with_min_inner_size<S: Into<Size>>(mut self, min_size: S) -> Self {
self.window.min_inner_size = Some(min_size.into());
self
}
#[inline]
pub fn with_max_inner_size<S: Into<Size>>(mut self, max_size: S) -> Self {
self.window.max_inner_size = Some(max_size.into());
self
}
#[inline]
pub fn with_position<P: Into<Position>>(mut self, position: P) -> Self {
self.window.position = Some(position.into());
self
}
#[inline]
pub fn with_resizable(mut self, resizable: bool) -> Self {
self.window.resizable = resizable;
self
}
#[inline]
pub fn with_enabled_buttons(mut self, buttons: WindowButtons) -> Self {
self.window.enabled_buttons = buttons;
self
}
#[inline]
pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
self.window.title = title.into();
self
}
#[inline]
pub fn with_fullscreen(mut self, fullscreen: Option<Fullscreen>) -> Self {
self.window.fullscreen = SendSyncWrapper(fullscreen);
self
}
#[inline]
pub fn with_maximized(mut self, maximized: bool) -> Self {
self.window.maximized = maximized;
self
}
#[inline]
pub fn with_visible(mut self, visible: bool) -> Self {
self.window.visible = visible;
self
}
#[inline]
pub fn with_transparent(mut self, transparent: bool) -> Self {
self.window.transparent = transparent;
self
}
#[inline]
pub fn with_blur(mut self, blur: bool) -> Self {
self.window.blur = blur;
self
}
#[inline]
pub fn transparent(&self) -> bool {
self.window.transparent
}
#[inline]
pub fn with_decorations(mut self, decorations: bool) -> Self {
self.window.decorations = decorations;
self
}
#[inline]
pub fn with_window_level(mut self, level: WindowLevel) -> Self {
self.window.window_level = level;
self
}
#[inline]
pub fn with_window_icon(mut self, window_icon: Option<Icon>) -> Self {
self.window.window_icon = window_icon;
self
}
#[inline]
pub fn with_theme(mut self, theme: Option<Theme>) -> Self {
self.window.preferred_theme = theme;
self
}
#[inline]
pub fn with_resize_increments<S: Into<Size>>(mut self, resize_increments: S) -> Self {
self.window.resize_increments = Some(resize_increments.into());
self
}
#[inline]
pub fn with_content_protected(mut self, protected: bool) -> Self {
self.window.content_protected = protected;
self
}
#[inline]
pub fn with_active(mut self, active: bool) -> Self {
self.window.active = active;
self
}
#[cfg(feature = "rwh_06")]
#[inline]
pub unsafe fn with_parent_window(
mut self,
parent_window: Option<rwh_06::RawWindowHandle>,
) -> Self {
self.window.parent_window = SendSyncWrapper(parent_window);
self
}
#[inline]
pub fn build<T: 'static>(
self,
window_target: &EventLoopWindowTarget<T>,
) -> Result<Window, OsError> {
let window =
platform_impl::Window::new(&window_target.p, self.window, self.platform_specific)?;
window.maybe_queue_on_main(|w| w.request_redraw());
Ok(Window { window })
}
}
impl Window {
#[inline]
pub fn new<T: 'static>(event_loop: &EventLoopWindowTarget<T>) -> Result<Window, OsError> {
let builder = WindowBuilder::new();
builder.build(event_loop)
}
#[inline]
pub fn id(&self) -> WindowId {
self.window.maybe_wait_on_main(|w| WindowId(w.id()))
}
#[inline]
pub fn scale_factor(&self) -> f64 {
self.window.maybe_wait_on_main(|w| w.scale_factor())
}
#[inline]
pub fn request_redraw(&self) {
self.window.maybe_queue_on_main(|w| w.request_redraw())
}
#[inline]
pub fn pre_present_notify(&self) {
self.window.maybe_queue_on_main(|w| w.pre_present_notify());
}
pub fn reset_dead_keys(&self) {
self.window.maybe_queue_on_main(|w| w.reset_dead_keys())
}
}
impl Window {
#[inline]
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
self.window.maybe_wait_on_main(|w| w.inner_position())
}
#[inline]
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
self.window.maybe_wait_on_main(|w| w.outer_position())
}
#[inline]
pub fn set_outer_position<P: Into<Position>>(&self, position: P) {
let position = position.into();
self.window
.maybe_queue_on_main(move |w| w.set_outer_position(position))
}
#[inline]
pub fn inner_size(&self) -> PhysicalSize<u32> {
self.window.maybe_wait_on_main(|w| w.inner_size())
}
#[inline]
#[must_use]
pub fn request_inner_size<S: Into<Size>>(&self, size: S) -> Option<PhysicalSize<u32>> {
let size = size.into();
self.window
.maybe_wait_on_main(|w| w.request_inner_size(size))
}
#[inline]
pub fn outer_size(&self) -> PhysicalSize<u32> {
self.window.maybe_wait_on_main(|w| w.outer_size())
}
#[inline]
pub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>) {
let min_size = min_size.map(|s| s.into());
self.window
.maybe_queue_on_main(move |w| w.set_min_inner_size(min_size))
}
#[inline]
pub fn set_max_inner_size<S: Into<Size>>(&self, max_size: Option<S>) {
let max_size = max_size.map(|s| s.into());
self.window
.maybe_queue_on_main(move |w| w.set_max_inner_size(max_size))
}
#[inline]
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
self.window.maybe_wait_on_main(|w| w.resize_increments())
}
#[inline]
pub fn set_resize_increments<S: Into<Size>>(&self, increments: Option<S>) {
let increments = increments.map(Into::into);
self.window
.maybe_queue_on_main(move |w| w.set_resize_increments(increments))
}
}
impl Window {
#[inline]
pub fn set_title(&self, title: &str) {
self.window.maybe_wait_on_main(|w| w.set_title(title))
}
#[inline]
pub fn set_transparent(&self, transparent: bool) {
self.window
.maybe_queue_on_main(move |w| w.set_transparent(transparent))
}
#[inline]
pub fn set_blur(&self, blur: bool) {
self.window.maybe_queue_on_main(move |w| w.set_blur(blur))
}
#[inline]
pub fn set_visible(&self, visible: bool) {
self.window
.maybe_queue_on_main(move |w| w.set_visible(visible))
}
#[inline]
pub fn is_visible(&self) -> Option<bool> {
self.window.maybe_wait_on_main(|w| w.is_visible())
}
#[inline]
pub fn set_resizable(&self, resizable: bool) {
self.window
.maybe_queue_on_main(move |w| w.set_resizable(resizable))
}
#[inline]
pub fn is_resizable(&self) -> bool {
self.window.maybe_wait_on_main(|w| w.is_resizable())
}
pub fn set_enabled_buttons(&self, buttons: WindowButtons) {
self.window
.maybe_queue_on_main(move |w| w.set_enabled_buttons(buttons))
}
pub fn enabled_buttons(&self) -> WindowButtons {
self.window.maybe_wait_on_main(|w| w.enabled_buttons())
}
#[inline]
pub fn set_minimized(&self, minimized: bool) {
self.window
.maybe_queue_on_main(move |w| w.set_minimized(minimized))
}
#[inline]
pub fn is_minimized(&self) -> Option<bool> {
self.window.maybe_wait_on_main(|w| w.is_minimized())
}
#[inline]
pub fn set_maximized(&self, maximized: bool) {
self.window
.maybe_queue_on_main(move |w| w.set_maximized(maximized))
}
#[inline]
pub fn is_maximized(&self) -> bool {
self.window.maybe_wait_on_main(|w| w.is_maximized())
}
#[inline]
pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
self.window
.maybe_queue_on_main(move |w| w.set_fullscreen(fullscreen.map(|f| f.into())))
}
#[inline]
pub fn fullscreen(&self) -> Option<Fullscreen> {
self.window
.maybe_wait_on_main(|w| w.fullscreen().map(|f| f.into()))
}
#[inline]
pub fn set_decorations(&self, decorations: bool) {
self.window
.maybe_queue_on_main(move |w| w.set_decorations(decorations))
}
#[inline]
pub fn is_decorated(&self) -> bool {
self.window.maybe_wait_on_main(|w| w.is_decorated())
}
pub fn set_window_level(&self, level: WindowLevel) {
self.window
.maybe_queue_on_main(move |w| w.set_window_level(level))
}
#[inline]
pub fn set_window_icon(&self, window_icon: Option<Icon>) {
self.window
.maybe_queue_on_main(move |w| w.set_window_icon(window_icon))
}
#[inline]
pub fn set_ime_cursor_area<P: Into<Position>, S: Into<Size>>(&self, position: P, size: S) {
let position = position.into();
let size = size.into();
self.window
.maybe_queue_on_main(move |w| w.set_ime_cursor_area(position, size))
}
#[inline]
pub fn set_ime_allowed(&self, allowed: bool) {
self.window
.maybe_queue_on_main(move |w| w.set_ime_allowed(allowed))
}
#[inline]
pub fn set_ime_purpose(&self, purpose: ImePurpose) {
self.window
.maybe_queue_on_main(move |w| w.set_ime_purpose(purpose))
}
#[inline]
pub fn focus_window(&self) {
self.window.maybe_queue_on_main(|w| w.focus_window())
}
#[inline]
pub fn has_focus(&self) -> bool {
self.window.maybe_wait_on_main(|w| w.has_focus())
}
#[inline]
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
self.window
.maybe_queue_on_main(move |w| w.request_user_attention(request_type))
}
#[inline]
pub fn set_theme(&self, theme: Option<Theme>) {
self.window.maybe_queue_on_main(move |w| w.set_theme(theme))
}
#[inline]
pub fn theme(&self) -> Option<Theme> {
self.window.maybe_wait_on_main(|w| w.theme())
}
pub fn set_content_protected(&self, protected: bool) {
self.window
.maybe_queue_on_main(move |w| w.set_content_protected(protected))
}
#[inline]
pub fn title(&self) -> String {
self.window.maybe_wait_on_main(|w| w.title())
}
}
impl Window {
#[inline]
pub fn set_cursor_icon(&self, cursor: CursorIcon) {
self.window
.maybe_queue_on_main(move |w| w.set_cursor_icon(cursor))
}
#[inline]
pub fn set_cursor_position<P: Into<Position>>(&self, position: P) -> Result<(), ExternalError> {
let position = position.into();
self.window
.maybe_wait_on_main(|w| w.set_cursor_position(position))
}
#[inline]
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
self.window.maybe_wait_on_main(|w| w.set_cursor_grab(mode))
}
#[inline]
pub fn set_cursor_visible(&self, visible: bool) {
self.window
.maybe_queue_on_main(move |w| w.set_cursor_visible(visible))
}
#[inline]
pub fn drag_window(&self) -> Result<(), ExternalError> {
self.window.maybe_wait_on_main(|w| w.drag_window())
}
#[inline]
pub fn drag_resize_window(&self, direction: ResizeDirection) -> Result<(), ExternalError> {
self.window
.maybe_wait_on_main(|w| w.drag_resize_window(direction))
}
pub fn show_window_menu(&self, position: impl Into<Position>) {
let position = position.into();
self.window
.maybe_queue_on_main(move |w| w.show_window_menu(position))
}
#[inline]
pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
self.window
.maybe_wait_on_main(|w| w.set_cursor_hittest(hittest))
}
}
impl Window {
#[inline]
pub fn current_monitor(&self) -> Option<MonitorHandle> {
self.window
.maybe_wait_on_main(|w| w.current_monitor().map(|inner| MonitorHandle { inner }))
}
#[inline]
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
self.window.maybe_wait_on_main(|w| {
w.available_monitors()
.into_iter()
.map(|inner| MonitorHandle { inner })
})
}
#[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
self.window
.maybe_wait_on_main(|w| w.primary_monitor().map(|inner| MonitorHandle { inner }))
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasWindowHandle for Window {
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
let raw = self
.window
.maybe_wait_on_main(|w| w.raw_window_handle_rwh_06().map(SendSyncWrapper))?
.0;
Ok(unsafe { rwh_06::WindowHandle::borrow_raw(raw) })
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for Window {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
let raw = self
.window
.maybe_wait_on_main(|w| w.raw_display_handle_rwh_06().map(SendSyncWrapper))?
.0;
Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) })
}
}
#[cfg(feature = "rwh_05")]
unsafe impl rwh_05::HasRawWindowHandle for Window {
fn raw_window_handle(&self) -> rwh_05::RawWindowHandle {
self.window
.maybe_wait_on_main(|w| SendSyncWrapper(w.raw_window_handle_rwh_05()))
.0
}
}
#[cfg(feature = "rwh_05")]
unsafe impl rwh_05::HasRawDisplayHandle for Window {
fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle {
self.window
.maybe_wait_on_main(|w| SendSyncWrapper(w.raw_display_handle_rwh_05()))
.0
}
}
#[cfg(feature = "rwh_04")]
unsafe impl rwh_04::HasRawWindowHandle for Window {
fn raw_window_handle(&self) -> rwh_04::RawWindowHandle {
self.window
.maybe_wait_on_main(|w| SendSyncWrapper(w.raw_window_handle_rwh_04()))
.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum CursorGrabMode {
None,
Confined,
Locked,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ResizeDirection {
East,
North,
NorthEast,
NorthWest,
South,
SouthEast,
SouthWest,
West,
}
impl From<ResizeDirection> for CursorIcon {
fn from(direction: ResizeDirection) -> Self {
use ResizeDirection::*;
match direction {
East => CursorIcon::EResize,
North => CursorIcon::NResize,
NorthEast => CursorIcon::NeResize,
NorthWest => CursorIcon::NwResize,
South => CursorIcon::SResize,
SouthEast => CursorIcon::SeResize,
SouthWest => CursorIcon::SwResize,
West => CursorIcon::WResize,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Fullscreen {
Exclusive(VideoMode),
Borderless(Option<MonitorHandle>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Theme {
Light,
Dark,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum UserAttentionType {
Critical,
#[default]
Informational,
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct WindowButtons: u32 {
const CLOSE = 1 << 0;
const MINIMIZE = 1 << 1;
const MAXIMIZE = 1 << 2;
}
}
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
pub enum WindowLevel {
AlwaysOnBottom,
#[default]
Normal,
AlwaysOnTop,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[non_exhaustive]
pub enum ImePurpose {
Normal,
Password,
Terminal,
}
impl Default for ImePurpose {
fn default() -> Self {
Self::Normal
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ActivationToken {
pub(crate) _token: String,
}
impl ActivationToken {
pub(crate) fn _new(_token: String) -> Self {
Self { _token }
}
}