rio_window/application.rs
1//! End user application handling.
2
3use crate::event::{DeviceEvent, DeviceId, StartCause, WindowEvent};
4use crate::event::{KeyEvent, Modifiers};
5use crate::event_loop::ActiveEventLoop;
6use crate::window::WindowId;
7
8/// The handler of the application events.
9pub trait ApplicationHandler<T: 'static = ()> {
10 /// Emitted when new events arrive from the OS to be processed.
11 ///
12 /// This is a useful place to put code that should be done before you start processing
13 /// events, such as updating frame timing information for benchmarking or checking the
14 /// [`StartCause`] to see if a timer set by
15 /// [`ControlFlow::WaitUntil`][crate::event_loop::ControlFlow::WaitUntil] has elapsed.
16 fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
17 let _ = (event_loop, cause);
18 }
19
20 /// Emitted when the application has been resumed.
21 ///
22 /// For consistency, all platforms emit a `Resumed` event even if they don't themselves have a
23 /// formal suspend/resume lifecycle. For systems without a formal suspend/resume lifecycle
24 /// the `Resumed` event is always emitted after the
25 /// [`NewEvents(StartCause::Init)`][StartCause::Init] event.
26 ///
27 /// # Portability
28 ///
29 /// It's recommended that applications should only initialize their graphics context and create
30 /// a window after they have received their first `Resumed` event. Some systems
31 /// (specifically Android) won't allow applications to create a render surface until they are
32 /// resumed.
33 ///
34 /// Considering that the implementation of [`Suspended`] and `Resumed` events may be internally
35 /// driven by multiple platform-specific events, and that there may be subtle differences across
36 /// platforms with how these internal events are delivered, it's recommended that applications
37 /// be able to gracefully handle redundant (i.e. back-to-back) [`Suspended`] or `Resumed`
38 /// events.
39 ///
40 /// Also see [`Suspended`] notes.
41 ///
42 /// ## Android
43 ///
44 /// On Android, the `Resumed` event is sent when a new [`SurfaceView`] has been created. This is
45 /// expected to closely correlate with the [`onResume`] lifecycle event but there may
46 /// technically be a discrepancy.
47 ///
48 /// [`onResume`]: https://developer.android.com/reference/android/app/Activity#onResume()
49 ///
50 /// Applications that need to run on Android must wait until they have been `Resumed`
51 /// before they will be able to create a render surface (such as an `EGLSurface`,
52 /// [`VkSurfaceKHR`] or [`wgpu::Surface`]) which depend on having a
53 /// [`SurfaceView`]. Applications must also assume that if they are [`Suspended`], then their
54 /// render surfaces are invalid and should be dropped.
55 ///
56 /// Also see [`Suspended`] notes.
57 ///
58 /// [`SurfaceView`]: https://developer.android.com/reference/android/view/SurfaceView
59 /// [Activity lifecycle]: https://developer.android.com/guide/components/activities/activity-lifecycle
60 /// [`VkSurfaceKHR`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkSurfaceKHR.html
61 /// [`wgpu::Surface`]: https://docs.rs/wgpu/latest/wgpu/struct.Surface.html
62 ///
63 /// ## iOS
64 ///
65 /// On iOS, the `Resumed` event is emitted in response to an [`applicationDidBecomeActive`]
66 /// callback which means the application is "active" (according to the
67 /// [iOS application lifecycle]).
68 ///
69 /// [`applicationDidBecomeActive`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive
70 /// [iOS application lifecycle]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
71 ///
72 /// ## Web
73 ///
74 /// On Web, the `Resumed` event is emitted in response to a [`pageshow`] event
75 /// with the property [`persisted`] being true, which means that the page is being
76 /// restored from the [`bfcache`] (back/forward cache) - an in-memory cache that
77 /// stores a complete snapshot of a page (including the JavaScript heap) as the
78 /// user is navigating away.
79 ///
80 /// [`pageshow`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
81 /// [`persisted`]: https://developer.mozilla.org/en-US/docs/Web/API/PageTransitionEvent/persisted
82 /// [`bfcache`]: https://web.dev/bfcache/
83 /// [`Suspended`]: Self::suspended
84 fn resumed(&mut self, event_loop: &ActiveEventLoop);
85
86 /// Emitted when an event is sent from [`EventLoopProxy::send_event`].
87 ///
88 /// [`EventLoopProxy::send_event`]: crate::event_loop::EventLoopProxy::send_event
89 fn user_event(&mut self, event_loop: &ActiveEventLoop, event: T) {
90 let _ = (event_loop, event);
91 }
92
93 /// Emitted when the OS sends an event to a winit window.
94 fn window_event(
95 &mut self,
96 event_loop: &ActiveEventLoop,
97 window_id: WindowId,
98 event: WindowEvent,
99 );
100
101 /// Emitted when the OS sends an event to a device.
102 fn device_event(
103 &mut self,
104 event_loop: &ActiveEventLoop,
105 device_id: DeviceId,
106 event: DeviceEvent,
107 ) {
108 let _ = (event_loop, device_id, event);
109 }
110
111 /// Emitted when the event loop is about to block and wait for new events.
112 ///
113 /// Most applications shouldn't need to hook into this event since there is no real relationship
114 /// between how often the event loop needs to wake up and the dispatching of any specific
115 /// events.
116 ///
117 /// High frequency event sources, such as input devices could potentially lead to lots of wake
118 /// ups and also lots of corresponding `AboutToWait` events.
119 ///
120 /// This is not an ideal event to drive application rendering from and instead applications
121 /// should render in response to [`WindowEvent::RedrawRequested`] events.
122 fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
123 let _ = event_loop;
124 }
125
126 /// Emitted when the application has been suspended.
127 ///
128 /// # Portability
129 ///
130 /// Not all platforms support the notion of suspending applications, and there may be no
131 /// technical way to guarantee being able to emit a `Suspended` event if the OS has
132 /// no formal application lifecycle (currently only Android, iOS, and Web do). For this reason,
133 /// Winit does not currently try to emit pseudo `Suspended` events before the application
134 /// quits on platforms without an application lifecycle.
135 ///
136 /// Considering that the implementation of `Suspended` and [`Resumed`] events may be internally
137 /// driven by multiple platform-specific events, and that there may be subtle differences across
138 /// platforms with how these internal events are delivered, it's recommended that applications
139 /// be able to gracefully handle redundant (i.e. back-to-back) `Suspended` or [`Resumed`]
140 /// events.
141 ///
142 /// Also see [`Resumed`] notes.
143 ///
144 /// ## Android
145 ///
146 /// On Android, the `Suspended` event is only sent when the application's associated
147 /// [`SurfaceView`] is destroyed. This is expected to closely correlate with the [`onPause`]
148 /// lifecycle event but there may technically be a discrepancy.
149 ///
150 /// [`onPause`]: https://developer.android.com/reference/android/app/Activity#onPause()
151 ///
152 /// Applications that need to run on Android should assume their [`SurfaceView`] has been
153 /// destroyed, which indirectly invalidates any existing render surfaces that may have been
154 /// created outside of Winit (such as an `EGLSurface`, [`VkSurfaceKHR`] or [`wgpu::Surface`]).
155 ///
156 /// After being `Suspended` on Android applications must drop all render surfaces before
157 /// the event callback completes, which may be re-created when the application is next
158 /// [`Resumed`].
159 ///
160 /// [`SurfaceView`]: https://developer.android.com/reference/android/view/SurfaceView
161 /// [Activity lifecycle]: https://developer.android.com/guide/components/activities/activity-lifecycle
162 /// [`VkSurfaceKHR`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkSurfaceKHR.html
163 /// [`wgpu::Surface`]: https://docs.rs/wgpu/latest/wgpu/struct.Surface.html
164 ///
165 /// ## iOS
166 ///
167 /// On iOS, the `Suspended` event is currently emitted in response to an
168 /// [`applicationWillResignActive`] callback which means that the application is
169 /// about to transition from the active to inactive state (according to the
170 /// [iOS application lifecycle]).
171 ///
172 /// [`applicationWillResignActive`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622950-applicationwillresignactive
173 /// [iOS application lifecycle]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
174 ///
175 /// ## Web
176 ///
177 /// On Web, the `Suspended` event is emitted in response to a [`pagehide`] event
178 /// with the property [`persisted`] being true, which means that the page is being
179 /// put in the [`bfcache`] (back/forward cache) - an in-memory cache that stores a
180 /// complete snapshot of a page (including the JavaScript heap) as the user is
181 /// navigating away.
182 ///
183 /// [`pagehide`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event
184 /// [`persisted`]: https://developer.mozilla.org/en-US/docs/Web/API/PageTransitionEvent/persisted
185 /// [`bfcache`]: https://web.dev/bfcache/
186 /// [`Resumed`]: Self::resumed
187 fn suspended(&mut self, event_loop: &ActiveEventLoop) {
188 let _ = event_loop;
189 }
190
191 /// Emitted when the event loop is being shut down.
192 ///
193 /// This is irreversible - if this method is called, it is guaranteed that the event loop
194 /// will exit right after.
195 fn exiting(&mut self, event_loop: &ActiveEventLoop) {
196 let _ = event_loop;
197 }
198
199 /// Emitted when the application has received a memory warning.
200 ///
201 /// ## Platform-specific
202 ///
203 /// ### Android
204 ///
205 /// On Android, the `MemoryWarning` event is sent when [`onLowMemory`] was called. The
206 /// application must [release memory] or risk being killed.
207 ///
208 /// [`onLowMemory`]: https://developer.android.com/reference/android/app/Application.html#onLowMemory()
209 /// [release memory]: https://developer.android.com/topic/performance/memory#release
210 ///
211 /// ### iOS
212 ///
213 /// On iOS, the `MemoryWarning` event is emitted in response to an
214 /// [`applicationDidReceiveMemoryWarning`] callback. The application must free as much
215 /// memory as possible or risk being terminated, see [how to respond to memory warnings].
216 ///
217 /// [`applicationDidReceiveMemoryWarning`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623063-applicationdidreceivememorywarni
218 /// [how to respond to memory warnings]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle/responding_to_memory_warnings
219 ///
220 /// ### Others
221 ///
222 /// - **macOS / Orbital / Wayland / Web / Windows:** Unsupported.
223 fn memory_warning(&mut self, event_loop: &ActiveEventLoop) {
224 let _ = event_loop;
225 }
226
227 fn open_urls(&mut self, event_loop: &ActiveEventLoop, urls: Vec<String>) {
228 let _ = (event_loop, urls);
229 }
230
231 fn open_config(&mut self, event_loop: &ActiveEventLoop) {
232 let _ = event_loop;
233 }
234
235 fn hook_event(
236 &mut self,
237 event_loop: &ActiveEventLoop,
238 hook: &KeyEvent,
239 modifiers: &Modifiers,
240 ) {
241 let _ = (event_loop, hook, modifiers);
242 }
243}