1 | //! Winit is a cross-platform window creation and event loop management library. |
2 | //! |
3 | //! # Building windows |
4 | //! |
5 | //! Before you can build a [`Window`], you first need to build an [`EventLoop`]. This is done with the |
6 | //! [`EventLoop::new()`] function. |
7 | //! |
8 | //! ```no_run |
9 | //! use winit::event_loop::EventLoop; |
10 | //! let event_loop = EventLoop::new().unwrap(); |
11 | //! ``` |
12 | //! |
13 | //! Once this is done, there are two ways to create a [`Window`]: |
14 | //! |
15 | //! - Calling [`Window::new(&event_loop)`][window_new]. |
16 | //! - Calling [`let builder = WindowBuilder::new()`][window_builder_new] then [`builder.build(&event_loop)`][window_builder_build]. |
17 | //! |
18 | //! The first method is the simplest and will give you default values for everything. The second |
19 | //! method allows you to customize the way your [`Window`] will look and behave by modifying the |
20 | //! fields of the [`WindowBuilder`] object before you create the [`Window`]. |
21 | //! |
22 | //! # Event handling |
23 | //! |
24 | //! Once a [`Window`] has been created, it will generate different *events*. A [`Window`] object can |
25 | //! generate [`WindowEvent`]s when certain input events occur, such as a cursor moving over the |
26 | //! window or a key getting pressed while the window is focused. Devices can generate |
27 | //! [`DeviceEvent`]s, which contain unfiltered event data that isn't specific to a certain window. |
28 | //! Some user activity, like mouse movement, can generate both a [`WindowEvent`] *and* a |
29 | //! [`DeviceEvent`]. You can also create and handle your own custom [`Event::UserEvent`]s, if desired. |
30 | //! |
31 | //! You can retrieve events by calling [`EventLoop::run()`]. This function will |
32 | //! dispatch events for every [`Window`] that was created with that particular [`EventLoop`], and |
33 | //! will run until [`exit()`] is used, at which point [`Event::LoopExiting`]. |
34 | //! |
35 | //! Winit no longer uses a `EventLoop::poll_events() -> impl Iterator<Event>`-based event loop |
36 | //! model, since that can't be implemented properly on some platforms (e.g web, iOS) and works poorly on |
37 | //! most other platforms. However, this model can be re-implemented to an extent with |
38 | #![cfg_attr ( |
39 | any( |
40 | windows_platform, |
41 | macos_platform, |
42 | android_platform, |
43 | x11_platform, |
44 | wayland_platform |
45 | ), |
46 | doc = "[`EventLoopExtPumpEvents::pump_events()`][platform::pump_events::EventLoopExtPumpEvents::pump_events()]" |
47 | )] |
48 | #![cfg_attr ( |
49 | not(any( |
50 | windows_platform, |
51 | macos_platform, |
52 | android_platform, |
53 | x11_platform, |
54 | wayland_platform |
55 | )), |
56 | doc = "`EventLoopExtPumpEvents::pump_events()`" |
57 | )] |
58 | //! [^1]. See that method's documentation for more reasons about why |
59 | //! it's discouraged beyond compatibility reasons. |
60 | //! |
61 | //! |
62 | //! ```no_run |
63 | //! use winit::{ |
64 | //! event::{Event, WindowEvent}, |
65 | //! event_loop::{ControlFlow, EventLoop}, |
66 | //! window::WindowBuilder, |
67 | //! }; |
68 | //! |
69 | //! let event_loop = EventLoop::new().unwrap(); |
70 | //! let window = WindowBuilder::new().build(&event_loop).unwrap(); |
71 | //! |
72 | //! // ControlFlow::Poll continuously runs the event loop, even if the OS hasn't |
73 | //! // dispatched any events. This is ideal for games and similar applications. |
74 | //! event_loop.set_control_flow(ControlFlow::Poll); |
75 | //! |
76 | //! // ControlFlow::Wait pauses the event loop if no events are available to process. |
77 | //! // This is ideal for non-game applications that only update in response to user |
78 | //! // input, and uses significantly less power/CPU time than ControlFlow::Poll. |
79 | //! event_loop.set_control_flow(ControlFlow::Wait); |
80 | //! |
81 | //! event_loop.run(move |event, elwt| { |
82 | //! match event { |
83 | //! Event::WindowEvent { |
84 | //! event: WindowEvent::CloseRequested, |
85 | //! .. |
86 | //! } => { |
87 | //! println!("The close button was pressed; stopping" ); |
88 | //! elwt.exit(); |
89 | //! }, |
90 | //! Event::AboutToWait => { |
91 | //! // Application update code. |
92 | //! |
93 | //! // Queue a RedrawRequested event. |
94 | //! // |
95 | //! // You only need to call this if you've determined that you need to redraw in |
96 | //! // applications which do not always need to. Applications that redraw continuously |
97 | //! // can render here instead. |
98 | //! window.request_redraw(); |
99 | //! }, |
100 | //! Event::WindowEvent { |
101 | //! event: WindowEvent::RedrawRequested, |
102 | //! .. |
103 | //! } => { |
104 | //! // Redraw the application. |
105 | //! // |
106 | //! // It's preferable for applications that do not render continuously to render in |
107 | //! // this event rather than in AboutToWait, since rendering in here allows |
108 | //! // the program to gracefully handle redraws requested by the OS. |
109 | //! }, |
110 | //! _ => () |
111 | //! } |
112 | //! }); |
113 | //! ``` |
114 | //! |
115 | //! [`WindowEvent`] has a [`WindowId`] member. In multi-window environments, it should be |
116 | //! compared to the value returned by [`Window::id()`] to determine which [`Window`] |
117 | //! dispatched the event. |
118 | //! |
119 | //! # Drawing on the window |
120 | //! |
121 | //! Winit doesn't directly provide any methods for drawing on a [`Window`]. However, it allows you to |
122 | //! retrieve the raw handle of the window and display (see the [`platform`] module and/or the |
123 | //! [`raw_window_handle`] and [`raw_display_handle`] methods), which in turn allows |
124 | //! you to create an OpenGL/Vulkan/DirectX/Metal/etc. context that can be used to render graphics. |
125 | //! |
126 | //! Note that many platforms will display garbage data in the window's client area if the |
127 | //! application doesn't render anything to the window by the time the desktop compositor is ready to |
128 | //! display the window to the user. If you notice this happening, you should create the window with |
129 | //! [`visible` set to `false`](crate::window::WindowBuilder::with_visible) and explicitly make the |
130 | //! window visible only once you're ready to render into it. |
131 | //! |
132 | //! [`EventLoop`]: event_loop::EventLoop |
133 | //! [`EventLoop::new()`]: event_loop::EventLoop::new |
134 | //! [`EventLoop::run()`]: event_loop::EventLoop::run |
135 | //! [`exit()`]: event_loop::EventLoopWindowTarget::exit |
136 | //! [`Window`]: window::Window |
137 | //! [`WindowId`]: window::WindowId |
138 | //! [`WindowBuilder`]: window::WindowBuilder |
139 | //! [window_new]: window::Window::new |
140 | //! [window_builder_new]: window::WindowBuilder::new |
141 | //! [window_builder_build]: window::WindowBuilder::build |
142 | //! [`Window::id()`]: window::Window::id |
143 | //! [`WindowEvent`]: event::WindowEvent |
144 | //! [`DeviceEvent`]: event::DeviceEvent |
145 | //! [`Event::UserEvent`]: event::Event::UserEvent |
146 | //! [`Event::LoopExiting`]: event::Event::LoopExiting |
147 | //! [`raw_window_handle`]: ./window/struct.Window.html#method.raw_window_handle |
148 | //! [`raw_display_handle`]: ./window/struct.Window.html#method.raw_display_handle |
149 | //! [^1]: `EventLoopExtPumpEvents::pump_events()` is only available on Windows, macOS, Android, X11 and Wayland. |
150 | |
151 | #![deny (rust_2018_idioms)] |
152 | #![deny (rustdoc::broken_intra_doc_links)] |
153 | #![deny (clippy::all)] |
154 | #![deny (unsafe_op_in_unsafe_fn)] |
155 | #![cfg_attr (feature = "cargo-clippy" , deny(warnings))] |
156 | // Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc |
157 | #![cfg_attr (docsrs, feature(doc_auto_cfg))] |
158 | #![allow (clippy::missing_safety_doc)] |
159 | |
160 | #[cfg (feature = "rwh_06" )] |
161 | pub use rwh_06 as raw_window_handle; |
162 | |
163 | #[allow (unused_imports)] |
164 | #[macro_use ] |
165 | extern crate log; |
166 | #[cfg (feature = "serde" )] |
167 | #[macro_use ] |
168 | extern crate serde; |
169 | #[macro_use ] |
170 | extern crate bitflags; |
171 | |
172 | pub mod dpi; |
173 | #[macro_use ] |
174 | pub mod error; |
175 | pub mod event; |
176 | pub mod event_loop; |
177 | mod icon; |
178 | pub mod keyboard; |
179 | pub mod monitor; |
180 | mod platform_impl; |
181 | pub mod window; |
182 | |
183 | pub mod platform; |
184 | |
185 | /// Wrapper for objects which winit will access on the main thread so they are effectively `Send` |
186 | /// and `Sync`, since they always execute on a single thread. |
187 | /// |
188 | /// # Safety |
189 | /// |
190 | /// Winit can run only one event loop at a time, and the event loop itself is tied to some thread. |
191 | /// The objects could be sent across the threads, but once passed to winit, they execute on the |
192 | /// main thread if the platform demands it. Thus, marking such objects as `Send + Sync` is safe. |
193 | #[doc (hidden)] |
194 | #[derive (Clone, Debug)] |
195 | pub(crate) struct SendSyncWrapper<T>(pub(crate) T); |
196 | |
197 | unsafe impl<T> Send for SendSyncWrapper<T> {} |
198 | unsafe impl<T> Sync for SendSyncWrapper<T> {} |
199 | |