Implement ApplicationHandler::can_create|destroy_surfaces() (#3765)

This commit is contained in:
daxpedda 2024-06-30 00:41:57 +02:00 committed by GitHub
parent a0d69c782a
commit 75ce71f05a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 178 additions and 114 deletions

View file

@ -20,7 +20,7 @@ fn main() -> Result<(), impl std::error::Error> {
} }
impl ApplicationHandler for Application { impl ApplicationHandler for Application {
fn resumed(&mut self, event_loop: &ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
let attributes = Window::default_attributes() let attributes = Window::default_attributes()
.with_title("parent window") .with_title("parent window")
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))

View file

@ -67,7 +67,7 @@ impl ApplicationHandler for ControlFlowDemo {
} }
} }
fn resumed(&mut self, event_loop: &ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
let window_attributes = Window::default_attributes().with_title( let window_attributes = Window::default_attributes().with_title(
"Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.", "Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.",
); );

View file

@ -22,7 +22,7 @@ fn main() -> std::process::ExitCode {
} }
impl ApplicationHandler for PumpDemo { impl ApplicationHandler for PumpDemo {
fn resumed(&mut self, event_loop: &ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
let window_attributes = Window::default_attributes().with_title("A fantastic window!"); let window_attributes = Window::default_attributes().with_title("A fantastic window!");
self.window = Some(event_loop.create_window(window_attributes).unwrap()); self.window = Some(event_loop.create_window(window_attributes).unwrap());
} }

View file

@ -28,7 +28,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
} }
fn resumed(&mut self, event_loop: &ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
let window_attributes = Window::default_attributes() let window_attributes = Window::default_attributes()
.with_title("Fantastic window number one!") .with_title("Fantastic window number one!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)); .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0));

View file

@ -459,8 +459,8 @@ impl ApplicationHandler for Application {
info!("Device {device_id:?} event: {event:?}"); info!("Device {device_id:?} event: {event:?}");
} }
fn resumed(&mut self, event_loop: &ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
info!("Resumed the event loop"); info!("Ready to create surfaces");
self.dump_monitors(event_loop); self.dump_monitors(event_loop);
// Create initial window. // Create initial window.

View file

@ -18,7 +18,7 @@ fn main() -> Result<(), Box<dyn Error>> {
} }
impl ApplicationHandler for XEmbedDemo { impl ApplicationHandler for XEmbedDemo {
fn resumed(&mut self, event_loop: &ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
let window_attributes = Window::default_attributes() let window_attributes = Window::default_attributes()
.with_title("An embedded window!") .with_title("An embedded window!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))

View file

@ -18,69 +18,80 @@ pub trait ApplicationHandler {
/// Emitted when the application has been resumed. /// Emitted when the application has been resumed.
/// ///
/// For consistency, all platforms emit a `Resumed` event even if they don't themselves have a /// See [`suspended()`][Self::suspended].
/// formal suspend/resume lifecycle. For systems without a formal suspend/resume lifecycle
/// the `Resumed` event is always emitted after the
/// [`NewEvents(StartCause::Init)`][StartCause::Init] event.
/// ///
/// # Portability /// ## Platform-specific
/// ///
/// It's recommended that applications should only initialize their graphics context and create /// ### iOS
/// a window after they have received their first `Resumed` event. Some systems
/// (specifically Android) won't allow applications to create a render surface until they are
/// resumed.
/// ///
/// Considering that the implementation of [`Suspended`] and `Resumed` events may be internally /// On iOS, the [`resumed()`] method is called in response to an [`applicationDidBecomeActive`]
/// driven by multiple platform-specific events, and that there may be subtle differences across /// callback which means the application is about to transition from the inactive to active
/// platforms with how these internal events are delivered, it's recommended that applications /// state (according to the [iOS application lifecycle]).
/// be able to gracefully handle redundant (i.e. back-to-back) [`Suspended`] or `Resumed`
/// events.
/// ///
/// Also see [`Suspended`] notes. /// [`applicationDidBecomeActive`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive
/// [iOS application lifecycle]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
/// ///
/// ## Android /// ### Web
/// ///
/// On Android, the `Resumed` event is sent when a new [`SurfaceView`] has been created. This is /// On Web, the [`resumed()`] method is called in response to a [`pageshow`] event if the
/// expected to closely correlate with the [`onResume`] lifecycle event but there may /// page is being restored from the [`bfcache`] (back/forward cache) - an in-memory cache
/// technically be a discrepancy. /// that stores a complete snapshot of a page (including the JavaScript heap) as the user is
/// navigating away.
///
/// [`pageshow`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
/// [`bfcache`]: https://web.dev/bfcache/
///
/// ### Others
///
/// **Android / macOS / Orbital / Wayland / Windows / X11:** Unsupported.
///
/// [`resumed()`]: Self::resumed
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
let _ = event_loop;
}
/// Emitted from the point onwards the application should create render surfaces.
///
/// See [`destroy_surfaces()`].
///
/// ## Portability
///
/// It's recommended that applications should only initialize their render surfaces after the
/// [`can_create_surfaces()`] method is called. Some systems (specifically Android) won't allow
/// applications to create a render surface until that point.
///
/// For consistency, all platforms call this method even if they don't themselves have a formal
/// surface destroy/create lifecycle. For systems without a surface destroy/create lifecycle the
/// [`can_create_surfaces()`] event is always emitted after the [`StartCause::Init`] event.
///
/// Applications should be able to gracefully handle back-to-back [`can_create_surfaces()`] and
/// [`destroy_surfaces()`] calls.
///
/// ## Platform-specific
///
/// ### Android
///
/// On Android, the [`can_create_surfaces()`] method is called when a new [`SurfaceView`] has
/// been created. This is expected to closely correlate with the [`onResume`] lifecycle
/// event but there may technically be a discrepancy.
/// ///
/// [`onResume`]: https://developer.android.com/reference/android/app/Activity#onResume() /// [`onResume`]: https://developer.android.com/reference/android/app/Activity#onResume()
/// ///
/// Applications that need to run on Android must wait until they have been `Resumed` /// Applications that need to run on Android must wait until they have been "resumed" before
/// before they will be able to create a render surface (such as an `EGLSurface`, /// they will be able to create a render surface (such as an `EGLSurface`, [`VkSurfaceKHR`]
/// [`VkSurfaceKHR`] or [`wgpu::Surface`]) which depend on having a /// or [`wgpu::Surface`]) which depend on having a [`SurfaceView`]. Applications must also
/// [`SurfaceView`]. Applications must also assume that if they are [`Suspended`], then their /// assume that if they are [suspended], then their render surfaces are invalid and should
/// render surfaces are invalid and should be dropped. /// be dropped.
///
/// Also see [`Suspended`] notes.
/// ///
/// [suspended]: Self::destroy_surfaces
/// [`SurfaceView`]: https://developer.android.com/reference/android/view/SurfaceView /// [`SurfaceView`]: https://developer.android.com/reference/android/view/SurfaceView
/// [Activity lifecycle]: https://developer.android.com/guide/components/activities/activity-lifecycle /// [Activity lifecycle]: https://developer.android.com/guide/components/activities/activity-lifecycle
/// [`VkSurfaceKHR`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkSurfaceKHR.html /// [`VkSurfaceKHR`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkSurfaceKHR.html
/// [`wgpu::Surface`]: https://docs.rs/wgpu/latest/wgpu/struct.Surface.html /// [`wgpu::Surface`]: https://docs.rs/wgpu/latest/wgpu/struct.Surface.html
/// ///
/// ## iOS /// [`can_create_surfaces()`]: Self::can_create_surfaces
/// /// [`destroy_surfaces()`]: Self::destroy_surfaces
/// On iOS, the `Resumed` event is emitted in response to an [`applicationDidBecomeActive`] fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop);
/// callback which means the application is "active" (according to the
/// [iOS application lifecycle]).
///
/// [`applicationDidBecomeActive`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive
/// [iOS application lifecycle]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
///
/// ## Web
///
/// On Web, the `Resumed` event is emitted in response to a [`pageshow`] event
/// with the property [`persisted`] being true, which means that the page is being
/// restored from the [`bfcache`] (back/forward cache) - an in-memory cache that
/// stores a complete snapshot of a page (including the JavaScript heap) as the
/// user is navigating away.
///
/// [`pageshow`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
/// [`persisted`]: https://developer.mozilla.org/en-US/docs/Web/API/PageTransitionEvent/persisted
/// [`bfcache`]: https://web.dev/bfcache/
/// [`Suspended`]: Self::suspended
fn resumed(&mut self, event_loop: &ActiveEventLoop);
/// Called after a wake up is requested using [`EventLoopProxy::wake_up()`]. /// Called after a wake up is requested using [`EventLoopProxy::wake_up()`].
/// ///
@ -121,7 +132,7 @@ pub trait ApplicationHandler {
/// # ) { /// # ) {
/// # } /// # }
/// # /// #
/// # fn resumed(&mut self, _event_loop: &ActiveEventLoop) {} /// # fn can_create_surfaces(&mut self, _event_loop: &ActiveEventLoop) {}
/// # /// #
/// fn proxy_wake_up(&mut self, _event_loop: &ActiveEventLoop) { /// fn proxy_wake_up(&mut self, _event_loop: &ActiveEventLoop) {
/// // Iterate current events, since wake-ups may have been merged. /// // Iterate current events, since wake-ups may have been merged.
@ -208,25 +219,47 @@ pub trait ApplicationHandler {
/// Emitted when the application has been suspended. /// Emitted when the application has been suspended.
/// ///
/// # Portability /// See [`resumed()`][Self::resumed].
/// ///
/// Not all platforms support the notion of suspending applications, and there may be no /// ## Platform-specific
/// technical way to guarantee being able to emit a `Suspended` event if the OS has
/// no formal application lifecycle (currently only Android, iOS, and Web do). For this reason,
/// Winit does not currently try to emit pseudo `Suspended` events before the application
/// quits on platforms without an application lifecycle.
/// ///
/// Considering that the implementation of `Suspended` and [`Resumed`] events may be internally /// ### iOS
/// driven by multiple platform-specific events, and that there may be subtle differences across
/// platforms with how these internal events are delivered, it's recommended that applications
/// be able to gracefully handle redundant (i.e. back-to-back) `Suspended` or [`Resumed`]
/// events.
/// ///
/// Also see [`Resumed`] notes. /// On iOS, the [`suspended()`] method is called in response to an
/// [`applicationWillResignActive`] callback which means that the application is about to
/// transition from the active to inactive state (according to the [iOS application lifecycle]).
/// ///
/// ## Android /// [`applicationWillResignActive`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622950-applicationwillresignactive
/// [iOS application lifecycle]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
/// ///
/// On Android, the `Suspended` event is only sent when the application's associated /// ### Web
///
/// On Web, the [`suspended()`] method is called in response to a [`pagehide`] event if the
/// page is being restored from the [`bfcache`] (back/forward cache) - an in-memory cache that
/// stores a complete snapshot of a page (including the JavaScript heap) as the user is
/// navigating away.
///
/// [`pagehide`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event
/// [`bfcache`]: https://web.dev/bfcache/
///
/// ### Others
///
/// **Android / macOS / Orbital / Wayland / Windows / X11:** Unsupported.
///
/// [`suspended()`]: Self::suspended
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
let _ = event_loop;
}
/// Emitted when the application must destroy its render surfaces.
///
/// See [`can_create_surfaces()`] for more details.
///
/// ## Platform-specific
///
/// ### Android
///
/// On Android, the [`destroy_surfaces()`] method is called when the application's associated
/// [`SurfaceView`] is destroyed. This is expected to closely correlate with the [`onPause`] /// [`SurfaceView`] is destroyed. This is expected to closely correlate with the [`onPause`]
/// lifecycle event but there may technically be a discrepancy. /// lifecycle event but there may technically be a discrepancy.
/// ///
@ -236,38 +269,24 @@ pub trait ApplicationHandler {
/// destroyed, which indirectly invalidates any existing render surfaces that may have been /// destroyed, which indirectly invalidates any existing render surfaces that may have been
/// created outside of Winit (such as an `EGLSurface`, [`VkSurfaceKHR`] or [`wgpu::Surface`]). /// created outside of Winit (such as an `EGLSurface`, [`VkSurfaceKHR`] or [`wgpu::Surface`]).
/// ///
/// After being `Suspended` on Android applications must drop all render surfaces before /// After being [suspended] on Android applications must drop all render surfaces before
/// the event callback completes, which may be re-created when the application is next /// the event callback completes, which may be re-created when the application is next
/// [`Resumed`]. /// [resumed].
/// ///
/// [suspended]: Self::destroy_surfaces
/// [resumed]: Self::can_create_surfaces
/// [`SurfaceView`]: https://developer.android.com/reference/android/view/SurfaceView /// [`SurfaceView`]: https://developer.android.com/reference/android/view/SurfaceView
/// [Activity lifecycle]: https://developer.android.com/guide/components/activities/activity-lifecycle /// [Activity lifecycle]: https://developer.android.com/guide/components/activities/activity-lifecycle
/// [`VkSurfaceKHR`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkSurfaceKHR.html /// [`VkSurfaceKHR`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkSurfaceKHR.html
/// [`wgpu::Surface`]: https://docs.rs/wgpu/latest/wgpu/struct.Surface.html /// [`wgpu::Surface`]: https://docs.rs/wgpu/latest/wgpu/struct.Surface.html
/// ///
/// ## iOS /// ### Others
/// ///
/// On iOS, the `Suspended` event is currently emitted in response to an /// - **iOS / macOS / Orbital / Wayland / Web / Windows / X11:** Unsupported.
/// [`applicationWillResignActive`] callback which means that the application is
/// about to transition from the active to inactive state (according to the
/// [iOS application lifecycle]).
/// ///
/// [`applicationWillResignActive`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622950-applicationwillresignactive /// [`can_create_surfaces()`]: Self::can_create_surfaces
/// [iOS application lifecycle]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle /// [`destroy_surfaces()`]: Self::destroy_surfaces
/// fn destroy_surfaces(&mut self, event_loop: &ActiveEventLoop) {
/// ## Web
///
/// On Web, the `Suspended` event is emitted in response to a [`pagehide`] event
/// with the property [`persisted`] being true, which means that the page is being
/// put in the [`bfcache`] (back/forward cache) - an in-memory cache that stores a
/// complete snapshot of a page (including the JavaScript heap) as the user is
/// navigating away.
///
/// [`pagehide`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event
/// [`persisted`]: https://developer.mozilla.org/en-US/docs/Web/API/PageTransitionEvent/persisted
/// [`bfcache`]: https://web.dev/bfcache/
/// [`Resumed`]: Self::resumed
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
let _ = event_loop; let _ = event_loop;
} }
@ -308,6 +327,7 @@ pub trait ApplicationHandler {
} }
} }
#[deny(clippy::missing_trait_methods)]
impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A { impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
#[inline] #[inline]
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) { fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
@ -319,6 +339,11 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
(**self).resumed(event_loop); (**self).resumed(event_loop);
} }
#[inline]
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
(**self).can_create_surfaces(event_loop);
}
#[inline] #[inline]
fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) { fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) {
(**self).proxy_wake_up(event_loop); (**self).proxy_wake_up(event_loop);
@ -354,6 +379,11 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
(**self).suspended(event_loop); (**self).suspended(event_loop);
} }
#[inline]
fn destroy_surfaces(&mut self, event_loop: &ActiveEventLoop) {
(**self).destroy_surfaces(event_loop);
}
#[inline] #[inline]
fn exiting(&mut self, event_loop: &ActiveEventLoop) { fn exiting(&mut self, event_loop: &ActiveEventLoop) {
(**self).exiting(event_loop); (**self).exiting(event_loop);
@ -365,6 +395,7 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
} }
} }
#[deny(clippy::missing_trait_methods)]
impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> { impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> {
#[inline] #[inline]
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) { fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
@ -376,6 +407,11 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> {
(**self).resumed(event_loop); (**self).resumed(event_loop);
} }
#[inline]
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
(**self).can_create_surfaces(event_loop);
}
#[inline] #[inline]
fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) { fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) {
(**self).proxy_wake_up(event_loop); (**self).proxy_wake_up(event_loop);
@ -411,6 +447,11 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> {
(**self).suspended(event_loop); (**self).suspended(event_loop);
} }
#[inline]
fn destroy_surfaces(&mut self, event_loop: &ActiveEventLoop) {
(**self).destroy_surfaces(event_loop);
}
#[inline] #[inline]
fn exiting(&mut self, event_loop: &ActiveEventLoop) { fn exiting(&mut self, event_loop: &ActiveEventLoop) {
(**self).exiting(event_loop); (**self).exiting(event_loop);

View file

@ -57,6 +57,14 @@ changelog entry.
- Changed `EventLoopProxy::send_event` to `EventLoopProxy::wake_up`, it now - Changed `EventLoopProxy::send_event` to `EventLoopProxy::wake_up`, it now
only wakes up the loop. only wakes up the loop.
- On Web, slightly improve accuracy of `DeviceEvent::MouseMotion`. - On Web, slightly improve accuracy of `DeviceEvent::MouseMotion`.
- `ApplicationHandler::create|destroy_surfaces()` was split off from
`ApplicationHandler::resumed/suspended()`.
`ApplicationHandler::can_create_surfaces()` should, for portability reasons
to Android, be the only place to create render surfaces.
`ApplicationHandler::resumed/suspended()` are now only emitted by iOS and Web
and now signify actually resuming/suspending the application.
### Removed ### Removed

View file

@ -85,6 +85,11 @@ pub(crate) enum Event {
/// [`ApplicationHandler::suspended`]: crate::application::ApplicationHandler::suspended /// [`ApplicationHandler::suspended`]: crate::application::ApplicationHandler::suspended
Suspended, Suspended,
/// See [`ApplicationHandler::can_create_surfaces`] for details.
///
/// [`ApplicationHandler::can_create_surfaces`]: crate::application::ApplicationHandler::can_create_surfaces
CreateSurfaces,
/// See [`ApplicationHandler::resumed`] for details. /// See [`ApplicationHandler::resumed`] for details.
/// ///
/// [`ApplicationHandler::resumed`]: crate::application::ApplicationHandler::resumed /// [`ApplicationHandler::resumed`]: crate::application::ApplicationHandler::resumed

View file

@ -52,7 +52,7 @@
//! } //! }
//! //!
//! impl ApplicationHandler for App { //! impl ApplicationHandler for App {
//! fn resumed(&mut self, event_loop: &ActiveEventLoop) { //! fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
//! self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap()); //! self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap());
//! } //! }
//! //!

View file

@ -176,10 +176,10 @@ impl EventLoop {
match event { match event {
MainEvent::InitWindow { .. } => { MainEvent::InitWindow { .. } => {
app.resumed(self.window_target()); app.can_create_surfaces(self.window_target());
}, },
MainEvent::TerminateWindow { .. } => { MainEvent::TerminateWindow { .. } => {
app.suspended(self.window_target()); app.destroy_surfaces(self.window_target());
}, },
MainEvent::WindowResized { .. } => resized = true, MainEvent::WindowResized { .. } => resized = true,
MainEvent::RedrawNeeded { .. } => pending_redraw = true, MainEvent::RedrawNeeded { .. } => pending_redraw = true,

View file

@ -314,9 +314,9 @@ impl ApplicationDelegate {
/// dispatch `NewEvents(Init)` + `Resumed` /// dispatch `NewEvents(Init)` + `Resumed`
pub fn dispatch_init_events(&self) { pub fn dispatch_init_events(&self) {
self.with_handler(|app, event_loop| app.new_events(event_loop, StartCause::Init)); self.with_handler(|app, event_loop| app.new_events(event_loop, StartCause::Init));
// NB: For consistency all platforms must emit a 'resumed' event even though macOS // NB: For consistency all platforms must call `can_create_surfaces` even though macOS
// applications don't themselves have a formal suspend/resume lifecycle. // applications don't themselves have a formal surface destroy/create lifecycle.
self.with_handler(|app, event_loop| app.resumed(event_loop)); self.with_handler(|app, event_loop| app.can_create_surfaces(event_loop));
} }
// Called by RunLoopObserver after finishing waiting for new events // Called by RunLoopObserver after finishing waiting for new events

View file

@ -496,8 +496,12 @@ pub fn did_finish_launching(mtm: MainThreadMarker) {
let (windows, events) = AppState::get_mut(mtm).did_finish_launching_transition(); let (windows, events) = AppState::get_mut(mtm).did_finish_launching_transition();
let events = std::iter::once(EventWrapper::StaticEvent(Event::NewEvents(StartCause::Init))) let events = [
.chain(events); EventWrapper::StaticEvent(Event::NewEvents(StartCause::Init)),
EventWrapper::StaticEvent(Event::CreateSurfaces),
]
.into_iter()
.chain(events);
handle_nonuser_events(mtm, events); handle_nonuser_events(mtm, events);
// the above window dance hack, could possibly trigger new windows to be created. // the above window dance hack, could possibly trigger new windows to be created.

View file

@ -130,6 +130,7 @@ fn map_user_event<A: ApplicationHandler>(
}, },
Event::Suspended => app.suspended(window_target), Event::Suspended => app.suspended(window_target),
Event::Resumed => app.resumed(window_target), Event::Resumed => app.resumed(window_target),
Event::CreateSurfaces => app.can_create_surfaces(window_target),
Event::AboutToWait => app.about_to_wait(window_target), Event::AboutToWait => app.about_to_wait(window_target),
Event::LoopExiting => app.exiting(window_target), Event::LoopExiting => app.exiting(window_target),
Event::MemoryWarning => app.memory_warning(window_target), Event::MemoryWarning => app.memory_warning(window_target),

View file

@ -301,10 +301,10 @@ impl EventLoop {
app.new_events(&self.window_target, cause); app.new_events(&self.window_target, cause);
// NB: For consistency all platforms must emit a 'resumed' event even though Wayland // NB: For consistency all platforms must call `can_create_surfaces` even though Wayland
// applications don't themselves have a formal suspend/resume lifecycle. // applications don't themselves have a formal surface destroy/create lifecycle.
if cause == StartCause::Init { if cause == StartCause::Init {
app.resumed(&self.window_target); app.can_create_surfaces(&self.window_target);
} }
// Indicate user wake up. // Indicate user wake up.

View file

@ -505,10 +505,10 @@ impl EventLoop {
fn single_iteration<A: ApplicationHandler>(&mut self, app: &mut A, cause: StartCause) { fn single_iteration<A: ApplicationHandler>(&mut self, app: &mut A, cause: StartCause) {
app.new_events(&self.event_processor.target, cause); app.new_events(&self.event_processor.target, cause);
// NB: For consistency all platforms must emit a 'resumed' event even though X11 // NB: For consistency all platforms must call `can_create_surfaces` even though X11
// applications don't themselves have a formal suspend/resume lifecycle. // applications don't themselves have a formal surface destroy/create lifecycle.
if cause == StartCause::Init { if cause == StartCause::Init {
app.resumed(&self.event_processor.target) app.can_create_surfaces(&self.event_processor.target)
} }
// Process all pending events // Process all pending events

View file

@ -507,7 +507,7 @@ impl EventLoop {
app.new_events(&self.window_target, start_cause); app.new_events(&self.window_target, start_cause);
if start_cause == StartCause::Init { if start_cause == StartCause::Init {
app.resumed(&self.window_target); app.can_create_surfaces(&self.window_target);
} }
// Handle window creates. // Handle window creates.

View file

@ -87,6 +87,7 @@ fn handle_event<A: ApplicationHandler>(app: &mut A, target: &RootActiveEventLoop
Event::UserWakeUp => app.proxy_wake_up(target), Event::UserWakeUp => app.proxy_wake_up(target),
Event::Suspended => app.suspended(target), Event::Suspended => app.suspended(target),
Event::Resumed => app.resumed(target), Event::Resumed => app.resumed(target),
Event::CreateSurfaces => app.can_create_surfaces(target),
Event::AboutToWait => app.about_to_wait(target), Event::AboutToWait => app.about_to_wait(target),
Event::LoopExiting => app.exiting(target), Event::LoopExiting => app.exiting(target),
Event::MemoryWarning => app.memory_warning(target), Event::MemoryWarning => app.memory_warning(target),

View file

@ -441,9 +441,11 @@ impl Shared {
} }
pub fn init(&self) { pub fn init(&self) {
// NB: For consistency all platforms must emit a 'resumed' event even though web // NB: For consistency all platforms must call `can_create_surfaces` even though web
// applications don't themselves have a formal suspend/resume lifecycle. // applications don't themselves have a formal surface destroy/create lifecycle.
self.run_until_cleared([Event::NewEvents(StartCause::Init), Event::Resumed].into_iter()); self.run_until_cleared(
[Event::NewEvents(StartCause::Init), Event::CreateSurfaces].into_iter(),
);
} }
// Run the polling logic for the Poll ControlFlow, which involves clearing the queue // Run the polling logic for the Poll ControlFlow, which involves clearing the queue

View file

@ -216,6 +216,7 @@ impl EventLoop {
Event::UserWakeUp => app.proxy_wake_up(event_loop_windows_ref), Event::UserWakeUp => app.proxy_wake_up(event_loop_windows_ref),
Event::Suspended => app.suspended(event_loop_windows_ref), Event::Suspended => app.suspended(event_loop_windows_ref),
Event::Resumed => app.resumed(event_loop_windows_ref), Event::Resumed => app.resumed(event_loop_windows_ref),
Event::CreateSurfaces => app.can_create_surfaces(event_loop_windows_ref),
Event::AboutToWait => app.about_to_wait(event_loop_windows_ref), Event::AboutToWait => app.about_to_wait(event_loop_windows_ref),
Event::LoopExiting => app.exiting(event_loop_windows_ref), Event::LoopExiting => app.exiting(event_loop_windows_ref),
Event::MemoryWarning => app.memory_warning(event_loop_windows_ref), Event::MemoryWarning => app.memory_warning(event_loop_windows_ref),
@ -281,6 +282,7 @@ impl EventLoop {
Event::UserWakeUp => app.proxy_wake_up(event_loop_windows_ref), Event::UserWakeUp => app.proxy_wake_up(event_loop_windows_ref),
Event::Suspended => app.suspended(event_loop_windows_ref), Event::Suspended => app.suspended(event_loop_windows_ref),
Event::Resumed => app.resumed(event_loop_windows_ref), Event::Resumed => app.resumed(event_loop_windows_ref),
Event::CreateSurfaces => app.can_create_surfaces(event_loop_windows_ref),
Event::AboutToWait => app.about_to_wait(event_loop_windows_ref), Event::AboutToWait => app.about_to_wait(event_loop_windows_ref),
Event::LoopExiting => app.exiting(event_loop_windows_ref), Event::LoopExiting => app.exiting(event_loop_windows_ref),
Event::MemoryWarning => app.memory_warning(event_loop_windows_ref), Event::MemoryWarning => app.memory_warning(event_loop_windows_ref),

View file

@ -345,10 +345,10 @@ impl EventLoopRunner {
}, },
}; };
self.call_event_handler(Event::NewEvents(start_cause)); self.call_event_handler(Event::NewEvents(start_cause));
// NB: For consistency all platforms must emit a 'resumed' event even though Windows // NB: For consistency all platforms must call `can_create_surfaces` even though Windows
// applications don't themselves have a formal suspend/resume lifecycle. // applications don't themselves have a formal surface destroy/create lifecycle.
if init { if init {
self.call_event_handler(Event::Resumed); self.call_event_handler(Event::CreateSurfaces);
} }
self.dispatch_buffered_events(); self.dispatch_buffered_events();
} }