use std::fmt;
use raw_window_handle::{
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
};
use crate::{
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
error::{ExternalError, NotSupportedError, OsError},
event_loop::EventLoopWindowTarget,
monitor::{MonitorHandle, VideoMode},
platform_impl,
};
pub use crate::icon::{BadIcon, Icon};
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) {
if let Some(Fullscreen::Exclusive(_)) = self.fullscreen() {
self.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 {
WindowId(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 fullscreen: Option<Fullscreen>,
pub maximized: bool,
pub visible: bool,
pub transparent: 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 parent_window: Option<RawWindowHandle>,
pub active: bool,
}
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: None,
visible: true,
transparent: false,
decorations: true,
window_level: Default::default(),
window_icon: None,
preferred_theme: None,
resize_increments: None,
content_protected: false,
parent_window: None,
active: true,
}
}
}
impl WindowBuilder {
#[inline]
pub fn new() -> Self {
Default::default()
}
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 = 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 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) -> WindowBuilder {
self.window.active = active;
self
}
#[inline]
pub unsafe fn with_parent_window(mut self, parent_window: Option<RawWindowHandle>) -> Self {
self.window.parent_window = parent_window;
self
}
#[inline]
pub fn build<T: 'static>(
self,
window_target: &EventLoopWindowTarget<T>,
) -> Result<Window, OsError> {
platform_impl::Window::new(&window_target.p, self.window, self.platform_specific).map(
|window| {
window.request_redraw();
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 {
WindowId(self.window.id())
}
#[inline]
pub fn scale_factor(&self) -> f64 {
self.window.scale_factor()
}
#[inline]
pub fn request_redraw(&self) {
self.window.request_redraw()
}
}
impl Window {
#[inline]
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
self.window.inner_position()
}
#[inline]
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
self.window.outer_position()
}
#[inline]
pub fn set_outer_position<P: Into<Position>>(&self, position: P) {
self.window.set_outer_position(position.into())
}
#[inline]
pub fn inner_size(&self) -> PhysicalSize<u32> {
self.window.inner_size()
}
#[inline]
pub fn set_inner_size<S: Into<Size>>(&self, size: S) {
self.window.set_inner_size(size.into())
}
#[inline]
pub fn outer_size(&self) -> PhysicalSize<u32> {
self.window.outer_size()
}
#[inline]
pub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>) {
self.window.set_min_inner_size(min_size.map(|s| s.into()))
}
#[inline]
pub fn set_max_inner_size<S: Into<Size>>(&self, max_size: Option<S>) {
self.window.set_max_inner_size(max_size.map(|s| s.into()))
}
#[inline]
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
self.window.resize_increments()
}
#[inline]
pub fn set_resize_increments<S: Into<Size>>(&self, increments: Option<S>) {
self.window
.set_resize_increments(increments.map(Into::into))
}
}
impl Window {
#[inline]
pub fn set_title(&self, title: &str) {
self.window.set_title(title)
}
#[inline]
pub fn set_transparent(&self, transparent: bool) {
self.window.set_transparent(transparent)
}
#[inline]
pub fn set_visible(&self, visible: bool) {
self.window.set_visible(visible)
}
#[inline]
pub fn is_visible(&self) -> Option<bool> {
self.window.is_visible()
}
#[inline]
pub fn set_resizable(&self, resizable: bool) {
self.window.set_resizable(resizable)
}
#[inline]
pub fn is_resizable(&self) -> bool {
self.window.is_resizable()
}
pub fn set_enabled_buttons(&self, buttons: WindowButtons) {
self.window.set_enabled_buttons(buttons)
}
pub fn enabled_buttons(&self) -> WindowButtons {
self.window.enabled_buttons()
}
#[inline]
pub fn set_minimized(&self, minimized: bool) {
self.window.set_minimized(minimized);
}
#[inline]
pub fn is_minimized(&self) -> Option<bool> {
self.window.is_minimized()
}
#[inline]
pub fn set_maximized(&self, maximized: bool) {
self.window.set_maximized(maximized)
}
#[inline]
pub fn is_maximized(&self) -> bool {
self.window.is_maximized()
}
#[inline]
pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
self.window.set_fullscreen(fullscreen.map(|f| f.into()))
}
#[inline]
pub fn fullscreen(&self) -> Option<Fullscreen> {
self.window.fullscreen().map(|f| f.into())
}
#[inline]
pub fn set_decorations(&self, decorations: bool) {
self.window.set_decorations(decorations)
}
#[inline]
pub fn is_decorated(&self) -> bool {
self.window.is_decorated()
}
pub fn set_window_level(&self, level: WindowLevel) {
self.window.set_window_level(level)
}
#[inline]
pub fn set_window_icon(&self, window_icon: Option<Icon>) {
self.window.set_window_icon(window_icon)
}
#[inline]
pub fn set_ime_position<P: Into<Position>>(&self, position: P) {
self.window.set_ime_position(position.into())
}
#[inline]
pub fn set_ime_allowed(&self, allowed: bool) {
self.window.set_ime_allowed(allowed);
}
#[inline]
pub fn set_ime_purpose(&self, purpose: ImePurpose) {
self.window.set_ime_purpose(purpose);
}
#[inline]
pub fn focus_window(&self) {
self.window.focus_window()
}
#[inline]
pub fn has_focus(&self) -> bool {
self.window.has_focus()
}
#[inline]
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
self.window.request_user_attention(request_type)
}
#[inline]
pub fn set_theme(&self, theme: Option<Theme>) {
self.window.set_theme(theme)
}
#[inline]
pub fn theme(&self) -> Option<Theme> {
self.window.theme()
}
pub fn set_content_protected(&self, _protected: bool) {
#[cfg(any(macos_platform, windows_platform))]
self.window.set_content_protected(_protected);
}
#[inline]
pub fn title(&self) -> String {
self.window.title()
}
}
impl Window {
#[inline]
pub fn set_cursor_icon(&self, cursor: CursorIcon) {
self.window.set_cursor_icon(cursor);
}
#[inline]
pub fn set_cursor_position<P: Into<Position>>(&self, position: P) -> Result<(), ExternalError> {
self.window.set_cursor_position(position.into())
}
#[inline]
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
self.window.set_cursor_grab(mode)
}
#[inline]
pub fn set_cursor_visible(&self, visible: bool) {
self.window.set_cursor_visible(visible)
}
#[inline]
pub fn drag_window(&self) -> Result<(), ExternalError> {
self.window.drag_window()
}
#[inline]
pub fn drag_resize_window(&self, direction: ResizeDirection) -> Result<(), ExternalError> {
self.window.drag_resize_window(direction)
}
#[inline]
pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
self.window.set_cursor_hittest(hittest)
}
}
impl Window {
#[inline]
pub fn current_monitor(&self) -> Option<MonitorHandle> {
self.window
.current_monitor()
.map(|inner| MonitorHandle { inner })
}
#[inline]
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
self.window
.available_monitors()
.into_iter()
.map(|inner| MonitorHandle { inner })
}
#[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
self.window
.primary_monitor()
.map(|inner| MonitorHandle { inner })
}
}
unsafe impl HasRawWindowHandle for Window {
fn raw_window_handle(&self) -> RawWindowHandle {
self.window.raw_window_handle()
}
}
unsafe impl HasRawDisplayHandle for Window {
fn raw_display_handle(&self) -> RawDisplayHandle {
self.window.raw_display_handle()
}
}
#[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)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum CursorIcon {
Default,
Crosshair,
Hand,
Arrow,
Move,
Text,
Wait,
Help,
Progress,
NotAllowed,
ContextMenu,
Cell,
VerticalText,
Alias,
Copy,
NoDrop,
Grab,
Grabbing,
AllScroll,
ZoomIn,
ZoomOut,
EResize,
NResize,
NeResize,
NwResize,
SResize,
SeResize,
SwResize,
WResize,
EwResize,
NsResize,
NeswResize,
NwseResize,
ColResize,
RowResize,
}
impl Default for CursorIcon {
fn default() -> Self {
CursorIcon::Default
}
}
#[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, PartialEq, Eq)]
pub enum UserAttentionType {
Critical,
Informational,
}
impl Default for UserAttentionType {
fn default() -> Self {
UserAttentionType::Informational
}
}
bitflags! {
pub struct WindowButtons: u32 {
const CLOSE = 1 << 0;
const MINIMIZE = 1 << 1;
const MAXIMIZE = 1 << 2;
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum WindowLevel {
AlwaysOnBottom,
Normal,
AlwaysOnTop,
}
impl Default for WindowLevel {
fn default() -> Self {
Self::Normal
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[non_exhaustive]
pub enum ImePurpose {
Normal,
Password,
Terminal,
}
impl Default for ImePurpose {
fn default() -> Self {
Self::Normal
}
}