gpui: Add run_embedded and ApplicationHandle for externally driven run loops (#60574)
On ordinary platforms, `Platform::run` blocks for the lifetime of the app, and `Application::run`'s stack frame keeps the app state alive. Embedded platforms invert that: the run loop belongs to someone else. `Application::run_embedded` supports that shape: it starts the app exactly like `run()`, but returns an `ApplicationHandle` holding the strong app handle. Release Notes: - N/A
This commit is contained in:
1 parent
883bb315fd
commit
244a8d349c
1 file changed
+47
@@ -143,6 +143,31 @@ impl Drop for AppRefMut<'_> {
|
||||
/// You won't interact with this type much outside of initial configuration and startup.
|
||||
pub struct Application(Rc<AppCell>);
|
||||
|
||||
/// A strong handle to an [`Application`] started with [`Application::run_embedded`].
|
||||
///
|
||||
/// Dropping this handle releases the app, so an embedder must hold it for as long as the
|
||||
/// app should run. While held, it is the embedder's entry point back into GPUI each time
|
||||
/// the external run loop gives it control.
|
||||
pub struct ApplicationHandle {
|
||||
app: Rc<AppCell>,
|
||||
}
|
||||
|
||||
impl ApplicationHandle {
|
||||
/// Invoke `f` with the app context. Must not be called re-entrantly from code that
|
||||
/// is already inside an update; the app state is a `RefCell` and will panic on a
|
||||
/// double borrow.
|
||||
pub fn update<R>(&self, f: impl FnOnce(&mut App) -> R) -> R {
|
||||
let cx = &mut *self.app.borrow_mut();
|
||||
f(cx)
|
||||
}
|
||||
|
||||
/// An [`AsyncApp`] for use across await points. It holds the app weakly; keeping the
|
||||
/// app alive remains this handle's job.
|
||||
pub fn to_async(&self) -> AsyncApp {
|
||||
self.update(|cx| cx.to_async())
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an application before it is fully launched. Once your app is
|
||||
/// configured, you'll start the app with `App::run`.
|
||||
impl Application {
|
||||
@@ -209,6 +234,28 @@ impl Application {
|
||||
}));
|
||||
}
|
||||
|
||||
/// Start the application for an embedder that drives the run loop itself.
|
||||
///
|
||||
/// On ordinary platforms `Platform::run` blocks for the lifetime of the app, and the
|
||||
/// app state is kept alive by [`Application::run`]'s stack frame. Embedded platforms —
|
||||
/// where the run loop belongs to someone else, e.g. GPUI compiled into a Wasm guest,
|
||||
/// or a GPUI view hosted inside a foreign native application — implement
|
||||
/// `Platform::run` to invoke the launch callback and return immediately. This method
|
||||
/// supports that shape: it returns an [`ApplicationHandle`] that keeps the app alive
|
||||
/// and lets the embedder re-enter it whenever the external run loop yields control.
|
||||
pub fn run_embedded<F>(self, on_finish_launching: F) -> ApplicationHandle
|
||||
where
|
||||
F: 'static + FnOnce(&mut App),
|
||||
{
|
||||
let this = self.0.clone();
|
||||
let platform = self.0.borrow().platform.clone();
|
||||
platform.run(Box::new(move || {
|
||||
let cx = &mut *this.borrow_mut();
|
||||
on_finish_launching(cx);
|
||||
}));
|
||||
ApplicationHandle { app: self.0 }
|
||||
}
|
||||
|
||||
/// Register a handler to be invoked when the platform instructs the application
|
||||
/// to open one or more URLs.
|
||||
pub fn on_open_urls<F>(&self, mut callback: F) -> &Self
|
||||
|
||||
Reference in new issue
Block a user