diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 356cf1b76b..f196923ad8 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -1007,6 +1007,22 @@ impl Context for AppContext { let entity = self.entities.read(handle); read(entity, self) } + + fn read_window( + &self, + window: &AnyWindowHandle, + read: impl FnOnce(AnyView, &AppContext) -> R, + ) -> Result { + let window = self + .windows + .get(window.id) + .ok_or_else(|| anyhow!("window not found"))? + .as_ref() + .unwrap(); + + let root_view = window.root_view.clone().unwrap(); + Ok(read(root_view, self)) + } } /// These effects are processed at the end of each application update cycle. diff --git a/crates/gpui2/src/app/async_context.rs b/crates/gpui2/src/app/async_context.rs index e191e7315f..b9eeacb262 100644 --- a/crates/gpui2/src/app/async_context.rs +++ b/crates/gpui2/src/app/async_context.rs @@ -66,6 +66,16 @@ impl Context for AsyncAppContext { let mut lock = app.borrow_mut(); lock.update_window(window, f) } + + fn read_window( + &self, + window: &AnyWindowHandle, + read: impl FnOnce(AnyView, &AppContext) -> R, + ) -> Result { + let app = self.app.upgrade().context("app was released")?; + let lock = app.borrow(); + lock.read_window(window, read) + } } impl AsyncAppContext { @@ -250,6 +260,14 @@ impl Context for AsyncWindowContext { { self.app.read_model(handle, read) } + + fn read_window( + &self, + window: &AnyWindowHandle, + read: impl FnOnce(AnyView, &AppContext) -> R, + ) -> Result { + self.app.read_window(window, read) + } } impl VisualContext for AsyncWindowContext { diff --git a/crates/gpui2/src/app/model_context.rs b/crates/gpui2/src/app/model_context.rs index 44a3337f03..1fe9a09ba7 100644 --- a/crates/gpui2/src/app/model_context.rs +++ b/crates/gpui2/src/app/model_context.rs @@ -239,6 +239,14 @@ impl<'a, T> Context for ModelContext<'a, T> { { self.app.read_model(handle, read) } + + fn read_window( + &self, + window: &AnyWindowHandle, + read: impl FnOnce(AnyView, &AppContext) -> R, + ) -> Result { + self.app.read_window(window, read) + } } impl Borrow for ModelContext<'_, T> { diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index 7b5ab5f7d7..f8d5c01160 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -58,6 +58,15 @@ impl Context for TestAppContext { let app = self.app.borrow(); app.read_model(handle, read) } + + fn read_window( + &self, + window: &AnyWindowHandle, + read: impl FnOnce(AnyView, &AppContext) -> R, + ) -> Result { + let app = self.app.borrow(); + app.read_window(window, read) + } } impl TestAppContext { @@ -146,6 +155,11 @@ impl TestAppContext { Some(read(lock.try_global()?, &lock)) } + pub fn set_global(&mut self, global: G) { + let mut lock = self.app.borrow_mut(); + lock.set_global(global); + } + pub fn update_global( &mut self, update: impl FnOnce(&mut G, &mut AppContext) -> R, diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index 79275005d2..ff150824b1 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -104,6 +104,12 @@ pub trait Context { fn update_window(&mut self, window: AnyWindowHandle, f: F) -> Result where F: FnOnce(AnyView, &mut WindowContext<'_>) -> T; + + fn read_window( + &self, + window: &AnyWindowHandle, + read: impl FnOnce(AnyView, &AppContext) -> R, + ) -> Result; } pub trait VisualContext: Context { diff --git a/crates/gpui2/src/input.rs b/crates/gpui2/src/input.rs index d768ce946a..140f724417 100644 --- a/crates/gpui2/src/input.rs +++ b/crates/gpui2/src/input.rs @@ -45,7 +45,7 @@ impl ElementInputHandler { /// containing view. pub fn new(element_bounds: Bounds, cx: &mut ViewContext) -> Self { ElementInputHandler { - view: cx.view(), + view: cx.view().clone(), element_bounds, cx: cx.to_async(), } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index ac7dcf0256..a9d2d55453 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1428,6 +1428,19 @@ impl Context for WindowContext<'_> { let entity = self.entities.read(handle); read(&*entity, &*self.app) } + + fn read_window( + &self, + window: &AnyWindowHandle, + read: impl FnOnce(AnyView, &AppContext) -> R, + ) -> Result { + if window == &self.window.handle { + let root_view = self.window.root_view.clone().unwrap(); + Ok(read(root_view, self)) + } else { + window.read(self.app, read) + } + } } impl VisualContext for WindowContext<'_> { @@ -1747,9 +1760,8 @@ impl<'a, V: 'static> ViewContext<'a, V> { } } - // todo!("change this to return a reference"); - pub fn view(&self) -> View { - self.view.clone() + pub fn view(&self) -> &View { + self.view } pub fn model(&self) -> Model { @@ -1772,7 +1784,7 @@ impl<'a, V: 'static> ViewContext<'a, V> { where V: 'static, { - let view = self.view(); + let view = self.view().clone(); self.window_cx.on_next_frame(move |cx| view.update(cx, f)); } @@ -2170,7 +2182,7 @@ impl<'a, V: 'static> ViewContext<'a, V> { &mut self, handler: impl Fn(&mut V, &Event, DispatchPhase, &mut ViewContext) + 'static, ) { - let handle = self.view(); + let handle = self.view().clone(); self.window_cx.on_mouse_event(move |event, phase, cx| { handle.update(cx, |view, cx| { handler(view, event, phase, cx); @@ -2244,6 +2256,14 @@ impl Context for ViewContext<'_, V> { { self.window_cx.read_model(handle, read) } + + fn read_window( + &self, + window: &AnyWindowHandle, + read: impl FnOnce(AnyView, &AppContext) -> R, + ) -> Result { + self.window_cx.read_window(window, read) + } } impl VisualContext for ViewContext<'_, V> { @@ -2315,6 +2335,14 @@ impl WindowHandle { } } + pub fn root(&self, cx: &C) -> Result> { + cx.read_window(&self.any_handle, |root_view, _| { + root_view + .downcast::() + .map_err(|_| anyhow!("the type of the window's root view has changed")) + })? + } + pub fn update( self, cx: &mut C, @@ -2395,6 +2423,13 @@ impl AnyWindowHandle { { cx.update_window(self, update) } + + pub fn read(self, cx: &C, read: impl FnOnce(AnyView, &AppContext) -> R) -> Result + where + C: Context, + { + cx.read_window(&self, read) + } } #[cfg(any(test, feature = "test-support"))]