Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow non-static eframe::App lifetime #5060

Merged
merged 4 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion crates/eframe/src/epi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ type DynError = Box<dyn std::error::Error + Send + Sync>;
/// This is how your app is created.
///
/// You can use the [`CreationContext`] to setup egui, restore state, setup OpenGL things, etc.
pub type AppCreator = Box<dyn FnOnce(&CreationContext<'_>) -> Result<Box<dyn App>, DynError>>;
pub type AppCreator<'app> =
Box<dyn 'app + FnOnce(&CreationContext<'_>) -> Result<Box<dyn 'app + App>, DynError>>;

/// Data that is passed to [`AppCreator`] that can be used to setup and initialize your app.
pub struct CreationContext<'s> {
Expand Down
2 changes: 1 addition & 1 deletion crates/eframe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ pub mod icon_data;
pub fn run_native(
app_name: &str,
mut native_options: NativeOptions,
app_creator: AppCreator,
app_creator: AppCreator<'_>,
) -> Result {
#[cfg(not(feature = "__screenshot"))]
assert!(
Expand Down
25 changes: 14 additions & 11 deletions crates/eframe/src/native/glow_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,24 @@ use super::{
// ----------------------------------------------------------------------------
// Types:

pub struct GlowWinitApp {
pub struct GlowWinitApp<'app> {
repaint_proxy: Arc<egui::mutex::Mutex<EventLoopProxy<UserEvent>>>,
app_name: String,
native_options: NativeOptions,
running: Option<GlowWinitRunning>,
running: Option<GlowWinitRunning<'app>>,

// Note that since this `AppCreator` is FnOnce we are currently unable to support
// re-initializing the `GlowWinitRunning` state on Android if the application
// suspends and resumes.
app_creator: Option<AppCreator>,
app_creator: Option<AppCreator<'app>>,
}

/// State that is initialized when the application is first starts running via
/// a Resumed event. On Android this ensures that any graphics state is only
/// initialized once the application has an associated `SurfaceView`.
struct GlowWinitRunning {
struct GlowWinitRunning<'app> {
integration: EpiIntegration,
app: Box<dyn App>,
app: Box<dyn 'app + App>,

// These needs to be shared with the immediate viewport renderer, hence the Rc/Arc/RefCells:
glutin: Rc<RefCell<GlutinWindowContext>>,
Expand Down Expand Up @@ -126,12 +126,12 @@ struct Viewport {

// ----------------------------------------------------------------------------

impl GlowWinitApp {
impl<'app> GlowWinitApp<'app> {
pub fn new(
event_loop: &EventLoop<UserEvent>,
app_name: &str,
native_options: NativeOptions,
app_creator: AppCreator,
app_creator: AppCreator<'app>,
) -> Self {
crate::profile_function!();
Self {
Expand Down Expand Up @@ -195,7 +195,10 @@ impl GlowWinitApp {
Ok((glutin_window_context, painter))
}

fn init_run_state(&mut self, event_loop: &ActiveEventLoop) -> Result<&mut GlowWinitRunning> {
fn init_run_state(
&mut self,
event_loop: &ActiveEventLoop,
) -> Result<&mut GlowWinitRunning<'app>> {
crate::profile_function!();

let storage = if let Some(file) = &self.native_options.persistence_path {
Expand Down Expand Up @@ -292,7 +295,7 @@ impl GlowWinitApp {
let app_creator = std::mem::take(&mut self.app_creator)
.expect("Single-use AppCreator has unexpectedly already been taken");

let app = {
let app: Box<dyn 'app + App> = {
// Use latest raw_window_handle for eframe compatibility
use raw_window_handle::{HasDisplayHandle as _, HasWindowHandle as _};

Expand Down Expand Up @@ -346,7 +349,7 @@ impl GlowWinitApp {
}
}

impl WinitApp for GlowWinitApp {
impl<'app> WinitApp for GlowWinitApp<'app> {
fn frame_nr(&self, viewport_id: ViewportId) -> u64 {
self.running
.as_ref()
Expand Down Expand Up @@ -483,7 +486,7 @@ impl WinitApp for GlowWinitApp {
}
}

impl GlowWinitRunning {
impl<'app> GlowWinitRunning<'app> {
fn run_ui_and_paint(
&mut self,
event_loop: &ActiveEventLoop,
Expand Down
6 changes: 3 additions & 3 deletions crates/eframe/src/native/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ fn run_and_return(event_loop: &mut EventLoop<UserEvent>, winit_app: impl WinitAp
app.return_result
}

fn run_and_exit(event_loop: EventLoop<UserEvent>, winit_app: impl WinitApp + 'static) -> Result {
fn run_and_exit(event_loop: EventLoop<UserEvent>, winit_app: impl WinitApp) -> Result {
log::trace!("Entering the winit event loop (run_app)…");

// When to repaint what window
Expand All @@ -314,7 +314,7 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, winit_app: impl WinitApp + 'st
pub fn run_glow(
app_name: &str,
mut native_options: epi::NativeOptions,
app_creator: epi::AppCreator,
app_creator: epi::AppCreator<'_>,
) -> Result {
#![allow(clippy::needless_return_with_question_mark)] // False positive

Expand All @@ -339,7 +339,7 @@ pub fn run_glow(
pub fn run_wgpu(
app_name: &str,
mut native_options: epi::NativeOptions,
app_creator: epi::AppCreator,
app_creator: epi::AppCreator<'_>,
) -> Result {
#![allow(clippy::needless_return_with_question_mark)] // False positive

Expand Down
22 changes: 11 additions & 11 deletions crates/eframe/src/native/wgpu_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,26 @@ use super::{epi_integration, event_loop_context, winit_integration, winit_integr
// ----------------------------------------------------------------------------
// Types:

pub struct WgpuWinitApp {
pub struct WgpuWinitApp<'app> {
repaint_proxy: Arc<Mutex<EventLoopProxy<UserEvent>>>,
app_name: String,
native_options: NativeOptions,

/// Set at initialization, then taken and set to `None` in `init_run_state`.
app_creator: Option<AppCreator>,
app_creator: Option<AppCreator<'app>>,

/// Set when we are actually up and running.
running: Option<WgpuWinitRunning>,
running: Option<WgpuWinitRunning<'app>>,
}

/// State that is initialized when the application is first starts running via
/// a Resumed event. On Android this ensures that any graphics state is only
/// initialized once the application has an associated `SurfaceView`.
struct WgpuWinitRunning {
struct WgpuWinitRunning<'app> {
integration: EpiIntegration,

/// The users application.
app: Box<dyn App>,
app: Box<dyn 'app + App>,

/// Wrapped in an `Rc<RefCell<…>>` so it can be re-entrantly shared via a weak-pointer.
shared: Rc<RefCell<SharedState>>,
Expand Down Expand Up @@ -95,12 +95,12 @@ pub struct Viewport {

// ----------------------------------------------------------------------------

impl WgpuWinitApp {
impl<'app> WgpuWinitApp<'app> {
pub fn new(
event_loop: &EventLoop<UserEvent>,
app_name: &str,
native_options: NativeOptions,
app_creator: AppCreator,
app_creator: AppCreator<'app>,
) -> Self {
crate::profile_function!();

Expand Down Expand Up @@ -143,7 +143,7 @@ impl WgpuWinitApp {
}

#[cfg(target_os = "android")]
fn recreate_window(&self, event_loop: &ActiveEventLoop, running: &WgpuWinitRunning) {
fn recreate_window(&self, event_loop: &ActiveEventLoop, running: &WgpuWinitRunning<'app>) {
let SharedState {
egui_ctx,
viewports,
Expand Down Expand Up @@ -180,7 +180,7 @@ impl WgpuWinitApp {
storage: Option<Box<dyn Storage>>,
window: Window,
builder: ViewportBuilder,
) -> crate::Result<&mut WgpuWinitRunning> {
) -> crate::Result<&mut WgpuWinitRunning<'app>> {
crate::profile_function!();

#[allow(unsafe_code, unused_mut, unused_unsafe)]
Expand Down Expand Up @@ -323,7 +323,7 @@ impl WgpuWinitApp {
}
}

impl WinitApp for WgpuWinitApp {
impl<'app> WinitApp for WgpuWinitApp<'app> {
fn frame_nr(&self, viewport_id: ViewportId) -> u64 {
self.running
.as_ref()
Expand Down Expand Up @@ -489,7 +489,7 @@ impl WinitApp for WgpuWinitApp {
}
}

impl WgpuWinitRunning {
impl<'app> WgpuWinitRunning<'app> {
fn save_and_destroy(&mut self) {
crate::profile_function!();

Expand Down
2 changes: 1 addition & 1 deletion crates/eframe/src/web/app_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl AppRunner {
pub async fn new(
canvas: web_sys::HtmlCanvasElement,
web_options: crate::WebOptions,
app_creator: epi::AppCreator,
app_creator: epi::AppCreator<'static>,
text_agent: TextAgent,
) -> Result<Self, String> {
let painter = super::ActiveWebPainter::new(canvas, &web_options).await?;
Expand Down
2 changes: 1 addition & 1 deletion crates/eframe/src/web/web_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl WebRunner {
&self,
canvas: web_sys::HtmlCanvasElement,
web_options: crate::WebOptions,
app_creator: epi::AppCreator,
app_creator: epi::AppCreator<'static>,
) -> Result<(), JsValue> {
self.destroy();

Expand Down
Loading