2020-01-05 11:02:41 -05:00
//! Winit is a cross-platform window creation and event loop management library.
2014-08-02 20:49:48 +02:00
//!
2020-01-05 11:02:41 -05:00
//! # Building windows
2014-09-04 11:38:33 +02:00
//!
2024-01-31 17:29:59 +04:00
//! Before you can create a [`Window`], you first need to build an [`EventLoop`]. This is done with
//! the [`EventLoop::new()`] function.
2014-09-04 11:38:33 +02:00
//!
2017-01-28 15:33:54 +01:00
//! ```no_run
2019-02-05 10:30:33 -05:00
//! use winit::event_loop::EventLoop;
2024-11-12 14:52:48 +01:00
//!
//! # // Intentionally use `fn main` for clarity
//! fn main() {
//! let event_loop = EventLoop::new().unwrap();
//! // ...
//! }
2017-01-28 15:33:54 +01:00
//! ```
//!
2024-01-31 17:29:59 +04:00
//! Then you create a [`Window`] with [`create_window`].
2014-10-04 19:17:02 +02:00
//!
2019-02-05 10:30:33 -05:00
//! # Event handling
2014-10-04 19:17:02 +02:00
//!
2019-06-24 17:30:06 -04:00
//! Once a [`Window`] has been created, it will generate different *events*. A [`Window`] object can
2020-01-05 11:02:41 -05:00
//! generate [`WindowEvent`]s when certain input events occur, such as a cursor moving over the
//! window or a key getting pressed while the window is focused. Devices can generate
//! [`DeviceEvent`]s, which contain unfiltered event data that isn't specific to a certain window.
//! Some user activity, like mouse movement, can generate both a [`WindowEvent`] *and* a
2024-06-24 13:04:55 +03:00
//! [`DeviceEvent`].
2020-01-05 11:02:41 -05:00
//!
2025-03-17 10:56:00 +01:00
//! You can retrieve events by calling [`EventLoop::run_app()`]. This function will dispatch events
//! for every [`Window`] that was created with that particular [`EventLoop`].
2017-01-28 15:33:54 +01:00
//!
2020-01-05 11:02:41 -05:00
//! Winit no longer uses a `EventLoop::poll_events() -> impl Iterator<Event>`-based event loop
2024-07-10 16:17:39 +02:00
//! model, since that can't be implemented properly on some platforms (e.g Web, iOS) and works
2020-11-12 20:49:44 +01:00
//! poorly on most other platforms. However, this model can be re-implemented to an extent with
2023-10-25 17:42:51 +02:00
#![ cfg_attr(
any ( windows_platform , macos_platform , android_platform , x11_platform , wayland_platform ) ,
2024-02-23 14:37:21 +04:00
doc = " [`EventLoopExtPumpEvents::pump_app_events()`][platform::pump_events::EventLoopExtPumpEvents::pump_app_events()] "
2023-10-25 17:42:51 +02:00
) ]
#![ cfg_attr(
not ( any ( windows_platform , macos_platform , android_platform , x11_platform , wayland_platform ) ) ,
2024-02-23 14:37:21 +04:00
doc = " `EventLoopExtPumpEvents::pump_app_events()` "
2023-10-25 17:42:51 +02:00
) ]
//! [^1]. See that method's documentation for more reasons about why
2023-12-03 18:39:08 +01:00
//! it's discouraged beyond compatibility reasons.
2017-01-28 15:33:54 +01:00
//!
//!
//! ```no_run
2024-02-23 14:37:21 +04:00
//! use winit::application::ApplicationHandler;
//! use winit::event::WindowEvent;
//! use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
2024-08-23 23:40:27 +03:00
//! use winit::window::{Window, WindowId, WindowAttributes};
2024-02-23 14:37:21 +04:00
//!
//! #[derive(Default)]
//! struct App {
2024-08-23 23:40:27 +03:00
//! window: Option<Box<dyn Window>>,
2024-02-23 14:37:21 +04:00
//! }
//!
//! impl ApplicationHandler for App {
2024-08-06 21:02:53 +03:00
//! fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
2025-03-17 10:56:00 +01:00
//! // The event loop has launched, and we can initialize our UI state.
//!
//! // Create a simple window with default attributes.
2024-08-23 23:40:27 +03:00
//! self.window = Some(event_loop.create_window(WindowAttributes::default()).unwrap());
2024-02-23 14:37:21 +04:00
//! }
//!
2025-03-17 10:56:00 +01:00
//! fn window_event(
//! &mut self,
//! event_loop: &dyn ActiveEventLoop,
//! id: WindowId,
//! event: WindowEvent,
//! ) {
//! // Called by `EventLoop::run_app` when a new event happens on the window.
2024-02-23 14:37:21 +04:00
//! match event {
//! WindowEvent::CloseRequested => {
//! println!("The close button was pressed; stopping");
//! event_loop.exit();
//! },
//! WindowEvent::RedrawRequested => {
//! // Redraw the application.
//! //
//! // It's preferable for applications that do not render continuously to render in
//! // this event rather than in AboutToWait, since rendering in here allows
//! // the program to gracefully handle redraws requested by the OS.
//!
//! // Draw.
//!
//! // Queue a RedrawRequested event.
//! //
//! // You only need to call this if you've determined that you need to redraw in
//! // applications which do not always need to. Applications that redraw continuously
//! // can render here instead.
//! self.window.as_ref().unwrap().request_redraw();
2025-03-17 10:56:00 +01:00
//! },
2024-02-23 14:37:21 +04:00
//! _ => (),
//! }
//! }
//! }
2019-06-22 13:26:06 -04:00
//!
2024-11-12 14:52:48 +01:00
//! # // Intentionally use `fn main` for clarity
2025-03-17 10:56:00 +01:00
//! fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Create a new event loop.
//! let event_loop = EventLoop::new()?;
//!
//! // Configure settings before launching.
2017-01-28 15:33:54 +01:00
//!
2024-11-12 14:52:48 +01:00
//! // ControlFlow::Poll continuously runs the event loop, even if the OS hasn't
//! // dispatched any events. This is ideal for games and similar applications.
//! event_loop.set_control_flow(ControlFlow::Poll);
2023-10-10 22:46:08 +02:00
//!
2024-11-12 14:52:48 +01:00
//! // ControlFlow::Wait pauses the event loop if no events are available to process.
//! // This is ideal for non-game applications that only update in response to user
//! // input, and uses significantly less power/CPU time than ControlFlow::Poll.
//! event_loop.set_control_flow(ControlFlow::Wait);
2023-10-10 22:46:08 +02:00
//!
2025-03-17 10:56:00 +01:00
//! // Launch and begin running the event loop.
//! event_loop.run_app(App::default())?;
//!
//! Ok(())
2024-11-12 14:52:48 +01:00
//! }
2017-01-28 15:33:54 +01:00
//! ```
//!
2023-10-25 17:42:51 +02:00
//! [`WindowEvent`] has a [`WindowId`] member. In multi-window environments, it should be
//! compared to the value returned by [`Window::id()`] to determine which [`Window`]
2020-01-05 11:02:41 -05:00
//! dispatched the event.
2014-10-04 19:17:02 +02:00
//!
2016-11-03 09:49:19 +01:00
//! # Drawing on the window
//!
2023-12-03 18:39:08 +01:00
//! Winit doesn't directly provide any methods for drawing on a [`Window`]. However, it allows you
2022-07-21 22:22:36 +03:00
//! to retrieve the raw handle of the window and display (see the [`platform`] module and/or the
//! [`raw_window_handle`] and [`raw_display_handle`] methods), which in turn allows
2023-10-25 17:42:51 +02:00
//! you to create an OpenGL/Vulkan/DirectX/Metal/etc. context that can be used to render graphics.
2019-02-05 10:30:33 -05:00
//!
2020-04-20 00:04:30 -04:00
//! Note that many platforms will display garbage data in the window's client area if the
//! application doesn't render anything to the window by the time the desktop compositor is ready to
//! display the window to the user. If you notice this happening, you should create the window with
2024-03-16 10:22:29 +01:00
//! [`visible` set to `false`][crate::window::WindowAttributes::with_visible] and explicitly make
2020-04-20 00:04:30 -04:00
//! the window visible only once you're ready to render into it.
//!
2024-11-21 17:37:03 +01:00
//! There is another important concept you need to know about when drawing: the "safe area". This
//! can be accessed with [`Window::safe_area`], and describes a rectangle in the surface that is not
//! obscured by notches, the status bar, and so on. You should be drawing your background and
//! non-important content on the entire surface, but restrict important content (such as
//! interactable UIs, text, etc.) to only being drawn inside the safe area.
//!
//! [`Window::safe_area`]: crate::window::Window::safe_area
//!
//! # Coordinate systems
//!
//! Windowing systems use many different coordinate systems, and this is reflected in Winit as well;
//! there are "desktop coordinates", which is the coordinates of a window or monitor relative to the
//! desktop at large, "window coordinates" which is the coordinates of the surface, relative to the
//! window, and finally "surface coordinates", which is the coordinates relative to the drawn
//! surface. All of these coordinates are relative to the top-left corner of their respective
//! origin.
//!
//! Most of the functionality in Winit works with surface coordinates, so usually you only need to
//! concern yourself with those. In case you need to convert to some other coordinate system, Winit
//! provides [`Window::surface_position`] and [`Window::surface_size`] to describe the surface's
//! location in window coordinates, and Winit provides [`Window::outer_position`] and
//! [`Window::outer_size`] to describe the window's location in desktop coordinates. Using these
//! methods, you should be able to convert a position in one coordinate system to another.
//!
//! An overview of how these four methods fit together can be seen in the image below:
#![ doc = concat!( " \n \n " , include_str!( " ../docs/res/coordinate-systems-desktop.svg " ), " \n \n " ) ] // Rustfmt removes \n, adding them like this works around that.
//! On mobile, the situation is usually a bit different; because of the smaller screen space,
//! windows usually fill the whole screen at a time, and as such there is _rarely_ a difference
//! between these three coordinate systems, although you should still strive to handle this, as
//! they're still relevant in more niche area such as Mac Catalyst, or multi-tasking on tablets.
//!
//! This is illustrated in the image below, along with the safe area since it's often relevant on
//! mobile.
#![ doc = concat!( " \n \n " , include_str!( " ../docs/res/coordinate-systems-mobile.svg " ), " \n \n " ) ] // Rustfmt removes \n, adding them like this works around that.
//! [`Window::surface_position`]: crate::window::Window::surface_position
//! [`Window::surface_size`]: crate::window::Window::surface_size
//! [`Window::outer_position`]: crate::window::Window::outer_position
//! [`Window::outer_size`]: crate::window::Window::outer_size
//!
2024-02-26 14:52:00 +01:00
//! # UI scaling
//!
//! UI scaling is important, go read the docs for the [`dpi`] crate for an
//! introduction.
//!
//! All of Winit's functions return physical types, but can take either logical or physical
//! coordinates as input, allowing you to use the most convenient coordinate system for your
//! particular application.
//!
//! Winit will dispatch a [`ScaleFactorChanged`] event whenever a window's scale factor has changed.
//! This can happen if the user drags their window from a standard-resolution monitor to a high-DPI
//! monitor or if the user changes their DPI settings. This allows you to rescale your application's
//! UI elements and adjust how the platform changes the window's size to reflect the new scale
//! factor. If a window hasn't received a [`ScaleFactorChanged`] event, its scale factor
//! can be found by calling [`window.scale_factor()`].
//!
//! [`ScaleFactorChanged`]: event::WindowEvent::ScaleFactorChanged
//! [`window.scale_factor()`]: window::Window::scale_factor
//!
2024-02-23 15:35:18 +01:00
//! # Cargo Features
//!
//! Winit provides the following Cargo features:
//!
//! * `x11` (enabled by default): On Unix platforms, enables the X11 backend.
//! * `wayland` (enabled by default): On Unix platforms, enables the Wayland backend.
//! * `rwh_06`: Implement `raw-window-handle v0.6` traits.
//! * `serde`: Enables serialization/deserialization of certain types with [Serde](https://crates.io/crates/serde).
//! * `mint`: Enables mint (math interoperability standard types) conversions.
//!
//! See the [`platform`] module for documentation on platform-specific cargo
//! features.
//!
2024-08-23 08:34:58 -07:00
//! # Platform/Architecture Support
//!
//! Platform support on `winit` has two tiers: Tier 1 and Tier 2.
//!
//! - Tier 1 is **guaranteed to work**. Targets in this tier are actively tested both in CI and by
//! maintainers.
//! - Tier 2 is **guaranteed to build**. Code compilation is tested in CI, but deeper testing is not
//! done.
//!
//! Please open an issue if you would like to add a Tier 2 target, or if you would
//! like a Tier 2 target moved to Tier 1.
//!
//! ## Tier 1 Targets
//!
//! |Target Name |Target Triple |APIs |
//! |-------------------------------|------------------------------------|---------------|
//! |32-Bit x86 Windows with MSVC |`i686-pc-windows-msvc` |Win32 |
//! |64-Bit x86 Windows with MSVC |`x86_64-pc-windows-msvc` |Win32 |
//! |32-Bit x86 Windows with glibc |`i686-pc-windows-gnu` |Win32 |
//! |64-Bit x86 Windows with glibc |`x86_64-pc-windows-gnu` |Win32 |
//! |32-Bit x86 Linux with glibc |`i686-unknown-linux-gnu` |X11, Wayland |
//! |64-Bit x86 Linux with glibc |`x86_64-unknown-linux-gnu` |X11, Wayland |
//! |64-Bit ARM Android |`aarch64-linux-android` |Android |
//! |64-Bit x86 Redox OS |`x86_64-unknown-redox` |Orbital |
//! |32-Bit x86 Redox OS |`i686-unknown-redox` |Orbital |
//! |64-Bit ARM Redox OS |`aarch64-unknown-redox` |Orbital |
//! |64-bit x64 macOS |`x86_64-apple-darwin` |AppKit |
//! |64-bit ARM macOS |`aarch64-apple-darwin` |AppKit |
//! |32-bit Wasm Web browser |`wasm32-unknown-unknown` |`wasm-bindgen` |
//!
//! ## Tier 2 Targets
//!
//! |Target Name |Target Triple |APIs |
//! |------------------------------------|------------------------------------|---------------|
//! |64-Bit ARM Windows with MSVC |`aarch64-pc-windows-msvc` |Win32 |
//! |32-Bit x86 Windows 7 with MSVC |`i686-win7-windows-msvc` |Win32 |
//! |64-Bit x86 Windows 7 with MSVC |`x86_64-win7-windows-msvc` |Win32 |
//! |64-bit x86 Linux with Musl |`x86_64-unknown-linux-musl` |X11, Wayland |
//! |64-bit x86 Linux with 32-bit glibc |`x86_64-unknown-linux-gnux32` |X11, Wayland |
//! |64-bit x86 Android |`x86_64-linux-android` |Android |
//! |64-bit x64 iOS |`x86_64-apple-ios` |UIKit |
//! |64-bit ARM iOS |`aarch64-apple-ios` |UIKit |
//! |64-bit ARM Mac Catalyst |`aarch64-apple-ios-macabi` |UIKit |
//! |32-bit x86 Android |`i686-linux-android` |Android |
//! |64-bit x86 FreeBSD |`x86_64-unknown-freebsd` |X11, Wayland |
//! |64-bit x86 NetBSD |`x86_64-unknown-netbsd` |X11 |
//! |32-bit x86 Linux with Musl |`i686-unknown-linux-musl` |X11, Wayland |
//! |64-bit RISC-V Linux with glibc |`riscv64gc-unknown-linux-gnu` |X11, Wayland |
//! |64-bit ARM Linux with glibc |`aarch64-unknown-linux-gnu` |X11, Wayland |
//! |64-bit ARM Linux with Musl |`aarch64-unknown-linux-musl` |X11, Wayland |
//! |64-bit PowerPC Linux with glibc |`powerpc64le-unknown-linux-gnu` |X11, Wayland |
//! |32-Bit ARM Linux with glibc |`armv5te-unknown-linux-gnueabi` |X11, Wayland |
//! |64-Bit Linux on IBM Supercomputers |`s390x-unknown-linux-gnu` |X11, Wayland |
//! |32-bit ARM Android |`arm-linux-androideabi` |Android |
//! |64-bit SPARC Linux with glibc |`sparc64-unknown-linux-gnu` |X11, Wayland |
//!
2019-11-11 18:05:59 -05:00
//! [`EventLoop`]: event_loop::EventLoop
//! [`EventLoop::new()`]: event_loop::EventLoop::new
2024-02-23 14:37:21 +04:00
//! [`EventLoop::run_app()`]: event_loop::EventLoop::run_app
2024-01-31 17:29:59 +04:00
//! [`exit()`]: event_loop::ActiveEventLoop::exit
2019-11-11 18:05:59 -05:00
//! [`Window`]: window::Window
2020-01-05 11:02:41 -05:00
//! [`WindowId`]: window::WindowId
2024-01-31 17:29:59 +04:00
//! [`WindowAttributes`]: window::WindowAttributes
//! [`create_window`]: event_loop::ActiveEventLoop::create_window
2023-10-25 17:42:51 +02:00
//! [`Window::id()`]: window::Window::id
2019-11-11 18:05:59 -05:00
//! [`WindowEvent`]: event::WindowEvent
//! [`DeviceEvent`]: event::DeviceEvent
2020-04-19 11:58:58 -07:00
//! [`raw_window_handle`]: ./window/struct.Window.html#method.raw_window_handle
2022-07-21 22:22:36 +03:00
//! [`raw_display_handle`]: ./window/struct.Window.html#method.raw_display_handle
2024-02-23 14:37:21 +04:00
//! [^1]: `EventLoopExtPumpEvents::pump_app_events()` is only available on Windows, macOS, Android, X11 and Wayland.
2014-08-02 20:49:48 +02:00
2019-06-18 02:27:00 +08:00
#![ deny(rust_2018_idioms) ]
2021-08-30 19:40:02 +02:00
#![ deny(rustdoc::broken_intra_doc_links) ]
2022-06-10 13:43:33 +03:00
#![ deny(clippy::all) ]
2023-09-30 21:43:41 +02:00
#![ deny(unsafe_op_in_unsafe_fn) ]
2024-02-28 19:50:05 +02:00
#![ cfg_attr(clippy, deny(warnings)) ]
2022-10-24 17:02:52 -05:00
// Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly
// doc
2024-01-04 12:54:35 +01:00
#![ cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg_hide), doc(cfg_hide(doc, docsrs))) ]
2022-06-10 13:43:33 +03:00
#![ allow(clippy::missing_safety_doc) ]
2024-11-22 13:14:11 -08:00
#![ warn(clippy::uninlined_format_args) ]
2025-04-06 15:41:46 +09:00
// TODO: wasm-binding needs to be updated for that to be resolved, for now just silence it.
#![ cfg_attr(web_platform, allow(unknown_lints, wasm_c_abi)) ]
2019-06-18 02:27:00 +08:00
2024-02-26 14:52:00 +01:00
// Re-export DPI types so that users don't have to put it in Cargo.toml.
#[ doc(inline) ]
pub use dpi ;
2023-10-14 19:07:39 -07:00
pub use rwh_06 as raw_window_handle ;
2024-02-23 14:37:21 +04:00
pub mod application ;
2024-02-16 17:28:13 +01:00
#[ cfg(any(doc, doctest, test)) ]
pub mod changelog ;
2019-05-29 21:29:54 -04:00
#[ macro_use ]
pub mod error ;
2023-12-16 22:02:17 +02:00
mod cursor ;
2019-02-05 10:30:33 -05:00
pub mod event ;
pub mod event_loop ;
2025-03-23 20:02:07 +03:00
pub mod icon ;
2023-05-28 20:02:59 +02:00
pub mod keyboard ;
2019-06-25 03:15:34 +02:00
pub mod monitor ;
2019-02-05 10:30:33 -05:00
mod platform_impl ;
2025-05-01 19:25:15 +09:00
use winit_core ::as_any as utils ;
2019-02-05 10:30:33 -05:00
pub mod window ;
2015-09-21 09:15:53 +02:00
2019-02-05 10:30:33 -05:00
pub mod platform ;