winit/
lib.rs

1//! Winit is a cross-platform window creation and event loop management library.
2//!
3//! # Building windows
4//!
5//! Before you can create a [`Window`], you first need to build an [`EventLoop`]. This is done with
6//! the [`EventLoop::new()`] function.
7//!
8//! ```no_run
9//! use winit::event_loop::EventLoop;
10//!
11//! # // Intentionally use `fn main` for clarity
12//! fn main() {
13//!     let event_loop = EventLoop::new().unwrap();
14//!     // ...
15//! }
16//! ```
17//!
18//! Then you create a [`Window`] with [`create_window`].
19//!
20//! # Event handling
21//!
22//! Once a [`Window`] has been created, it will generate different *events*. A [`Window`] object can
23//! generate [`WindowEvent`]s when certain input events occur, such as a cursor moving over the
24//! window or a key getting pressed while the window is focused. Devices can generate
25//! [`DeviceEvent`]s, which contain unfiltered event data that isn't specific to a certain window.
26//! Some user activity, like mouse movement, can generate both a [`WindowEvent`] *and* a
27//! [`DeviceEvent`]. You can also create and handle your own custom [`Event::UserEvent`]s, if
28//! desired.
29//!
30//! You can retrieve events by calling [`EventLoop::run_app()`]. This function will
31//! dispatch events for every [`Window`] that was created with that particular [`EventLoop`], and
32//! will run until [`exit()`] is used, at which point [`Event::LoopExiting`].
33//!
34//! Winit no longer uses a `EventLoop::poll_events() -> impl Iterator<Event>`-based event loop
35//! model, since that can't be implemented properly on some platforms (e.g web, iOS) and works
36//! poorly on most other platforms. However, this model can be re-implemented to an extent with
37#![cfg_attr(
38    any(windows_platform, macos_platform, android_platform, x11_platform, wayland_platform),
39    doc = "[`EventLoopExtPumpEvents::pump_app_events()`][platform::pump_events::EventLoopExtPumpEvents::pump_app_events()]"
40)]
41#![cfg_attr(
42    not(any(windows_platform, macos_platform, android_platform, x11_platform, wayland_platform)),
43    doc = "`EventLoopExtPumpEvents::pump_app_events()`"
44)]
45//! [^1]. See that method's documentation for more reasons about why
46//! it's discouraged beyond compatibility reasons.
47//!
48//!
49//! ```no_run
50//! use winit::application::ApplicationHandler;
51//! use winit::event::WindowEvent;
52//! use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
53//! use winit::window::{Window, WindowId};
54//!
55//! #[derive(Default)]
56//! struct App {
57//!     window: Option<Window>,
58//! }
59//!
60//! impl ApplicationHandler for App {
61//!     fn resumed(&mut self, event_loop: &ActiveEventLoop) {
62//!         self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap());
63//!     }
64//!
65//!     fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) {
66//!         match event {
67//!             WindowEvent::CloseRequested => {
68//!                 println!("The close button was pressed; stopping");
69//!                 event_loop.exit();
70//!             },
71//!             WindowEvent::RedrawRequested => {
72//!                 // Redraw the application.
73//!                 //
74//!                 // It's preferable for applications that do not render continuously to render in
75//!                 // this event rather than in AboutToWait, since rendering in here allows
76//!                 // the program to gracefully handle redraws requested by the OS.
77//!
78//!                 // Draw.
79//!
80//!                 // Queue a RedrawRequested event.
81//!                 //
82//!                 // You only need to call this if you've determined that you need to redraw in
83//!                 // applications which do not always need to. Applications that redraw continuously
84//!                 // can render here instead.
85//!                 self.window.as_ref().unwrap().request_redraw();
86//!             }
87//!             _ => (),
88//!         }
89//!     }
90//! }
91//!
92//! # // Intentionally use `fn main` for clarity
93//! fn main() {
94//!     let event_loop = EventLoop::new().unwrap();
95//!
96//!     // ControlFlow::Poll continuously runs the event loop, even if the OS hasn't
97//!     // dispatched any events. This is ideal for games and similar applications.
98//!     event_loop.set_control_flow(ControlFlow::Poll);
99//!
100//!     // ControlFlow::Wait pauses the event loop if no events are available to process.
101//!     // This is ideal for non-game applications that only update in response to user
102//!     // input, and uses significantly less power/CPU time than ControlFlow::Poll.
103//!     event_loop.set_control_flow(ControlFlow::Wait);
104//!
105//!     let mut app = App::default();
106//!     event_loop.run_app(&mut app);
107//! }
108//! ```
109//!
110//! [`WindowEvent`] has a [`WindowId`] member. In multi-window environments, it should be
111//! compared to the value returned by [`Window::id()`] to determine which [`Window`]
112//! dispatched the event.
113//!
114//! # Drawing on the window
115//!
116//! Winit doesn't directly provide any methods for drawing on a [`Window`]. However, it allows you
117//! to retrieve the raw handle of the window and display (see the [`platform`] module and/or the
118//! [`raw_window_handle`] and [`raw_display_handle`] methods), which in turn allows
119//! you to create an OpenGL/Vulkan/DirectX/Metal/etc. context that can be used to render graphics.
120//!
121//! Note that many platforms will display garbage data in the window's client area if the
122//! application doesn't render anything to the window by the time the desktop compositor is ready to
123//! display the window to the user. If you notice this happening, you should create the window with
124//! [`visible` set to `false`][crate::window::WindowAttributes::with_visible] and explicitly make
125//! the window visible only once you're ready to render into it.
126//!
127//! # UI scaling
128//!
129//! UI scaling is important, go read the docs for the [`dpi`] crate for an
130//! introduction.
131//!
132//! All of Winit's functions return physical types, but can take either logical or physical
133//! coordinates as input, allowing you to use the most convenient coordinate system for your
134//! particular application.
135//!
136//! Winit will dispatch a [`ScaleFactorChanged`] event whenever a window's scale factor has changed.
137//! This can happen if the user drags their window from a standard-resolution monitor to a high-DPI
138//! monitor or if the user changes their DPI settings. This allows you to rescale your application's
139//! UI elements and adjust how the platform changes the window's size to reflect the new scale
140//! factor. If a window hasn't received a [`ScaleFactorChanged`] event, its scale factor
141//! can be found by calling [`window.scale_factor()`].
142//!
143//! [`ScaleFactorChanged`]: event::WindowEvent::ScaleFactorChanged
144//! [`window.scale_factor()`]: window::Window::scale_factor
145//!
146//! # Cargo Features
147//!
148//! Winit provides the following Cargo features:
149//!
150//! * `x11` (enabled by default): On Unix platforms, enables the X11 backend.
151//! * `wayland` (enabled by default): On Unix platforms, enables the Wayland backend.
152//! * `rwh_04`: Implement `raw-window-handle v0.4` traits.
153//! * `rwh_05`: Implement `raw-window-handle v0.5` traits.
154//! * `rwh_06`: Implement `raw-window-handle v0.6` traits.
155//! * `serde`: Enables serialization/deserialization of certain types with [Serde](https://crates.io/crates/serde).
156//! * `mint`: Enables mint (math interoperability standard types) conversions.
157//!
158//! See the [`platform`] module for documentation on platform-specific cargo
159//! features.
160//!
161//! [`EventLoop`]: event_loop::EventLoop
162//! [`EventLoop::new()`]: event_loop::EventLoop::new
163//! [`EventLoop::run_app()`]: event_loop::EventLoop::run_app
164//! [`exit()`]: event_loop::ActiveEventLoop::exit
165//! [`Window`]: window::Window
166//! [`WindowId`]: window::WindowId
167//! [`WindowAttributes`]: window::WindowAttributes
168//! [window_new]: window::Window::new
169//! [`create_window`]: event_loop::ActiveEventLoop::create_window
170//! [`Window::id()`]: window::Window::id
171//! [`WindowEvent`]: event::WindowEvent
172//! [`DeviceEvent`]: event::DeviceEvent
173//! [`Event::UserEvent`]: event::Event::UserEvent
174//! [`Event::LoopExiting`]: event::Event::LoopExiting
175//! [`raw_window_handle`]: ./window/struct.Window.html#method.raw_window_handle
176//! [`raw_display_handle`]: ./window/struct.Window.html#method.raw_display_handle
177//! [^1]: `EventLoopExtPumpEvents::pump_app_events()` is only available on Windows, macOS, Android, X11 and Wayland.
178
179#![deny(rust_2018_idioms)]
180#![deny(rustdoc::broken_intra_doc_links)]
181#![deny(clippy::all)]
182#![deny(unsafe_op_in_unsafe_fn)]
183#![cfg_attr(clippy, deny(warnings))]
184// Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly
185// doc
186#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg_hide), doc(cfg_hide(doc, docsrs)))]
187#![allow(clippy::missing_safety_doc)]
188
189#[cfg(feature = "rwh_04")]
190pub use rwh_04 as raw_window_handle_04;
191#[cfg(feature = "rwh_05")]
192pub use rwh_05 as raw_window_handle_05;
193#[cfg(feature = "rwh_06")]
194pub use rwh_06 as raw_window_handle;
195
196// Re-export DPI types so that users don't have to put it in Cargo.toml.
197#[doc(inline)]
198pub use dpi;
199
200pub mod application;
201#[cfg(any(doc, doctest, test))]
202pub mod changelog;
203#[macro_use]
204pub mod error;
205mod cursor;
206pub mod event;
207pub mod event_loop;
208mod icon;
209pub mod keyboard;
210pub mod monitor;
211mod platform_impl;
212mod utils;
213pub mod window;
214
215pub mod platform;