| 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" )] |
| 190 | pub use rwh_04 as raw_window_handle_04; |
| 191 | #[cfg (feature = "rwh_05" )] |
| 192 | pub use rwh_05 as raw_window_handle_05; |
| 193 | #[cfg (feature = "rwh_06" )] |
| 194 | pub 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)] |
| 198 | pub use dpi; |
| 199 | |
| 200 | pub mod application; |
| 201 | #[cfg (any(doc, doctest, test))] |
| 202 | pub mod changelog; |
| 203 | #[macro_use ] |
| 204 | pub mod error; |
| 205 | mod cursor; |
| 206 | pub mod event; |
| 207 | pub mod event_loop; |
| 208 | mod icon; |
| 209 | pub mod keyboard; |
| 210 | pub mod monitor; |
| 211 | mod platform_impl; |
| 212 | mod utils; |
| 213 | pub mod window; |
| 214 | |
| 215 | pub mod platform; |
| 216 | |